Audio Player

A composable audio player. One component, one install, fully owned by you.

import {
  AudioPlayer,
  AudioPlayerControlBar,

Everything you need to build an audio player is in a single file: the engine, the UI controls, the queue, tracks, and playback speed. No separate installs, no cross-file wiring. Just one component you copy, paste, and own.

Installation

pnpm dlx shadcn@latest add @audio/player

The CLI resolves every dependency automatically: the store, the HTML audio engine, Fader, Transport, SortableList, and the shadcn/ui primitives the player uses.

Philosophy

Composable by default. AudioPlayer is just a container. Every control (seek bar, volume, queue, playback speed) is an independent component you drop in where you need it. No black-box layout, no hidden markup.

State lives in the store, not in components. All playback state (current track, progress, queue, shuffle, repeat) is held in a Zustand store. Components read and write that store directly. No prop drilling, no context threading.

The engine is separate from the UI. AudioProvider wires up the HTML audio element to the store: event listeners, retries, preloading, state restoration. UI components just read state and call store actions.

Setup

Pass tracks directly to AudioPlayer for a self-contained widget:

import { AudioPlayer, AudioPlayerControlBar, AudioPlayerPlay } from "@/components/player";
 
<AudioPlayer tracks={myTracks}>
  <AudioPlayerControlBar>
    <AudioPlayerPlay />
  </AudioPlayerControlBar>
</AudioPlayer>

For shared state across multiple players or app-wide persistence, mount AudioProvider once at the root:

// app/layout.tsx
import { AudioProvider } from "@/components/player";
 
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <AudioProvider tracks={initialTracks}>{children}</AudioProvider>
      </body>
    </html>
  );
}

Player

Compact

