Equalizer
An animated now-playing meter whose bars move independently, and stop when paused or when motion is reduced.
stableEqualizer.tsx
Examples
Sizes and tones
equalizer/basic.tsx
"use client";
import { useState } from "react";
import { Pause, Play } from "lucide-react";
import { Button, Equalizer } from "@streamuilib/react";
export default function EqualizerBasic() {
const [playing, setPlaying] = useState(true);
return (
<div className="flex items-center gap-6">
<Equalizer playing={playing} bars={3} tone="lime" />
<Equalizer playing={playing} bars={5} tone="pink" className="h-8" />
<Equalizer playing={playing} bars={7} tone="blue" className="h-12 gap-1 [&>span]:w-2" />
<Button size="sm" variant="secondary" onClick={() => setPlaying(!playing)}>
{playing ? <Pause aria-hidden /> : <Play aria-hidden />}
{playing ? "Pause" : "Play"}
</Button>
</div>
);
}Installation
bun add @streamuilib/reactusage.tsx
import { Equalizer } from "@streamuilib/react";
<Equalizer playing={isPlaying} bars={4} tone="pink" />API
| Prop | Type | Default | Description |
|---|---|---|---|
| playing | boolean | true | Animate the bars; when false they rest low. |
| bars | number | 4 | How many bars. |
| tone | "lime" | "pink" | "blue" | "violet" | "orange" | "lime" | Bar color. |
| className | string | — | Size it with height classes, e.g. h-8. |
Accessibility
- Purely decorative and aria-hidden; pair it with text that says what's playing.
- Under prefers-reduced-motion the bars hold still at a fixed height.
Source
packages/react/src/Equalizer.tsx
import type { ComponentProps, CSSProperties } from "react";
import { cn } from "./cn";
import { toneBg, type Tone } from "./tones";
export type EqualizerProps = ComponentProps<"span"> & {
/** Animate the bars; when false they rest low. */
playing?: boolean;
bars?: number;
tone?: Tone;
};
/**
* A decorative "now playing" meter. Each bar gets its own speed and delay so
* the motion never looks like one block. Hidden from assistive tech, and
* still under prefers-reduced-motion (styles in theme.css).
*/
export function Equalizer({ playing = true, bars = 4, tone = "lime", className, ...props }: EqualizerProps) {
return (
<span
aria-hidden
data-playing={playing || undefined}
className={cn("sui-eq inline-flex h-4 items-end gap-0.5", className)}
{...props}
>
{Array.from({ length: bars }, (_, i) => (
<span
key={i}
className={cn("sui-eq-bar block h-full w-1 border border-ink", toneBg[tone])}
style={{ "--sui-eq-i": i } as CSSProperties}
/>
))}
</span>
);
}