# Metronome
> Pixel metronome with a swinging pendulum whose weight slides with tempo, four beat lamps, tap tempo and optional click sound.
- Element: `<px-metronome>`
- React: `import { PxMetronome } from "@/components/lumesec/px-metronome"`
- Collection: Pixel Lab (https://elements.lumesec.ai/components/pixel-lab)
- Registry item: https://elements.lumesec.ai/r/px-metronome.json
- Page: https://elements.lumesec.ai/components/pixel-lab/metronome



Live preview: https://elements.lumesec.ai/view/px-metronome

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-metronome.js"></script>

<px-metronome bpm="96"></px-metronome>
```

## Playground

Change a prop and the component updates. Props marked live animate to the new value; the others rebuild the element.

## Installation

```bash
npx shadcn@latest add @lumesec/px-metronome
```

First time with the @lumesec registry? Register it once, or install by URL:

```bash
npx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.json
npx shadcn@latest add https://elements.lumesec.ai/r/px-metronome.json
```

## Usage

React:

```tsx
import { PxMetronome } from "@/components/lumesec/px-metronome";

export function Example() {
  return (
    <PxMetronome bpm={96} />
  );
}
```

HTML:

```html
<script type="module" src="https://elements.lumesec.ai/cdn/px-metronome.js"></script>

<px-metronome bpm="96"></px-metronome>
```

## Behaviour

A swinging pixel pendulum whose weight slides with the tempo, four beat lamps and sparks at each extreme. Tap tempo works, and sound is off until you turn it on.

## API reference

### Attributes

| Attribute | React prop | Type     | Default | Description                                                                   |
| --------- | ---------- | -------- | ------- | ----------------------------------------------------------------------------- |
| `bpm`     | `bpm`      | `number` | `96`    | Starting tempo, clamped to 40 to 208 and rounded. Read once on first connect. |

### Events

Events bubble and cross the shadow boundary unless the description says otherwise.

| Event    | React prop | Detail            | Description                                                                                                                |
| -------- | ---------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `change` | `onChange` | `{ bpm: number }` | Fires whenever the tempo is set by the buttons, tap tempo or `setBpm()`. It does not fire when the element first connects. |

### Methods

Call them on the element, for example through a React ref.

| Method                | Description                                                                                                |
| --------------------- | ---------------------------------------------------------------------------------------------------------- |
| `setBpm(bpm: number)` | Sets the tempo, clamped to 40 to 208, and fires `change`.                                                  |
| `toggle()`            | Starts or stops the metronome from beat one.                                                               |
| `tap()`               | Registers a tap; from the second tap on, the tempo is set from the average interval of the last five taps. |

## Accessibility

* The tempo is text ("96 BPM") over the pendulum and rolls on every change; the outgoing number is `aria-hidden`. The pendulum canvas is hidden from assistive technology.
* The tempo name and play state (for example "Andante · playing") are in an `aria-live="polite"` region.
* Controls are native buttons: "Slower" and "Faster" (labelled with `aria-label`), Start/Stop, Tap, and Sound with `aria-pressed`.
* Reduced motion: the pendulum jumps between its two extremes on each beat instead of swinging, and the beat sparks are skipped.

## Theming

The element reads your shadcn theme tokens through its shadow root, so light and dark follow your theme. The accent comes from `--lumesec`. See [Theming](/docs/theming).

This component reads `--foreground`, `--lumesec` and `--muted-foreground`.

To restyle only LumeSec elements, set the matching `--ui-*` overrides: `--ui-accent`, `--ui-fg`, `--ui-mono` and `--ui-muted`.

## Notes

* Sound is off by default. Turning it on creates a Web Audio context and plays a short 1,600 Hz click on beat one and 1,000 Hz on the others.
* The minus and plus buttons change the tempo by 2 BPM. Taps more than two seconds apart start a new measurement.
* The canvas is 214px tall.


