Theme studio

Design a theme, preview it live, then export it. Saved in this browser.

Quick picks #10b981
Generated scale
50100200300400500600700800900
Some text is below AA

VideoControls

  • Stable
  • WCAG 2.2 evidence
  • RTL

The control bar of a video: scrubber, play / pause, back, mute and volume, time, captions, settings, picture in picture and full screen, over a dark gradient. It drives nothing by itself: wire the callbacks to a media element (or use VideoPlayer, which does). Accessibility: a named group of React Aria buttons and sliders, each in the tab order. Play / pause changes its name ("Play" / "Pause"); mute, captions, full screen and picture in picture are toggle buttons with aria-pressed and a bar under the icon. The scrubber is a slider announcing "1:20 of 3:45"; arrows seek by seekStep, Page Up / Page Down by 10 %, Home / End to the ends, and pressing the track seeks there (no dragging needed). Shortcuts (K / Space, M, C, F, arrows) work only while focus is in the controls and are listed in aria-keyshortcuts (WCAG 2.1.1, 2.1.4, 2.5.7, 4.1.2). Every target is at least 28 px (2.5.8). Controls are media/fg on a gradient that keeps 3:1 over any frame; the brand fill and the 30 % rail are supplementary to the thumb and the time text (1.4.11). Consumer duties: captions for the media (1.2.2), a transcript or audio description where needed (1.2.3, 1.2.5), no autoplay with sound (1.4.2), and translated labels.

import { VideoControls } from "@nexera-ui/react";
Loading example…
5
examples
30
props
11
live controls
1
platform
9
WCAG criteria
0
blocks use it

Try every prop. Copy the code.

Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.

Loading…
layout
isPlaying
defaultPlaying
isMuted
defaultMuted
isCaptionsOn
defaultCaptionsOn
isFullscreen
isPictureInPicture
keyboardShortcuts
isDisabled
Generated code
import { VideoControls } from "@nexera-ui/react";

<VideoControls />

Examples 4

The same examples as Storybook, rendered live. Open Code to copy one.

Paused

Figma State=Paused: the play / pause button shows play and is named "Play".

Loading example…

Compact

Figma Layout=Compact: play / pause, mute, time and full screen, for narrow players.

Loading example…

Simulated playback

The controls wired to a simulated clock (no media), to try seeking, the back button and the shortcuts.

Loading example…

Narrow container

In a narrow container the button row wraps onto a second line instead of overflowing (WCAG 1.4.10).

Loading example…

Props 30

Press "Try it" on a card to load that prop into the playground.

30 props shown

layoutNexera
"full" | "compact"

Which controls are shown. full: play / pause, back seekStep, mute and volume, time, captions, settings, picture in picture, full screen. compact (narrow players): play / pause, mute, time, full screen.

Default full
isPlayingNexera
boolean

Whether the media plays. Pair it with onPlayingChange.

Default –
defaultPlayingNexera
boolean

Whether the media plays at first render (uncontrolled).

Default false
onPlayingChangeNexera
(isPlaying: boolean) => void

Called with the requested state when play / pause is pressed or K / Space is used. Play or pause your media.

Default –
duration*Nexera
number

Length of the media in seconds. NaN or Infinity (unknown, live) disables the scrubber.

Default –
currentTimeNexera
number

Playback position in seconds. Pair it with onSeek.

Default –
defaultCurrentTimeNexera
number

Playback position at first render (uncontrolled).

Default 0
onSeekNexera
(seconds: number) => void

Called with the position the user seeks to (scrubber, back button, arrow keys). Set your media's currentTime.

Default –
bufferedTimeNexera
number

How far the media has buffered, in seconds.

Default –
volumeNexera
number

Volume from 0 to 1 (controlled). Pair it with onVolumeChange.

Default –
defaultVolumeNexera
number

Volume at first render (uncontrolled).

Default 1
onVolumeChangeNexera
(volume: number) => void

Called with the new volume (volume slider, ArrowUp / ArrowDown).

Default –
isMutedNexera
boolean

Whether the sound is muted (controlled). Pair it with onMutedChange.

Default –
defaultMutedNexera
boolean

Whether the sound is muted at first render (uncontrolled).

Default false
onMutedChangeNexera
(isMuted: boolean) => void

Called with the new muted state (mute toggle, M). Raising the volume while muted unmutes.

Default –
isCaptionsOnNexera
boolean

Whether captions are shown (controlled).

Default –
defaultCaptionsOnNexera
boolean

Whether captions are shown at first render (uncontrolled).

Default false
onCaptionsChangeNexera
(isOn: boolean) => void

Called with the new captions state (captions toggle, C). The captions toggle (full) is shown when this is set.

Default –
isFullscreenNexera
boolean

Whether the player is in full screen (controlled).

Default –
onFullscreenChangeNexera
(isFullscreen: boolean) => void

Called with the requested full-screen state (toggle, F). The full-screen toggle is shown when this is set.

Default –
isPictureInPictureNexera
boolean

Whether picture in picture is on (controlled).

Default –
onPictureInPictureChangeNexera
(isOn: boolean) => void

Called with the requested picture-in-picture state. The toggle (full) is shown when this is set.

Default –
onSettingsPressNexera
() => void

Called when Settings is pressed: open your quality / speed menu. The button (full) is shown when this is set.

Default –
seekStepNexera
number

Seconds moved by ArrowLeft / ArrowRight (on the scrubber and as a shortcut) and by the back button.

Default 5
keyboardShortcutsNexera
boolean

Keyboard shortcuts while focus is in the controls: K / Space play and pause, M mute, C captions, F full screen, arrows seek and change the volume. Never global; set false to turn them off (WCAG 2.1.4).

Default true
formatTimeNexera
(seconds: number) => string

Formats a time for the Time text and the scrubber's announced value.

Default m:ss, or h:mm:ss from one hour
isDisabledNexera
boolean

Disables every control (for example before the media has loaded).

Default false
labelsNexera
Partial<VideoControlsLabels>

Accessible names and texts; English defaults. Translate them.

Default –
classNameNexera
string

Extra classes for the root, merged last so they win over the defaults.

Default –
styleNexera
CSSProperties

Inline style for the root.

Default –

* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.

Accessible by default.

Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.

WCAG 2.2 evidence

7 direct · 2 supporting
  • 1.3.1Info and RelationshipsLevel A · tested directly
  • 1.4.2Audio ControlLevel A · tested directly
  • 1.4.11Non-text ContrastLevel AA · supporting test
  • 2.1.1KeyboardLevel A · tested directly
  • 2.1.4Character Key ShortcutsLevel A · tested directly
  • 2.4.7Focus VisibleLevel AA · tested directly
  • 2.5.7Dragging MovementsLevel AA · tested directly
  • 2.5.8Target Size (Minimum)Level AA · supporting test
  • 4.1.2Name, Role, ValueLevel A · tested directly

Fits any width.

Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.

0 px · drag the corner

Styling hooks

Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.

  • data-disabled
  • data-dragging
  • data-hovered
  • data-pressed
  • data-selected
Usage
<VideoControls className="data-disabled:opacity-90 shadow-sm" />

Used in blocks

No block uses VideoControls yet.

Related components