nili/ui
All components

VideoPlayer

Overview
12 exports3 variant axes17 props4 files
import { 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.

00:00 / 00:00
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.

16/9
00:00 / 00:00
4/3
00:00 / 00:00
1/1
00:00 / 00:00
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.

md
00:00 / 00:00
sm
00:00 / 00:00
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.

with captions
00:00 / 00:00
native controls
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.

00:00 / 00:00
import { VideoPlayer } from "@nili/ui"

export function Example() {
  return (
    <VideoPlayer
      src={src}
      seekStep={10}
      onPlayChange={(playing) => track(playing ? "play" : "pause")}
      onTimeChange={(time) => syncTranscript(time)}
    />
  )
}