import {
  AudioPlayer,
  AudioPlayerControlBar,

With queue

import {
  AudioPlayer,
  AudioPlayerControlBar,

Variants

import {
  AudioPlayer,
  AudioPlayerControlBar,

Sizes

import {
  AudioPlayer,
  AudioPlayerControlBar,

AudioPlayer

Container for all player controls.

PropTypeDefaultDescription
tracksTrack[]-When provided, wraps children with AudioProvider automatically.
variant"default" | "ghost""default"Visual style. ghost is transparent with a hover background.
size"sm" | "default""default"Controls padding and border radius.
classNamestring-Additional CSS classes.

Inherits all other props from HTMLDivElement. The underlying CVA definition is exported as audioPlayerVariants for extension.

AudioProvider

Connects the HTML audio element to the Zustand store. Handles event listeners, retries, preloading, and state restoration.

PropTypeDefaultDescription
tracksTrack[][]Initial tracks to populate the queue.
childrenReactNode-Components that share this audio session.

AudioPlayerButton

Shared button primitive used by all player controls. Wraps a Button with an optional tooltip.

PropTypeDefaultDescription
tooltipLabelstring-When provided, wraps the button in a tooltip.

Inherits all other props from Button.

AudioPlayerControlBar

Groups controls in a single row or stacked column layout.

PropTypeDefaultDescription
variant"compact" | "stacked""compact"Controls the layout.

AudioPlayerControlGroup

Flexible row wrapper for arranging control clusters. Use className to adjust alignment.

AudioPlayerPlay

Play/pause button. Shows a spinner during loading/buffering. Spacebar shortcut is enabled automatically.

Inherits all props from AudioPlayerButton.

AudioPlayerSkipBack / AudioPlayerSkipForward

Navigate between tracks.

Inherits all props from AudioPlayerButton.

AudioPlayerRewind / AudioPlayerFastForward

Seek backward or forward by 10 seconds. Disabled for live streams.

Inherits all props from AudioPlayerButton.

AudioPlayerSeekBar

Seek timeline showing playback and buffered progress. Locked to 100% for live streams.

Inherits all props from Transport (except value, onSeek, bufferedValue).

AudioPlayerTimeDisplay

Displays current time or remaining time. Shows a live indicator for streams.

PropTypeDefaultDescription
remainingbooleanfalseShow remaining time instead of elapsed time.

AudioPlayerVolume

Dropdown with a horizontal fader to control volume and mute.

Inherits all props from Fader (except value, onValueChange, min, max, orientation, size).

Tracks

AudioTrackList renders a list of tracks. Omit tracks to read from the global queue; pass tracks for controlled mode.

Single track

"use client";

import {

Default

"use client";
import { toast } from "sonner";
import { AudioTrackList } from "@/components/audio/player";

Grid

"use client";
import { toast } from "sonner";
import { AudioTrackList } from "@/components/audio/player";

Sortable

"use client";
import { toast } from "sonner";
import { AudioTrackList } from "@/components/audio/player";

Sortable Grid

"use client";
import { toast } from "sonner";
import { AudioTrackList } from "@/components/audio/player";

AudioTrack

Renders a single track row. media and actions are composed, not configured — pass the pieces you want.

PropTypeDefaultDescription
trackIdstring | number-Look up a track from the queue by id (store mode).
trackTrack-Render a provided track object (controlled mode).
indexnumber-Display index, exposed to AudioTrackIndex.
onClick() => void-Called when the row is clicked.
onRemove(trackId: string) => void-Enables AudioTrackRemoveAction when provided.
mediaReact.ReactNode-Left-side content, e.g. <AudioTrackCover />.
actionsReact.ReactNode-Right-side content, e.g. <AudioTrackPlayPauseAction />.
<AudioTrack
  trackId={track.id}
  media={<AudioTrackCover />}
  actions={<AudioTrackPlayPauseAction />}
/>
 
// Sortable row with remove support
<AudioTrack
  trackId={track.id}
  media={
    <>
      <SortableDragHandle />
      <AudioTrackCover />
    </>
  }
  actions={
    <>
      <AudioTrackRemoveAction />
      <AudioTrackPlayPauseAction />
    </>
  }
  onRemove={handleRemove}
/>

AudioTrackCover, AudioTrackIndex, AudioTrackPlayPauseAction, and AudioTrackRemoveAction read track state from context — they only work inside AudioTrack. AudioTrackRemoveAction renders nothing for the currently playing track or when onRemove isn't set.

AudioTrackList

PropTypeDefaultDescription
tracksTrack[]-Controlled list. Omit to read from the global queue.
onTrackSelect(index: number, track?: Track) => void-Called when a track is selected.
onTrackRemove(trackId: string) => void-Called when a track is removed. Enables remove actions automatically.
mode"static" | "sortable""static"Enable drag-and-drop reordering.
media"cover" | "index""cover"Media style. In sortable mode a drag handle is added automatically.
actions"none" | "play-pause" | "remove" | "play-pause-with-remove"AutoAction variant per row. Auto: "play-pause-with-remove" when onTrackRemove is set.
variant"default" | "grid""default"Stacked list or responsive grid.
filterQuerystring-Text filter (matches title or artist).
filterFn(track: Track) => boolean-Custom filter. Overrides filterQuery when both are set.
emptyLabelstring"No tracks found"Empty state label.
emptyDescriptionstring"Try adding some tracks"Empty state description.

Queue

All queue controls work together or independently.

Simple

"use client";

import {

All controls

import {
  AudioPlayer,
  AudioPlayerControlBar,

Shuffle and repeat

import {
  AudioPlayer,
  AudioPlayerControlBar,

Preferences

import {
  AudioPlayer,
  AudioPlayerControlBar,

AudioQueue

A dialog with the full queue: search, selection, remove, and drag-and-drop reordering.

PropTypeDefaultDescription
onTrackSelect(index: number) => void-Called when a track is selected from the queue.
searchPlaceholderstring"Search for a track..."Search input placeholder.
emptyLabelstring"No tracks found"Empty state label.
emptyDescriptionstring"Try searching for a different track"Empty state description.

AudioQueueShuffle

Toggle that enables/disables shuffle. Persisted to localStorage.

Inherits all props from Toggle (except onPressedChange).

AudioQueueRepeatMode

Toggle that cycles through repeat modes: none → all → one. Persisted to localStorage.

Inherits all props from Toggle.

AudioQueuePreferences

Dropdown combining repeat mode and insert mode (first, last, after current) in one compact menu.

Inherits all props from AudioPlayerButton.

Playback Speed

"use client";

import {

AudioPlaybackSpeed

Dropdown to change playback speed. Disabled automatically for live streams.

PropTypeDefaultDescription
speedsreadonly { value: number; label: string }[]PLAYBACK_SPEEDSSpeed options. Default: 0.5×, 0.75×, 1×, 1.25×, 1.5×, 2×.
sizeButtonSize-"icon" hides the gauge icon, shows only the label.
variantButtonVariant"outline"Button variant.

Notes

More Shadcn Player components

Browse 7 production-ready audio/ui Player components for players, mixers, and synth interfaces. These examples use Base UI primitives from @base-ui/react and stay fully compatible with Shadcn Create so radius, color, and typography match your configured theme.

Browse all 7 Shadcn Player components for copy-ready layouts, dashboards, and forms built with Tailwind CSS in the audio/ui library.