VideoPlayer
Overviewimport { VideoPlayer, VideoPlayerLabels, VideoRatio } from '@nili/ui';This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.
Basic
Custom controls over a real video element. Everything unrecognised is spread onto the media element, so preload, crossOrigin and the media events work without this component re-declaring them — className is the exception, which styles the container.
import { VideoPlayer } from "@nili/ui"
export function Example() {
return (
<VideoPlayer
src="/media/flower.mp4"
poster="/media/flower.jpg"
labels={{
root: "Product tour",
play: "Play",
pause: "Pause",
seek: "Seek",
fullscreen: "Full screen",
}}
/>
)
}Aspect ratios
The frame is set by ratio, not by the file — so the layout does not jump when the metadata arrives. auto gives the box back to the video’s own dimensions.
import { VideoPlayer } from "@nili/ui"
export function Example() {
return (
<>
<VideoPlayer src={src} ratio="16/9" />
<VideoPlayer src={src} ratio="4/3" />
<VideoPlayer src={src} ratio="1/1" />
<VideoPlayer src={src} ratio="auto" />
</>
)
}Control density
size sets how large the controls are, not how large the video is. Use sm when the player sits in a card or a sidebar and the full-size bar would crowd the frame.
import { VideoPlayer } from "@nili/ui"
export function Example() {
return (
<>
<VideoPlayer src={src} size="md" />
<VideoPlayer src={src} size="sm" />
</>
)
}Captions, autoplay and native controls
tracks takes track elements for captions — ship them, since a muted autoplaying video is unreadable without. Autoplay only works muted in every browser, which is why the two go together. nativeControls hands the bar back to the browser when you need its picture-in-picture and cast menus.
import { VideoPlayer } from "@nili/ui"
export function Example() {
return (
<>
<VideoPlayer
src={src}
tracks={
<track
kind="captions"
srcLang="en"
label="English"
src="/media/flower.en.vtt"
default
/>
}
/>
{/* muted autoplay, looping — a background clip */}
<VideoPlayer src={src} autoPlay loop muted />
{/* the browser's own controls */}
<VideoPlayer src={src} nativeControls />
</>
)
}Events and seeking
onPlayChange and onTimeChange are there for analytics and for syncing a transcript. seekStep sets how far the arrow keys jump — five seconds is the default, and a long lecture usually wants more.
import { VideoPlayer } from "@nili/ui"
export function Example() {
return (
<VideoPlayer
src={src}
seekStep={10}
onPlayChange={(playing) => track(playing ? "play" : "pause")}
onTimeChange={(time) => syncTranscript(time)}
/>
)
}VideoButton
internalVideoControls
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| visible | 'true' | 'false' | true |
VideoElement
internalVideoOverlayButton
internalVideoPlayer
extends Omit< ComponentPropsWithoutRef<'video'>, 'src' | 'poster' | 'controls' | 'children' | 'autoPlay' | 'loop' | 'muted' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| size | md | sm | md | |
| ratio | 16/9 | 4/3 | 1/1 | auto | 16/9 |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| src* | string | — | |
| poster | string | — | |
| tracks | ReactNode | — | Caption and subtitle tracks. Pass real `<track>` elements — captions are the accessibility story of this component, not an optional extra. |
| autoPlay | boolean | false | |
| loop | boolean | false | |
| muted | boolean | false | Starts muted. Required by browsers for autoplay to be allowed at all. |
| nativeControls | boolean | false | Hand control back to the browser's own UI. Worth doing when the platform player is better than anything you would ship — picture-in-picture, AirPlay, and caption styling all come free with it. |
| seekStep | number | 5 | Seconds jumped by the arrow keys. |
| onPlayChange | (playing: boolean) => void | — | |
| onTimeChange | (currentTime: number) => void | — | |
| locale | string | — | BCP-47 tag driving the timestamps (`'fa'` → Persian). Defaults to the ambient locale from `NiliProvider`. |
| labels | VideoPlayerLabels | — |