Capsule Player
Show what's playing in a capsule, with a seek rail and play, previous and next.
import { CapsulePlayer } from '@youj/react'
Installation & usage
npm i @youj/reactFor an app already set up with npx @youj/cli init, which installs the peers (@youj/core, @youj/motion, motion and Base UI) and wires the provider. New app? Start at Installation.
Use a capsule player as a compact now-playing bar: at the foot of a music app, over a video timeline, in the corner of a podcast page. It shows the cover, the title and artist, a thin progress rail you can seek, the time played, and the transport buttons.
The player has no clock of its own. Pass it the playhead and the length from your audio or video element, and act on its callbacks.
import { CapsulePlayer } from '@youj/react'
<CapsulePlayer
title="Low Tide"
subtitle="Mara Quell"
artwork={<img src={cover} alt="" />}
playing={playing}
onPlayingChange={(next) => (next ? audio.play() : audio.pause())}
position={time}
duration={audio.duration}
onSeek={(seconds) => (audio.currentTime = seconds)}
onPrevious={previousTrack}
onNext={nextTrack}
/>Without onSeek the rail only shows progress. Without onPrevious or onNext, that button is disabled.
Description
A capsule player with a cover, a title and artist, a seek rail and previous, play and next buttons, over two tracks.
Code
capsule-player-demo.tsx, the Demo story. The component itself comes from the package.
Reference
Propstitle, playing, onPlayingChange… (12)
Props
| Prop | Type | |
|---|---|---|
titleRequired | string | – |
subtitle | stringThe artist, show or source, muted after the title. | – |
artwork | ReactNodeCover art: an <img> or any node, cropped to a disc. Decorative. | – |
playingRequired | boolean | – |
onPlayingChangeRequired | (playing: boolean) => void | – |
positionRequired | numberThe playhead, in seconds. | – |
durationRequired | numberThe track's length, in seconds. | – |
onSeek | (seconds: number) => voidSeeks to a time in seconds, as the rail is dragged or stepped. Without it the rail only shows progress. | – |
onPrevious | () => voidWithout it, the previous button is disabled. | – |
onNext | () => voidWithout it, the next button is disabled. | – |
locale | stringFormats the times. Default: the YoujProvider locale. | – |
size | 'sm' | 'default'
default `default` | `default` |
StylingParts and data attributes
Styling
Parts: capsule-player (with data-playing), capsule-player-art, capsule-player-title, capsule-player-time, capsule-player-rail and capsule-player-progress.
MotionPlay and pause, new track, rail
Motion
| Moment | Tokens | ||
|---|---|---|---|
| Play and pausethe triangle folds into the two pause bars | spring.snappy0.2s, bounce 0 | 0.2s, bounce 0 | |
| New trackthe new title rises in as the old one leaves upward | duration.baseease.emphasized220ms · cubic-bezier(0.6, 0, 0.1, 1) | 220mscubic-bezier(0.6, 0, 0.1, 1) | |
| Railthe thumb grows in on hover and focus; the fill follows the time exactly | duration.fastease.enter140ms · cubic-bezier(0.16, 1, 0.3, 1) | 140mscubic-bezier(0.16, 1, 0.3, 1) |
Reduced motion
The icon and the title change at once.
AccessibilityKeyboard
Accessibility
- The play button is named for what it does next: "Play", or "Pause" while playing.
- The rail is a slider named "Seek", spoken as the time and the length ("1:12 of 3:40"). The arrow keys move five seconds, and Home and End jump to the ends.
- The cover is decorative.
- The button names come from the labels (
play,pause,previousTrack,nextTrack,waveformSeek,waveformPosition), which the language packs translate.