# Get Started
This guide will walk you through adding **svelte-audio-ui** components using the [shadcn-svelte](https://shadcn-svelte.com) CLI and registry system.
## Prerequisites
Before you begin, make sure you have:
- A **Svelte 5 project** (SvelteKit recommended for most use cases)
- **Tailwind CSS v4** properly configured
- **shadcn-svelte** initialized in your project
If you haven’t initialized shadcn-svelte yet, run:
## Adding Components
You can add components **svelte-audio-ui** using **shadcn-svelte** CLI or **manually by copying the files.**
{#snippet cli()}
This command will:
- add the `AudioPlayer` component
- automatically install required shadcn primitives
- include the audio store and core logic
- install the `AudioProvider` if it does not already exist
Everything is copied into your project—nothing is installed as a runtime dependency.
{/snippet}
{#snippet manual()}
> On Progress
{/snippet}
## Step 3: Setup AudioProvider
The `AudioProvider` is required and will be added automatically when installing your first audio component.
It acts as the central engine that:
- initializes and manages the HTMLAudioElement
- syncs playback state with the store
- handles buffering, retries, and errors
- preloads upcoming tracks for smoother playback
- persists playback state (volume, progress, queue, etc)
Wrap your app with `AudioProvider` at the root level:
```svelte
{@render children()}
```
This ensures all audio components share a single, consistent playback state.
## Step 4: Use the component
```svelte
{@render children()}
```
## Styling
Components are styled with a design token system defined by CSS variables and implemented with Tailwind CSS. The variables follow the same approach as shadcn/ui and are fully customizable.
For detailed information about styling, color tokens, and customization options, see the [shadcn-svelte theming documentation.](https://www.shadcn-svelte.com/docs/theming)
## Working with LLMs
I try to keep the documentation structured in a way that’s easy for AI to read and work with.
To support that, I include:
- **[llms.txt](/llms.txt)** — a lightweight map of the documentation and component structure, so AI tools can quickly understand how things are organized without scanning everything.
- **[llms-full.txt](/llms-full.txt)** — a more complete dump of the docs and component sources, useful when you want deeper analysis or more accurate generation.
- **Copy Markdown button** — available on every page, so you can quickly grab the content and feed it into your own AI workflow without extra cleanup.
# Introduction
**svelte-audio-ui** is a collection of audio UI components built with [Svelte](https://svelte.dev), [Tailwind CSS](https://tailwindcss.com), and on top of [shadcn-svelte](https://shadcn-svelte.com).
It is inspired by [audio-ui](https://audio-ui.xyz)—an audio component system built on top of shadcn/ui for React—but rethought and rebuilt for the Svelte ecosystem.
**This is not a component library. It is how you build your own audio component system.**
## Why
I’ve used a lot of UI libraries over time, and they usually work well at the beginning.
But once you need deeper control—like adjusting behavior, matching a design system, or building something slightly outside the provided components—things start to break down.
You end up:
- wrapping components just to change small behavior details
- overriding styles in ways that feel fragile and hard to maintain
- mixing multiple libraries that don’t share the same API or design language
That friction adds up quickly.
svelte-audio-ui is my attempt to solve that by keeping everything simple:
> give you the actual code, not an abstraction layer
## Not a Component Library
svelte-audio-ui follows the same philosophy as audio-ui and shadcn:
You don’t install it as a dependency.
You copy the component into your project and own it.
This approach gives you:
- **No Lock-in:** Your components live inside your codebase, so you are never tied to an external package or update cycle that might break your UI.
- **Full Control Over Behavior:** You can change logic, structure, or state handling without needing to wrap or override anything.
- **Long-Term Maintainability:** Instead of fighting abstractions, your components evolve naturally alongside your application.
## Built for Svelte 5
This project is built specifically for modern Svelte, not adapted from another framework.
It uses Svelte 5 patterns and runes to keep components:
- **Explicit and Predictable:** State and reactivity are easy to follow without hidden magic or complex abstractions.
- **Lightweight by Default:** No unnecessary layers, just straightforward component logic that feels close to plain JavaScript.
- **Easy to Extend:** Adding new features or modifying behavior does not require learning a custom API.
The goal is simple: everything should feel like native Svelte code.
## Inspired by shadcn-svelte
The workflow is heavily influenced by [shadcn-svelte](https://shadcn-svelte.com):
- components are copied, not installed
- everything lives in your project
- nothing is hidden behind a package boundary
svelte-audio-ui just narrows the focus into one domain:
**building audio interfaces that are flexible and composable.**
## Composition
Instead of shipping one large “Audio Player” component, the system is built from smaller primitives that can be combined as needed.
Typical building blocks include:
- **Player Controls:** Play, pause, skip, and other interaction elements designed to be reused across different layouts.
- **Timeline / Progress:** A flexible progress system that can be adapted into simple sliders or more advanced scrubbing interactions.
- **Volume Controls:** Independent and composable volume handling that can be reused in different contexts.
- **Optional Layers (Waveform, Metadata):** Additional UI layers that can be plugged in when needed without affecting the core system.
This makes the system flexible enough for both simple players and more complex audio interfaces.
## Beautiful Defaults
Styling is handled with [Tailwind CSS](https://tailwindcss.com), with a focus on clean and consistent defaults.
- **Minimal but Practical:** Components look good out of the box without trying to impose a heavy visual identity.
- **Consistent Across Components:** Spacing, sizing, and interaction patterns are aligned so everything feels like part of the same system.
- **Easy to Customize:** Because styles are local and not abstracted, you can adjust them directly without fighting specificity or overrides.
## AI-Ready
Because everything is just code inside your project, AI tools can work with it more effectively.
- **Readable Structure:** Components follow consistent patterns, making them easier for AI to understand.
- **Extensible System:** AI can help generate new components that match your existing structure and conventions.
- **Faster Iteration:** Instead of starting from scratch, you can evolve your system with AI assistance over time.
## Particles
On top of primitives, there are also [particles](/particles)—pre-built compositions of multiple components.
## Open Source
svelte-audio-ui is open source and built in the open.
I’m working on this as an indie developer, so the project will continue to evolve as I use it in real projects.
If it’s useful for you, feel free to use it, adapt it, or contribute back.
# Audio Playback Speed
A compact dropdown button for switching playback speed on the fly — from a slow `0.5x` all the way up to `2x`. Shows the current rate directly on the button, auto-disables itself when a live stream is detected, and remembers your choice across page reloads.
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
{#if viewerData}
{:else}
Source code not available.
{/if}
{/snippet}
## Usage
```svelte
```
### Basic
Drop it anywhere — no extra wiring needed, it reads from and writes to `audioStore` directly:
```svelte
```
### Icon-only mode
Pass `size="icon"` to hide the gauge icon and show only the speed label — handy when space is tight in a control bar:
```svelte
```
### Custom speeds
Swap out the default speed options with your own list:
```svelte
```
## API Reference
### AudioPlaybackSpeed
#### Props
| Prop | Type | Default | Description |
| --------- | ------------------------------------ | ----------------- | ------------------------------------------------------------------------------ |
| `speeds` | `{ value: number; label: string }[]` | `DEFAULT_SPEEDS` | Speed options. Defaults: `0.5x`, `0.75x`, `1x`, `1.25x`, `1.5x`, `2x`. |
| `size` | `string` | `"sm"` | Button size. Use `"icon"` to hide the gauge icon and show only the speed label.|
| `variant` | `string` | `"outline"` | Button visual variant. |
| `class` | `string` | - | Additional CSS classes. |
Accepts any additional HTML button attributes via `...rest`.
#### Behavior
- **Live streams** — automatically disabled when `htmlAudio.isLive()` returns `true`. Tooltip changes to `"Not available for live streams"` so the user always knows why.
- **Current speed indicator** — the active rate is shown on the button and marked with a radio checkmark in the dropdown.
- **Persistence** — speed is saved to `localStorage` via `audioStore` and restored on the next page load.
- **Icon mode** — when `size="icon"`, the `Gauge` icon is hidden; only the speed label (e.g. `1x`) is shown.
> **Note:** `AudioPlaybackSpeed` requires `AudioProvider` (or the audio store) to be mounted higher in the tree. It reads `audioStore.playbackRate` and `audioStore.duration` reactively via Svelte 5 `$derived` runes — no hook wrappers needed.
## Examples
### Inside a player control bar
```svelte
```
### Custom labels
```svelte
```
## Related
- [Audio Player](/docs/components/player) — the full player component system
- [Audio Provider](/docs/components/provider) — required wrapper that manages playback state
# Audio Player
## Installation
{#snippet cli()}
{/snippet}
{#snippet manual()}
{#if viewerData}
{:else}
Source code not available.
{/if}
{/snippet}
## Setup
Wrap your app with `AudioProvider` at the root level. It powers everything behind the scenes—state, playback, events, retries, and preloading—so all audio components stay in sync.
First, wrap your app with `AudioProvider` at the root level:
```svelte
{@render children()}
```
## Usage
Use the component you need :
```svelte
```
### Stacked Layout
A player with stacked variant, showing time displays above and below the seek bar.
### Player with Queue
A full-featured player with queue management, shuffle, and repeat controls. Uses `AudioPlayerControlGroup` for flexible layout management.
For more queue management options, see the [Audio Queue documentation](/docs/components/queue).
## API Reference
### AudioPlayer.Root
A styled container component for audio controls. This is a presentational wrapper that provides consistent styling. All audio components are self-contained and read state from the global store.
#### Props
Inherits all props from `HTMLDivElement`.
#### Example
```svelte
{/* Your audio controls */}
```
### AudioPlayer.ControlBar
A container component that holds audio player controls. Use it to wrap your control components.
#### Props
| Prop | Type | Default | Description |
| --------- | ------------------------ | ----------- | ----------------------------------- |
| `variant` | `"compact" \| "stacked"` | `"compact"` | Layout variant for the control bar. |
| `class` | `string` | - | Additional CSS classes. |
#### Example
```svelte
```
#### Stacked Layout
```svelte
```
### AudioPlayer.ControlGroup
A flexible wrapper component for grouping audio controls and managing flex layouts. Useful for creating custom layouts with flex-col, justify-between, etc.
#### Props
| Prop | Type | Default | Description |
| ------- | -------- | ------- | ----------------------- |
| `class` | `string` | - | Additional CSS classes. |
#### Example
```svelte
```
### AudioPlayer.Play
A button that toggles play/pause state. Shows a loading spinner when buffering or loading, and automatically handles the Space bar keyboard shortcut.
#### Props
| Prop | Type | Default | Description |
| --------- | ------------------------- | --------- | ------------------------- |
| `class` | `string` | - | Additional CSS classes. |
| `size` | `string` | `"icon"` | Button size variant. |
| `variant` | `string` | `"ghost"` | Button visual variant. |
| `onclick` | `(e: MouseEvent) => void` | - | Additional click handler. |
> **Keyboard Shortcuts**: Automatically handles the Space bar to toggle play/pause when focus is on `document.body`.
### AudioPlayer.SkipBack
Navigates to the previous track. If the current track has played for more than 3 seconds, it restarts the current track instead.
Accepts `class`, `size`, and `variant` props (same as `AudioPlayer.Play`).
### AudioPlayer.SkipForward
Navigates to the next track in the queue.
Accepts `class`, `size`, and `variant` props (same as `AudioPlayer.Play`).
### AudioPlayer.Rewind
Seeks backward by 10 seconds. Disabled on live streams.
Accepts `class`, `size`, and `variant` props (same as `AudioPlayer.Play`).
### AudioPlayer.FastForward
Seeks forward by 10 seconds. Disabled on live streams.
Accepts `class`, `size`, and `variant` props (same as `AudioPlayer.Play`).
### AudioPlayer.SeekBar
A slider that shows playback progress and allows seeking. Locked and shows 100% for live streams.
#### Props
| Prop | Type | Default | Description |
| ------- | -------- | ------- | ----------------------- |
| `class` | `string` | - | Additional CSS classes. |
### AudioPlayer.TimeDisplay
Displays the current playback time or remaining time.
#### Props
| Prop | Type | Default | Description |
| ----------- | --------- | ------- | ----------------------------------------------- |
| `remaining` | `boolean` | `false` | Display remaining time instead of elapsed time. |
| `class` | `string` | - | Additional CSS classes. |
On live streams: the non-remaining display shows elapsed time, and the remaining display shows a pulsing **LIVE** badge with a Radio icon.
### AudioPlayer.Volume
A dropdown button that opens a volume slider. Includes a mute toggle button inside the dropdown. Hidden on mobile (`hidden md:flex`).
#### Props
| Prop | Type | Default | Description |
| --------- | -------- | ----------- | ----------------------- |
| `class` | `string` | - | Additional CSS classes. |
| `size` | `string` | `"icon"` | Button size variant. |
| `variant` | `string` | `"outline"` | Button visual variant. |
## Notes
#### Important Information :
- **Component Architecture:** All audio components are self-contained and read state directly from the global `audioStore` — a Svelte 5 reactive class instance (using `$state` fields) defined in `audio-store.svelte.ts`. The audio player uses the HTML5 audio element under the hood via the `htmlAudio` singleton from `html-audio.ts`.
- **AudioProvider Role:** The `AudioProvider` component manages the audio element lifecycle by importing the `htmlAudio` singleton directly (no hook needed). It initialises the `HTMLAudioElement` inside `onMount`, registers all playback event listeners via an `AbortController` (automatically cleaned up on destroy), handles error retries (up to 3 retries with exponential backoff), preloads the next track into a secondary muted `