shadcn.io is an independent project built on shadcn/ui
One speed, two rows, starting at 1. Rates are 0.5x, 0.75x, 1x, 1.25x, 1.5x, and 2x. Presets are Slow, Normal, Fast, and Faster, mapped to 0.5x, 1x, 1.5x, and 2x. Normal and 1x both start filled. Choosing Fast also fills 1.5x.
Use the rates for a precise player and the names when a word is enough. If six rates do not fit, a Select takes less width. In Svelte, Ark UI does not change how fast media plays.
Installation
Anatomy

Usage
<div class="flex flex-col gap-4"><ButtonGroup aria-label="Playback speed">{#each SPEEDS as item (item)}<Button aria-pressed={speed === item} onclick={handleSelect} size="sm" value={String(item)} variant={speed === item ? "default" : "outline"}>{item}x</Button>{/each}</ButtonGroup><ButtonGroup aria-label="Playback speed preset">{#each PRESETS as item (item.label)}<Button aria-pressed={speed === item.value} onclick={handleSelect} size="sm" value={String(item.value)} variant={speed === item.value ? "default" : "outline"}>{item.label}</Button>{/each}</ButtonGroup></div>FAQ
How is the speed stored?
As a number, starting at 1. Each button carries its rate as its value, and pressing it stores that rate as a number.
Why does Fast light up 1.5x too?
The presets map to rates: Slow is 0.5, Normal 1, Fast 1.5 and Faster 2. Both rows compare against the same number, so the matching buttons fill together. 0.75x and 1.25x have no preset.
How is the selected rate shown?
Its button uses variant="default" and sets aria-pressed. The others use outline.
How do I apply the speed to a player?
Set the media element's playbackRate to the stored number when it changes. The demo has no player.
How is 1.25x written?
The label is the number followed by x. Format it yourself if you want a different style, such as 1.25×.
What if six buttons don't fit?
Keep the preset row, or move the rates into a Select or a menu.
API Reference
Button Group
Sets aria-label="Playback speed" and aria-label="Playback speed preset". The rest is on the Button Group page.
Button
Sets aria-pressed={speed === item}, onclick={handleSelect}, size="sm", value={String(item)}, variant={speed === item ? "default" : "outline"} and aria-pressed={speed === item.value}. The rest is on the Button page.





