# Media Controls

Audio player controls with a play button that morphs into pause, skip buttons and toggle chips for modes like shuffle or sleep, plus a line or waveform scrubber that follows your finger.

> Composed · Pro · Mobile-Native — React Native, Expo Go compatible.

## Install

```bash
npx @lumioui/cli add pro/media-controls
```

## Import

```tsx
import { formatMediaTime, PlayPauseButton, MediaToggle, MediaChip, MediaControls } from "@/components/ui/media-controls/media-controls";
```

## Variants

- `audiobook` — Audiobook: `npx @lumioui/cli add pro/media-controls-audiobook`
- `meditation` — Meditation: `npx @lumioui/cli add pro/media-controls-meditation`
- `music` — Music player: `npx @lumioui/cli add pro/media-controls-music`
- `podcast` — Podcast: `npx @lumioui/cli add pro/media-controls-podcast`

## Props

### PlayPauseButton

| Prop | Type | Notes |
| --- | --- | --- |
| `playing` | `boolean` | — |
| `onPress?` | `() => void` | — |
| `size?` | `PlayPauseSize` | sm 44 · md 64 · lg 76 · xl 112 (single-control players). Default md. |
| `appearance?` | `"filled" | "bare"` | filled — accent disc; bare — large glyph only (full-screen music idiom). |
| `disabled?` | `boolean` | — |
| `className?` | `string` | — |

### MediaToggle

| Prop | Type | Notes |
| --- | --- | --- |
| `icon` | `IconName` | — |
| `label` | `string` | Accessible name ("Shuffle", "Repeat"). |
| `active` | `boolean` | — |
| `onPress?` | `() => void` | — |
| `badge?` | `string` | Tiny badge on the glyph — "1" for repeat-one. |
| `className?` | `string` | — |

### MediaChip

| Prop | Type | Notes |
| --- | --- | --- |
| `label` | `string` | — |
| `accessibilityLabel?` | `string` | Accessible name — "Playback speed 1.5x". Defaults to the label. |
| `icon?` | `IconName` | — |
| `active?` | `boolean` | Filled while a mode is on (sleep timer set). |
| `onPress?` | `() => void` | — |
| `className?` | `string` | — |

### MediaControls

| Prop | Type | Notes |
| --- | --- | --- |
| `playing?` | `boolean` | — |
| `defaultPlaying?` | `boolean` | — |
| `onPlayingChange?` | `(playing: boolean) => void` | — |
| `duration?` | `number` | Track length in seconds. Omit for a transport row with no clock. |
| `defaultPosition?` | `number` | Start position in seconds. |
| `trackId?` | `string | number` | Changing it (new track) resets the position to 0. |
| `rate?` | `number` | Simulated clock rate (1, 1.5, 2…). Default 1. |
| `onSeek?` | `(seconds: number) => void` | Fires after a scrub or skip with the new position in seconds. |
| `onPositionChange?` | `(seconds: number) => void` | Fires once per whole second of position (never per frame). |
| `onEnd?` | `() => void` | Fires when playback reaches the end. |
| `loop?` | `boolean` | Restart from the top at the end instead of stopping (repeat one). |
| `scrubber?` | `"line" | "waveform" | "none"` | line — thin bar with a knob; waveform — amplitude bars; none — hide. Default line. |
| `markers?` | `number[]` | Positions (seconds) drawn as notches on the line scrubber — chapters. |
| `showTime?` | `boolean` | Show elapsed / remaining under the scrubber. Default true. |
| `skip?` | `"track" | "seconds" | "both" | "none"` | track — prev/next · seconds — ±N skips · both — prev, −N, play, +N, next · none. Default track. |
| `skipBackSeconds?` | `number` | — |
| `skipForwardSeconds?` | `number` | — |
| `onPrevious?` | `() => void` | — |
| `onNext?` | `() => void` | — |
| `leading?` | `React.ReactNode` | Outer-left slot — shuffle toggle, speed chip. |
| `trailing?` | `React.ReactNode` | Outer-right slot — repeat toggle, sleep chip. |
| `size?` | `PlayPauseSize` | Play button size. Default lg. |
| `playAppearance?` | `"filled" | "bare"` | filled disc or bare glyph. Default filled. |
| `className?` | `string` | — |

## Icons rendered

- `shuffle` — /icons.html?i=shuffle

Source: https://lumioui.com/components/media-controls