audiocn

Level Meter

A peak and RMS level meter with zones, peak hold, a scale, a readout and a clip light.

−∞ dB

Installation

$ pnpm dlx shadcn@latest add @audiocn/level-meter

Usage

import { LevelMeter } from "@/components/ui/level-meter";
<LevelMeter aria-label="Microphone level" peakDb={-12} />

With no children, LevelMeter renders one track per channel with a peak bar and a peak-hold tick. Add children to control the anatomy.

Anatomy

<LevelMeter source={analyser.meter}>
  <LevelMeterChannels>
    <LevelMeterChannel index={0}>
      <LevelMeterTrack>
        <LevelMeterBar measure="rms" />
        <LevelMeterBar measure="peak" />
        <LevelMeterHold />
      </LevelMeterTrack>
    </LevelMeterChannel>
    <LevelMeterScale />
  </LevelMeterChannels>
  <LevelMeterValue />
  <LevelMeterClip />
</LevelMeter>

Examples

Default

Values

Pass peakDb (and optionally rmsDb) for data that arrives slowly. The meter still moves smoothly between updates.

Quiet
Good
Hot
Clipping

Vertical

−∞ dB

Variants

solid
segmented
gradient

Peak and RMS

Layer an rms bar over a translucent peak bar for a dual meter.

Ballistics

peak rises in 15 ms and falls steadily; vu is slow and averaged; instant follows the input exactly.

peak
vu
instant

Colors and zones

Override the meter tokens with a class, or pass your own zones.

Build your own visual

Each channel writes its live level to --meter-level (0..1). Anything inside a LevelMeterChannel can use it in CSS.

Microphone

−∞ dB

Feeding data

A meter accepts levels three ways. See Feeding data.

// A source: subscribes and paints itself, no React renders.
<LevelMeter source={analyser.meter} />

// Values: for slow data. Ballistics smooth the movement.
<LevelMeter peakDb={-9.1} rmsDb={-18} />

// A handle: for callers that own their own frame loop.
const meter = useRef<LevelMeterActions>(null);
meter.current?.paint({ channels: [{ peakDb: -9.1 }] });
<LevelMeter actionsRef={meter} />

Theming

Token or variableWhereDefault
--meter-ok, --meter-warn, --meter-clipthemegreen, amber, --destructive
--meter-thicknessroot0.5rem (sm 0.25rem, lg 0.75rem)
--meter-gaproot0.25rem, between channels
--meter-level, --meter-rms, --meter-holdeach channel, live0..1
Data attributeOnMeaning
data-orientation, data-variant, data-sizerootCurrent settings
data-zoneroot, channelsok, warn or clip
data-clippingrootThe signal clipped in the last 1.5 s
data-activechannelsThe level is above the bottom of the range
data-dimmedrootInside a muted or silenced channel strip
data-measurebarspeak or rms

Accessibility

  • The root has role="meter" with aria-valuemin, aria-valuemax and aria-valuenow in dB, and aria-valuetext such as "−12.0 dB". These update at most four times a second.
  • Give every meter a name with aria-label or aria-labelledby.
  • With reduced motion, the meter shows the current level four times a second instead of animating.

API reference

LevelMeter

Prop

Type

LevelMeterChannel

Prop

Type

LevelMeterBar

Prop

Type

LevelMeterScale, LevelMeterValue, LevelMeterClip

These wrap DbScale, DbReadout and ClipIndicator, and take their props. The range, orientation and data come from the meter.