# LED

> A status light that glows in its tone when lit, a dim dot when off, and blinks for an armed take.

```tsx
"use client";

import { useCallback, useState } from "react";
import { Button } from "@/components/ui/button";
import { Led } from "@/components/audio-ui/led";

export function LedDemo() {
  const [recording, setRecording] = useState(true);
  const [muted, setMuted] = useState(false);
  const toggleRecording = useCallback(() => setRecording((on) => !on), []);
  const toggleMuted = useCallback(() => setMuted((on) => !on), []);
  return (
    <div className="flex items-center gap-6">
      <Button
        aria-pressed={recording}
        onClick={toggleRecording}
        size="sm"
        variant="outline"
      >
        <Led blink label="Recording" on={recording} tone="destructive" />
        Rec
      </Button>
      <Button
        aria-pressed={muted}
        onClick={toggleMuted}
        size="sm"
        variant="outline"
      >
        <Led label="Mute" on={muted} />
        Mute
      </Button>
      <div className="flex items-center gap-2">
        <Led label="Off" on={false} size="sm" />
        <Led label="On" on size="default" />
        <Led label="Large" on size="lg" />
      </div>
    </div>
  );
}
```

A status light, as on a panel: lit, it glows in its tone; off, it stays a dim dot, so its place still shows. It shows a state and sets none: put it beside the button or the switch that does.

## Installation

**CLI**

```bash
npx shadcn@latest add @audio-ui/led
```

**Manual**

**1. Install the following dependencies:**

```bash
npm install class-variance-authority
```

**2. Copy and paste the following code into your project.**

```tsx title="components/audio-ui/led.tsx"
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const ledVariants = cva("rounded-full bg-muted-foreground/25 shadow-inner transition-[background-color,box-shadow] duration-100 data-on:bg-current data-on:shadow-[0_0_0.375rem_currentColor] data-blink:data-on:animate-pulse motion-reduce:transition-none motion-reduce:data-blink:data-on:animate-none inline-block shrink-0", {
  defaultVariants: {
    size: "default",
    tone: "primary",
  },
  variants: {
    size: {
      default: "size-2",
      lg: "size-3",
      sm: "size-1.5",
    },
    /** Its color when lit: the theme's primary, or destructive for recording and clipping. */
    tone: {
      destructive: "text-destructive",
      primary: "text-primary",
    },
  },
});

export interface LedProps extends VariantProps<typeof ledVariants> {
  /** Blinks while lit: a take arming, a clip about to start. Still for reduced motion. @default false */
  blink?: boolean;
  className?: string;
  /** Names what it shows, for assistive technology: "Recording", "Signal". */
  label: string;
  /** Whether it is lit. */
  on: boolean;
}

/**
 * A status light: lit, it glows in its tone; off, a dim dot, so its place
 * still shows. It shows a state, it does not set one: its label reads the
 * state out ("Recording: on").
 */
export function Led({
  blink = false,
  className,
  label,
  on,
  size,
  tone,
}: LedProps) {
  return (
    <span
      aria-label={`${label}: ${on ? "on" : "off"}`}
      className={cn(ledVariants({ size, tone }), className)}
      data-blink={blink ? "" : undefined}
      data-on={on ? "" : undefined}
      data-size={size ?? "default"}
      data-slot="led"
      role="img"
    />
  );
}
```

**3. Update the import paths to match your project setup.**

**Agent**

Give your agent the skill, and it picks the component, installs it and wires it to your audio:

```bash
npx skills add ouestlabs/audio-ui
```

Then ask it:

```text
Add the led from audio/ui to my project and wire it to my audio code.
```

To let the agent read the docs live, connect the [MCP server](/docs/mcp). More in [Agent Skill](/docs/agents).

## Usage

```tsx
import { Led } from "@/components/audio-ui/led";

<Led blink label="Recording" on={recording} tone="destructive" />
```

Its label reads the state out to assistive technology ("Recording: on"). `blink` pulses it while lit, and holds it still for reduced motion. Its shape follows the style: round, or square in the square styles.

## API reference

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `on` | `boolean` |  | Whether it is lit. |
| `label` | `string` |  | Names what it shows, for assistive technology: "Recording", "Signal". |
| `tone` | `"primary" \| "destructive"` | `"primary"` | Its color when lit: the theme's primary, or destructive for recording and clipping. |
| `blink` | `boolean` | `false` | Blinks while lit: a take arming, a clip about to start. Still for reduced motion. |
| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Its size. |
