AudioPlayer
ImplementedInline audio player — custom compact/expanded UI with play/pause, seek via keyboard (Space, ←→ ±5s, ↑↓ volume), and an error fallback alert. No pointer scrubbing yet (slider is keyboard-only). Autoplay is guarded by prefers-reduced-motion and gesture-blocked autoplay currently surfaces as the error state (tracked).
patterns/molecules/audioplayer.htmlInline audio player with custom play control and progress UI.
AudioPlayer
Media & playback — molecule
Inline audio player with custom play control and progress UI.
Opening keynote
Main hall
Usage
AudioPlayer is self-managing: give it a real src and an accessible label, and it handles play state, timing and the error fallback itself. The compact layout shows the play button, progress track and timecode; any of title / artist / artwork switches it to the expanded layout.
import { AudioPlayer } from '@epasslive/design-system'
// Compact
<AudioPlayer src="/track.mp3" label="Interview" />
// Expanded (title/artist/artwork)
<AudioPlayer
src="/keynote.mp3"
label="Opening keynote"
title="Opening keynote"
artist="Main hall"
artwork="/artwork.jpg"
/>Keyboard
| Key | Action |
|---|---|
Space | Toggle play / pause (container focused) |
← | Seek back 5 seconds |
→ | Seek forward 5 seconds |
↑ | Volume up (+0.1) |
↓ | Volume down (−0.1) |
Honest notes (current limitations)
- Seeking is keyboard-only today. Focus the player and press
←/→(±5 s). The progress track has no pointer or touch interaction yet — mouse users cannot scrub. Pointer seeking is planned via the DSSlidermolecule. - Volume is keyboard-only.
↑/↓adjust volume; there is no visible volume control or mute button yet. - Do not set
autoplay. Playback is suppressed when the user prefers reduced motion, and a browser that blocks ungestured autoplay currently surfaces the error alert even for healthy audio (known defect —NotAllowedErroris not distinguished from real media errors yet). No demo or story here uses autoplay. - The error fallback reflects genuine media failures. The third preview above uses a 404 source on purpose so the inline
role="alert"fallback renders for the right reason. - No captions/transcript support yet (WCAG 1.2.1 for audio-only content is the consumer's responsibility today).
Props
src*stringAudio source URL, passed straight to the native <audio> element (HTTPS or data URI).
label*stringAccessible name for the player region; prefixes the Play/Pause button labels ("Play {label}").
titlestringTrack title. Providing title, artist or artwork switches to the expanded layout.
artiststringTrack artist line, shown under the title in the expanded layout.
artworkstringSquare cover image URL (rendered 48×48, decorative — empty alt).
autoplaybooleanAttempt playback on mount. Suppressed when the user prefers reduced motion. Default false.
loopbooleanReplay from the start when the track ends. Default false.
classNamestringAdditional classes on the root element.
idstringStable root id; falls back to an SSR-safe useId() value.
Props
AudioPlayer
srcstring—Audio source URL.
titlestring—Track title (expanded variant).
artiststring—Artist line (expanded variant).
artworkstring—Artwork image URL (expanded variant).
autoplaybooleanfalseAttempt playback on mount — guarded by prefers-reduced-motion; note gesture-blocked autoplay currently renders the error state.
loopbooleanfalseLoop the track when it ends.
labelstring—Accessible name for the player — feeds the Play/Pause aria-labels and the progress slider's name.
classNamestring—Additional CSS classes.
idstring—Stable root id.
<AudioPlayer />Accessibility
ARIA
2 rulesUsage
Import
import { AudioPlayer } from "@epasslive/design-system"Example 1
<AudioPlayer src="/media/interview.mp3" label="Interview" />Example 2
<AudioPlayer src={url} label={track.name} title={track.name} artist={track.artist} artwork={track.cover} />Anti-patterns
— Do not set autoplay without accounting for gesture-blocked playback — it currently renders the error state
— Do not promise pointer scrubbing — seeking is keyboard-only until the slider interaction lands