KQ-1343 · MUSIC/APP
Music App
A complete music screen built with repeat-coil, mute-cone and follow-knot: a library of procedural covers and album pages that push in on glide, and a mini player (a bar, a pill or a corner card) that is one shared surface with the full player, growing from its box to the whole screen while the cover becomes the disc's label and the title and Play travel, all on glide; a downward drag on the grab bar follows 1:1 and, projected past a third of the height, folds it back. The disc (a record, a silver disc, or a sleeve the record slides half out of on glide) spins up like a motor on Play and coasts down under friction on Pause, its angle and the playing position integrated by one frame loop that runs only while something moves and the screen is visible; Up next follows a dragged row 1:1 while the others glide out of its way and settle it with its release velocity. The scrubber is a slider (arrows 5 s, Page keys 30 s, Home and End), the queue is one tab stop (arrows move, Alt+arrows reorder, Enter plays, Delete removes), and Escape closes the queue sheet, then the player.
Library
paused · “low tide” · 5 up next
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/music-app
Props
- disc
- "vinyl" | "cd" | "cover"
- default "vinyl"
- The turning artwork in the player: a record under a fixed sheen with the cover as its label, a silver disc printed with the cover, or the square sleeve with the record sliding half out of it while it plays.
- queue
- "panel" | "sheet"
- default "panel"
- Where Up next lives: a panel beside the library on desktop and beside the player on tablet, or a sheet behind a button. A phone always uses the sheet.
- mini
- "bar" | "pill" | "card"
- default "bar"
- The mini player's shape, and the shape the full player grows from: a bar along the bottom with a progress line, a floating pill with a progress ring, or a card in the corner.
- albums
- MusicAlbum[]
- default defaultMusicAlbums
- The library: albums with an artist, a year, procedural cover art and their tracks.
- track / defaultTrack
- string
- default the first album's first track
- The current track's id. Controlled or uncontrolled.
- onTrackChange
- (id: string) => void
- default —
- Fires from the press, the queue or the end of a track that moved to another.
- playing / defaultPlaying
- boolean
- default false
- Whether it is playing. Nothing plays until asked. Controlled or uncontrolled.
- onPlayingChange
- (playing: boolean) => void
- default —
- Play or Pause was pressed, or the queue ran out.
- upNext / defaultUpNext
- string[]
- default defaultMusicUpNext
- The queue after the current track, as track ids. Controlled or uncontrolled.
- onUpNextChange
- (ids: string[]) => void
- default —
- Fires from the drag, key, remove, clear, shuffle or track change that changed the queue.
- expanded / defaultExpanded
- boolean
- default false
- Whether the full player is open. Controlled or uncontrolled.
- onExpandedChange
- (expanded: boolean) => void
- default —
- The mini player was pressed, or the player was closed by its button, a downward drag or Escape.
- repeat / defaultRepeat
- "off" | "all" | "one"
- default "off"
- Repeat mode, shown by repeat-coil. Controlled or uncontrolled.
- onRepeatChange
- (mode: RepeatMode) => void
- default —
- The repeat button changed mode.
- volume / defaultVolume
- number
- default 70
- Volume 0 to 100, shown and set by mute-cone. Controlled or uncontrolled.
- onVolumeChange
- (volume: number) => void
- default —
- The volume was dragged or keyed.
- muted / defaultMuted
- boolean
- default false
- Whether it is muted. Controlled or uncontrolled.
- onMutedChange
- (muted: boolean) => void
- default —
- Mute was toggled.
- following / defaultFollowing
- string[]
- default ["Coldbrook Quartet"]
- The artists the listener follows, by name, toggled with follow-knot on album pages. Controlled or uncontrolled.
- onFollowingChange
- (artists: string[]) => void
- default —
- An artist was followed or unfollowed.
- defaultPosition
- number
- default 0
- Where the first track starts, in seconds.
- onSeek
- (seconds: number) => void
- default —
- The visitor moved the playhead: a scrub, a press on the track, a key, or Previous.
- status
- "ready" | "loading" | "error"
- default "ready"
- Loading draws placeholder covers; error offers Try again.
- onRetry
- () => void
- default —
- Try again was pressed after the library failed to load.
- label
- string
- default "Music"
- The screen's accessible name.
- sound
- boolean
- default false
- Play the presses, the ticks of a scrub and the queue, only for the visitor's own actions; the composed pieces play theirs too.
- disabled
- boolean
- default false
- Nothing plays, moves or opens.
- className
- string
- default —
- Classes for the root. It is 560px tall by default; pass a height class to change it.
| Prop | Type | Default | Description |
|---|---|---|---|
| disc | "vinyl" | "cd" | "cover" | "vinyl" | The turning artwork in the player: a record under a fixed sheen with the cover as its label, a silver disc printed with the cover, or the square sleeve with the record sliding half out of it while it plays. |
| queue | "panel" | "sheet" | "panel" | Where Up next lives: a panel beside the library on desktop and beside the player on tablet, or a sheet behind a button. A phone always uses the sheet. |
| mini | "bar" | "pill" | "card" | "bar" | The mini player's shape, and the shape the full player grows from: a bar along the bottom with a progress line, a floating pill with a progress ring, or a card in the corner. |
| albums | MusicAlbum[] | defaultMusicAlbums | The library: albums with an artist, a year, procedural cover art and their tracks. |
| track / defaultTrack | string | the first album's first track | The current track's id. Controlled or uncontrolled. |
| onTrackChange | (id: string) => void | — | Fires from the press, the queue or the end of a track that moved to another. |
| playing / defaultPlaying | boolean | false | Whether it is playing. Nothing plays until asked. Controlled or uncontrolled. |
| onPlayingChange | (playing: boolean) => void | — | Play or Pause was pressed, or the queue ran out. |
| upNext / defaultUpNext | string[] | defaultMusicUpNext | The queue after the current track, as track ids. Controlled or uncontrolled. |
| onUpNextChange | (ids: string[]) => void | — | Fires from the drag, key, remove, clear, shuffle or track change that changed the queue. |
| expanded / defaultExpanded | boolean | false | Whether the full player is open. Controlled or uncontrolled. |
| onExpandedChange | (expanded: boolean) => void | — | The mini player was pressed, or the player was closed by its button, a downward drag or Escape. |
| repeat / defaultRepeat | "off" | "all" | "one" | "off" | Repeat mode, shown by repeat-coil. Controlled or uncontrolled. |
| onRepeatChange | (mode: RepeatMode) => void | — | The repeat button changed mode. |
| volume / defaultVolume | number | 70 | Volume 0 to 100, shown and set by mute-cone. Controlled or uncontrolled. |
| onVolumeChange | (volume: number) => void | — | The volume was dragged or keyed. |
| muted / defaultMuted | boolean | false | Whether it is muted. Controlled or uncontrolled. |
| onMutedChange | (muted: boolean) => void | — | Mute was toggled. |
| following / defaultFollowing | string[] | ["Coldbrook Quartet"] | The artists the listener follows, by name, toggled with follow-knot on album pages. Controlled or uncontrolled. |
| onFollowingChange | (artists: string[]) => void | — | An artist was followed or unfollowed. |
| defaultPosition | number | 0 | Where the first track starts, in seconds. |
| onSeek | (seconds: number) => void | — | The visitor moved the playhead: a scrub, a press on the track, a key, or Previous. |
| status | "ready" | "loading" | "error" | "ready" | Loading draws placeholder covers; error offers Try again. |
| onRetry | () => void | — | Try again was pressed after the library failed to load. |
| label | string | "Music" | The screen's accessible name. |
| sound | boolean | false | Play the presses, the ticks of a scrub and the queue, only for the visitor's own actions; the composed pieces play theirs too. |
| disabled | boolean | false | Nothing plays, moves or opens. |
| className | string | — | Classes for the root. It is 560px tall by default; pass a height class to change it. |