Video Controls

Pro

Player controls over any video, with a scrubber, play and pause, skip, speed, captions, mute and fullscreen. Double-tap either side to seek, plus a minimal short-form mode.

Preview

Installation

npx @lumioui/cli add pro/video-controls

Usage

import { formatPlaybackTime, VideoControls } from "@/components/ui/video-controls/video-controls";
<VideoControls />

Also exported: formatPlaybackTime.

Examples

Course lesson

A learning app's lesson player in pink, playing at 1.5×.

Short-form minimal

A short-form food clip in orange using the minimal chrome: tap anywhere to pause (the play glyph ignites in), drag the hairline scrubber along the bottom edge, mute from the corner.

Streaming

A streaming app's watch page in red.

API reference

VideoScrubber

Prop Type Default
position* number

Current playback position in seconds.

—
duration* number

Total length in seconds.

—
buffered number

Buffered-ahead position in seconds — drawn as a lighter range.

—
playing boolean

While true the playhead advances between position updates.

—
rate number

Playback rate — scales the in-between advance. Default 1.

—
updateInterval number

How often your player reports position, in ms. Default 500.

—
onScrubStart () => void

Fires once when a scrub starts.

—
onScrub (seconds: number) => void

Fires while scrubbing, once per whole second crossed.

—
onSeek (seconds: number) => void

Fires on release with the seek target in seconds.

—
thin boolean

Hairline track with no resting thumb (minimal / short-form). Default false.

—
showBubble boolean

Show the time bubble above the thumb while scrubbing. Default true.

—
disabled boolean —
className string —

VideoControls

Prop Type Default
duration* number

Total length in seconds.

—
playing boolean

Controlled play state.

—
defaultPlaying boolean

Uncontrolled initial play state. Default false.

—
onPlayingChange (playing: boolean) => void

Fires with the next play state — call play()/pause() here.

—
position number

Current position in seconds.

—
buffered number

Buffered-ahead position in seconds.

—
onSeek (seconds: number) => void

Seek request in seconds — from the scrubber, skip buttons and double-tap.

—
onScrub (seconds: number) => void

Live scrub position, once per whole second (e.g. thumbnail previews).

—
skipInterval number

Skip distance for the ± buttons and double-tap. Default 10.

—
rate number

Current playback rate. Shows the speed pill when onRateChange is set.

—
rates number[]

Rates the speed pill cycles through. Default [1, 1.25, 1.5, 2, 0.75].

—
onRateChange (rate: number) => void —
captions boolean

Captions state. The CC button shows when onCaptionsChange is set.

—
onCaptionsChange (on: boolean) => void —
muted boolean

Mute state. The speaker button shows when onMutedChange is set.

—
onMutedChange (muted: boolean) => void —
fullscreen boolean

Fullscreen state. The expand button shows when onFullscreenChange is set.

—
onFullscreenChange (fullscreen: boolean) => void —
title string

Top-bar title (full variant).

—
subtitle string

Top-bar second line (full variant).

—
onClose () => void

Renders a collapse chevron top-left (full variant).

—
variant "full" | "minimal"

full (streaming-player chrome) or minimal (short-video feed). Default full.

—
visible boolean

Controlled chrome visibility (full variant).

—
defaultVisible boolean

Uncontrolled initial chrome visibility. Default true.

—
onVisibleChange (visible: boolean) => void —
autoHide number

Hide the chrome after this many ms of playing without interaction. 0 disables. Default 3000.

—
updateInterval number

How often your player reports position, in ms — the playhead interpolates between. Default 500.

—
aspectRatio number | null

Width / height of the player. Default 16/9. Pass null to fill the parent.

—
children React.ReactNode

The video surface, rendered full-bleed under the chrome.

—
className string —