vaiperui

components / video-player

VideoPlayer

Video player with custom controls, fullscreen, captions and keyboard shortcuts.

How to use

Wraps a native `<video>`. The controls hide after `hideControlsAfter` ms of inactivity while playing and come back on mouse, touch or keyboard. Clicking the video toggles play. Shortcuts: Space/K, arrows (seek and volume), M, F (fullscreen). Put `<track kind="captions">` as children and a captions button appears. `variant="overlay"` adds a large play button in the center while paused and adapts to the player width (container query).

preview
0:00 / 0:00
VideoPlayer.tsx
import { VideoPlayer } from "vaiperui";
<VideoPlayer src="/video/flower.mp4" poster="/video/poster.jpg" label="Flower">
<track kind="captions" src="/video/en.vtt" srcLang="en" label="English" />
</VideoPlayer>

Variants

`overlay` adds a large play button in the center while paused. Narrower than 560px the seek bar moves below the buttons and the volume slider hides.

preview
0:00 / 0:00
default
0:00 / 0:00
overlay
0:00 / 0:00
overlay, narrow (300px)
variants.tsx
<VideoPlayer src="/video/flower.mp4" />
<VideoPlayer src="/video/flower.mp4" variant="overlay" />

Colors

preview
0:00 / 0:00
primary
0:00 / 0:00
success
0:00 / 0:00
warning
0:00 / 0:00
danger
colors.tsx
<VideoPlayer src="/video/flower.mp4" variantColor="primary" />
<VideoPlayer src="/video/flower.mp4" variantColor="success" />
<VideoPlayer src="/video/flower.mp4" variantColor="warning" />
<VideoPlayer src="/video/flower.mp4" variantColor="danger" />

Sizes

preview
0:00 / 0:00
sm
0:00 / 0:00
md
0:00 / 0:00
lg
sizes.tsx
<VideoPlayer src="/video/flower.mp4" size="sm" />
<VideoPlayer src="/video/flower.mp4" size="md" />
<VideoPlayer src="/video/flower.mp4" size="lg" />

Custom color

preview
0:00 / 0:00
Pink
0:00 / 0:00
Per theme
custom-color.tsx
<VideoPlayer src="/video/flower.mp4" customColor="#db2777" />
<VideoPlayer src="/video/flower.mp4" customColor={{ light: "#7c3aed", dark: "#c4b5fd" }} />

Props

PropValuesDefaultDescription
variantdefault | overlaydefaultoverlay: large play button in the center while paused; narrower than 560px the seek bar moves below the buttons and the volume slider hides
srcstring—Video URL
posterstringnoneImage shown before playing
labelstringVideoAccessible name of the player
autoPlay / muted / loopbooleanfalseNative behaviors (autoPlay almost always needs muted)
preloadnone | metadata | autometadataHow much the browser loads before play
hideControlsAfternumber2500Idle ms before hiding the controls while playing; 0 keeps them visible
childrenReactNodenone`<track>` (captions) and extra `<source>` elements
labelsPartial<{ play, pause, mute, unmute, seek, volume, fullscreen, exitFullscreen, captions }>English textsOverrides the built-in texts (aria-labels of the buttons and sliders)
onPlay / onPause / onEnded() => voidnoneCalled by the matching media events
onTimeUpdate(currentTime: number) => voidnoneCalled while playing, with the position in seconds
variantColorprimary | success | warning | dangerprimaryAccent color (play button, progress, dots)
customColorstring | { light, dark }noneAny CSS color (or a pair per theme). Overrides variantColor
sizesm | md | lgmdSize of the controls and text
radiusnone | sm | md | lg | fulllgCorner rounding
animationnone | smooth | fast | bouncesmoothTransition of the controls

Accessibility

  • The player is a focusable `role="group"` named by `label`; focus it (Tab or click on the video) and the shortcuts work.
  • The play, mute and fullscreen buttons change their name with the state (`play`/`pause`, `mute`/`unmute`, `fullscreen`/`exitFullscreen` in `labels`).
  • The seek bar and the volume are `Slider`s (`role="slider"`) named by `labels.seek` and `labels.volume`.
  • The captions button only appears when the video has `<track>` children, and it exposes `aria-pressed` for on/off.
  • The controls hide after `hideControlsAfter` of inactivity while playing, never while a control has focus; hidden controls are `inert`, so they leave the tab order, and any key, focus or mouse movement brings them back.
  • With `variant="overlay"`, the big central play button is `aria-hidden` and `tabIndex={-1}`: it is a shortcut for mouse and touch, and keyboard and screen reader users use the play button of the bar.

Keyboard

KeyAction
Space / KPlay or pause (when focus is not on a button or slider)
ArrowLeft / ArrowRightSeek 5s back / forward
ArrowUp / ArrowDownVolume up / down by 10%
MMute or unmute
FToggle fullscreen

Keep in mind

  • Captions are not generated: pass `<track kind="captions">` as children, and provide a transcript or audio description when the content needs it.
  • Avoid `autoPlay`; if you must, start `startMuted`, since browsers block autoplay with sound and it surprises users. Translate `labels` for the page language.