Files
skills/docs/ui/react/react-audio-stream/src/components/stream-mixer/stream-mixer.md
2026-05-29 08:20:56 +01:00

2.2 KiB

stream-mixer

(no submodules)

Purpose

<StreamMixer> renders one strip per remote peer, each with a volume range slider, a mute toggle, a solo toggle, and a read-only FX-slot-count indicator. The component is the visible counterpart to useStreamMixer() — both surfaces are required by Requirement 6 ("Per-peer stream mixer") and the component's solo button proves the DAW-semantics test case from the spec.

Markup is intentionally minimal and unstyled — every interactive control carries an aria-label derived from the peer id so screen readers announce the right peer, and the toggles use aria-pressed for accessibility. Consumers who want richer chrome pass a renderStrip render-prop and own the layout entirely.

Features

  • Default markup with range slider, aria-pressed mute/solo toggles, FX-slot count.
  • renderStrip render-prop for custom layouts (e.g. shadcn cards, drag handles).
  • All mutations route through useStreamMixer() — DAW solo semantics inherited unchanged.
  • Group role="group" with consumer-supplied aria-label for screen readers.
  • Throws REACT_AUDIO_STREAM.NO_PROVIDER outside a <StreamProvider>.

Usage: Basic

<StreamMixer label="Live room mix" />

Usage: Advanced

<StreamMixer
    label="Studio mix"
    renderStrip={(peer, { setVolume, setMute, setSolo }) => (
        <PeerStrip
            peer={peer}
            onVolume={setVolume}
            onMute={() => setMute(!peer.muted)}
            onSolo={() => setSolo(!peer.soloed)}
        />
    )}
/>

API Reference

  • StreamMixerProps — { label?: string; renderStrip?: (peer, controls) => ReactNode }
  • StreamMixer(props): ReactNode

Implementation Notes

The aria-pressed attribute is set on both the mute and solo buttons because they are two-state toggles — this matches WAI-ARIA's authoring practice for toggle buttons and allows assistive tech to announce the current state without parsing the button label. The range slider's value is bound to the live peer.volume so it stays in sync with ducking caused by other peers' solo state (per Requirement 6: when any peer is soloed, non-soloed peers' track volumes go to 0, and the slider reflects that).