Step player
An iOS-style stepped progress track with a play, pause and replay control. The active step stretches into a bar that fills as it plays.
Step 1 of 5
Loading component source...
Installation
pnpm dlx shadcn@latest add mox/mox-ui/step-playerRun this command from your project directory to add the component and its dependencies.
- 1
Install the packages
pnpm add motion flubber clsx tailwind-merge - 2
Add the utility file
lib/utils.tsimport { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs));} - 3
Copy and paste the code into your project
Loading source⦠- 4
Update the import paths to match your project
Point
@/lib/utilsto your utility file if your path aliases differ.
Usage
import { StepPlayer } from "@/components/ui/step-player"
export function Demo() { return <StepPlayer steps={5} duration={3000} />}
// drive your own carousel off the index<StepPlayer steps={slides.length} value={index} onValueChange={setIndex} loop/>Options
Pick a value to see the prop you would pass. Defaults are left out.
<StepPlayer />Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | number | StepPlayerStep[] | Default: 4 | How many steps to show. Pass an array to give each one its own duration or label. |
value | number | Default: - | Active step index, for controlled use. Leave it out and the component tracks its own index. |
defaultValue | number | Default: 0 | Step to start on when uncontrolled. Clamped to the last step. |
onValueChange | (value: number) => void | Default: - | Fires when the step advances, wraps, or is clicked. Also fires on replay. |
playing | boolean | Default: - | Play state, for controlled use. Leave it out to let the button drive it. |
defaultPlaying | boolean | Default: false | Whether the sequence starts running on mount when uncontrolled. |
onPlayingChange | (playing: boolean) => void | Default: - | Fires when the button is pressed, and when the last step ends without loop. |
duration | number | Default: 4000 | Milliseconds each step runs for. A per-step duration overrides it; 0 stops the timer so you can drive the index yourself. |
loop | boolean | Default: false | Wraps back to the first step instead of stopping. The replay button never appears when this is on. |
onComplete | () => void | Default: - | Fires when the last step finishes, on every pass when looping. |
size | number | Default: 48 | Height of the track and button in pixels. Every other dimension is a fixed ratio of it, so the dots, bar, gaps, padding, icon, and tap targets all scale from this one number. |
showControl | boolean | Default: true | Shows the round play button. Turn it off for a track on its own and drive it with the playing prop. |
controlPosition | "left" | "right" | Default: "right" | Which side of the track the button sits on. |
seekable | boolean | Default: false | Lets a step be clicked to jump to it. The dots keep a finger-sized tap target at every size. |
className | string | Default: - | Extra classes merged onto the root element. It sizes itself from the size prop, so give it a width only if you want the track wider than its content. |
Press play to start the sequence. The current step stretches into a bar and fills as it runs, then shrinks to a filled dot when it hands off to the next one. Press again to pause mid-fill; the play icon splits into the pause bars as it goes. At the end it fades into a replay arrow. Steps can be clicked to jump.
Credits and license
Most components here are recreations of great work from around the web. I don't claim to be the original creator - this is my attempt to reverse-engineer, replicate, and often add a few extra features. I've tried to credit everyone; if I missed someone, let me know.
- Free to use and modify in both personal and commercial projects.
- Attribution to Mox UI is appreciated when using a component.
- Please don't resell the components as your own kit.