# Device Badge

Device Badge [#device-badge]

The **Device Badge** surfaces a browser AI capability — WebGPU, WASM, or IndexedDB storage — as a themed status pill. It reads the device's capabilities via the copy-owned `useCapabilities()` hook (from the `@localmode/ui/lib/use-environment` lib, installed automatically) and shows green when the capability is available, amber when it is not, and a pulsing muted dot while detection is in flight.

**When to use it:** gate a model-download UI behind device support (e.g. "WebGPU available → offer the fast WebGPU model; otherwise fall back to WASM"), or show users why a feature is or isn't available on their device.

Preview [#preview]

```tsx
'use client';

import { DeviceBadge } from '@/components/device-badge';

/**
 * Demo for the DeviceBadge component, used by the docs live preview.
 * Shows all three capability variants side by side. Detection runs in the
 * browser only after the preview is activated (Run-gated).
 */
export default function DeviceBadgeDemo() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <DeviceBadge capability="webgpu" />
      <DeviceBadge capability="wasm" />
      <DeviceBadge capability="storage" />
      <DeviceBadge capability="webgpu" compact />
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/local-first/device-badge
```

Dependencies [#dependencies]

**Data source:** detects capabilities entirely in the browser — no backend, no model download. Capability detection is provided by the copy-owned `@localmode/ui/lib/use-environment` lib (`useCapabilities`, `detectCapabilities`), installed automatically as a registry dependency, so the component is portable to any React app.

* `@localmode/ui/lib/use-environment` — the copy-owned `useCapabilities()` hook + `detectCapabilities()` (installed automatically as a registry dependency)
* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `device-badge.tsx` — the component
* `lib/use-environment.ts` — the copy-owned capability hooks (if not already present)
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**DeviceBadge**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `capability` | `"storage" \| "wasm" \| "webgpu"` | `"webgpu"` | Which capability to surface. `webgpu` reports GPU acceleration availability; `wasm` reports WebAssembly support; `storage` reports IndexedDB persistence. |
| `label` | `string` | — | Label shown before the status. Defaults to a human-readable capability name. |
| `compact` | `boolean` | `false` | When true, render a compact dot-only badge without the text label. |

Examples [#examples]

Default (WebGPU) [#default-webgpu]

```tsx
import { DeviceBadge } from '@/components/device-badge';

export function Example() {
  return <DeviceBadge />;
}
```

Gate a model choice [#gate-a-model-choice]

```tsx
import { DeviceBadge } from '@/components/device-badge';
import { useCapabilities } from '@/lib/use-environment';

export function ModelPicker() {
  const { capabilities } = useCapabilities();
  const hasWebGPU = Boolean(capabilities?.features.webgpu);

  return (
    <div className="flex items-center gap-3">
      <DeviceBadge capability="webgpu" />
      <button disabled={!hasWebGPU}>Load WebGPU model</button>
    </div>
  );
}
```

Compact (dot only) [#compact-dot-only]

```tsx
<DeviceBadge capability="storage" compact />
```

Customization [#customization]

The badge is styled entirely with shadcn/ui CSS-variable utilities (`border-border`, `bg-card`, `text-card-foreground`, `text-muted-foreground`), so it inherits your theme. The status colors use Tailwind's `emerald` / `amber` palettes directly — swap those classes in the copied `device-badge.tsx` to match your design system, or wire them to your own tokens.

Because you own the file, you can also extend `DeviceBadgeProps` to surface any capability returned by `detectCapabilities()` (e.g. `sharedarraybuffer`, `webworkers`) by adding an entry to the internal capability map.