Hitesh

Annunciator

Component

About

A panel of alarm lamps from a control room. A new alarm flashes until someone acknowledges it, then stays lit while its condition lasts; one that clears unseen keeps flashing, so nothing passes unnoticed. Skeuomorphic, accessible, Base UI. Part of Bevel: bevel-ui.vercel.app

Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Annunciator to your project and fits it to your theme.

Code

How Annunciator is used: the demo's code. The component's own source comes with a free account.

Usage.tsx

"use client"

import * as React from "react"
import {
  Annunciator,
  AnnunciatorAcknowledge,
  AnnunciatorPanel,
  AnnunciatorTile,
} from "@/components/ui/annunciator"

const conditions = [
  { id: "budget", label: "Over budget", tone: "red" },
  { id: "tests", label: "Tests failing", tone: "amber" },
  { id: "rate", label: "Rate limited", tone: "amber" },
  { id: "context", label: "Context full", tone: "amber" },
  { id: "approval", label: "Needs approval", tone: "white" },
  { id: "deploy", label: "Deploy live", tone: "green" },
] as const

/** An agent's alert panel. Steady lamps are acknowledged; a new alarm flashes until you press it. Click a lamp to raise or clear it. */
export function AnnunciatorAgent() {
  const [active, setActive] = React.useState<Record<string, boolean>>({
    budget: true,
    context: true,
    deploy: true,
  })
  const panel = React.useRef<HTMLDivElement>(null)
  // Start with the standing alarms acknowledged, then raise a fresh one.
  React.useEffect(() => {
    // After the first commit, once the button is enabled.
    const ack = setTimeout(
      () =>
        panel.current
          ?.querySelector<HTMLButtonElement>(
            "[data-slot=annunciator-acknowledge]"
          )
          ?.click(),
      150
    )
    const raise = setTimeout(
      () => setActive((a) => ({ ...a, tests: true })),
      700
    )
    return () => {
      clearTimeout(ack)
      clearTimeout(raise)
    }
  }, [])
  return (
    <div ref={panel}>
      <Annunciator aria-label="Agent alerts" className="w-[30rem]">
        <AnnunciatorPanel>
          {conditions.map((c) => (
            <AnnunciatorTile
              key={c.id}
              id={c.id}
              tone={c.tone}
              active={!!active[c.id]}
              onClick={() => setActive((a) => ({ ...a, [c.id]: !a[c.id] }))}
            >
              {c.label}
            </AnnunciatorTile>
          ))}
        </AnnunciatorPanel>
        <AnnunciatorAcknowledge />
      </Annunciator>
    </div>
  )
}

export default AnnunciatorAgent

Dependencies

More by Hitesh

View all
  • Wallet

    Wallet

    8
  • Kbd

    Kbd

    4
  • Number wheel

    Number wheel

    4
  • Badge

    Badge

    2
  • Icon key

    Icon key

    1
  • Gauge and dial

    Gauge and dial

  • Ledger

    Ledger

  • Preset keys

    Preset keys

Explore more

Part of Bevel — browse the full library on 21st.dev.