# VideoPlayer

> A video player built on the browser's own `<video>`: chapters and captions written as WebVTT tracks from data, time links that work without script, and a custom control bar with a settings menu pages extend, which replaces the native controls once script runs.

```ts
import { VideoPlayer } from "@sdxc/ui/video";
```

A `<figure>` sharing one timeline with its parts; with no script its native controls play and
time links open the file there. Map VideoPlayerSync (`@sdxc/ui/video/video-player`) for
the bar. Theming: `--ui-video-player-` radius, progress-color, menu-bg, on-video, transcript-height.

## Examples

```tsx
<VideoPlayer duration={703} chapters={chapters}>
	<VideoPlayer.Screen label="Centering 3 kg" captionsLabel="English" chaptersLabel="Chapters"><VideoPlayer.Source src="/07.mp4" type="video/mp4" /></VideoPlayer.Screen>
	<VideoPlayer.Side><VideoPlayer.Chapters label="Chapters" /></VideoPlayer.Side>
</VideoPlayer>
```

```tsx
<VideoPlayer duration={703} chapters={chapters} transcript={lines} tone="theater">
	<VideoPlayer.Screen label="Centering 3 kg" captionsLabel="English" chaptersLabel="Chapters">
		<VideoPlayer.Source src="/07.mp4" type="video/mp4" label="1080p" badge="HD" />
		<VideoPlayer.Controls label="Video controls"><VideoPlayer.Progress label="Seek" /><VideoPlayer.Play label="Play" pauseLabel="Pause" /><VideoPlayer.Time /></VideoPlayer.Controls>
	</VideoPlayer.Screen>
	<VideoPlayer.Side><VideoPlayer.Transcript label="Transcript" /></VideoPlayer.Side>
</VideoPlayer>
```

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `duration` | `number` | Length in seconds; it closes the last chapter and the last caption. |
| `chapters?` | `readonly Chapter[]` | Chapters in playing order. |
| `transcript?` | `readonly Cue[]` | Spoken lines in playing order. |
| `current?` | `number` | The moment the page renders as now, in seconds, before the island takes over. |
| `tone?` | `"plain" \| "theater"` | Colour scheme of the player. @default "plain" |
| `children` | `RemixNode` | The parts, in reading order; a VideoPlayer.Side becomes the second column. |

Also accepts everything in `TagProps<"figure">`.


### VideoPlayer.Screen

The 16:9 screen: a native `<video controls>` holding its sources and the chapters and captions tracks written from the timeline, over a VideoPlayer.Frame when given, under a VideoPlayer.Controls bar that takes over from the native controls.

| Prop | Type | Description |
| --- | --- | --- |
| `label` | `string` | The video's accessible name. |
| `poster?` | `string` | Image shown before playback, as the native `poster`. |
| `language?` | `string` | Language of the chapters and captions tracks. @default "en" |
| `captionsLabel` | `string` | The captions track's name in the player's menus, such as "English". |
| `chaptersLabel` | `string` | The chapters track's name, such as "Chapters". |
| `children` | `RemixNode` | VideoPlayer.Source elements in preference order, any extra `<track>`, an optional VideoPlayer.Frame and an optional VideoPlayer.Controls. |

Also accepts everything in `Omit<TagProps<"div">, "children">`.


### VideoPlayer.Source

One file the video may play, in preference order, exactly as a `<source>` inside `<video>`; the first one also gives every time link its address.

| Prop | Type | Description |
| --- | --- | --- |
| `src` | `string` | The file's address; the first source's is where every time link points. |
| `type?` | `string` | Media type, such as `video/webm`, so the browser skips files it cannot play. |
| `label?` | `string` | The file's name in the quality menu, such as `1080p`; the file name stands in when unset. |
| `badge?` | `string` | Short mark beside the label and on the settings gear, such as `HD` or `4K`. |

Also accepts everything in `Omit<TagProps<"source">, "children">`.


### VideoPlayer.Frame

A drawn still under the video: it shows before playback and through any transparent part of the picture while it plays.

Takes no props of its own.

### VideoPlayer.Scrubber

The chapters as one bar of segments as long as each chapter, filled to the current moment, so the video's shape shows before it plays.

Takes no props of its own.

### VideoPlayer.Caption

The video's title line: the title at the start, small print at the end, wrapping under each other on a narrow screen.

| Prop | Type | Description |
| --- | --- | --- |
| `meta?` | `RemixNode` | Small print at the inline end, such as "Lesson 7 · 11:43". |

Also accepts everything in `TagProps<"figcaption">`.


### VideoPlayer.Side

The second column: chapters, transcript and anything the page adds, such as a card for the next video, stacked in order.

Takes no props of its own.

### VideoPlayer.Chapters

The chapters as links to their moments, each with its still when given; the chapter playing carries `aria-current`.

| Prop | Type | Description |
| --- | --- | --- |
| `label` | `string` | The visible label and the list's accessible name. |

Also accepts everything in `Omit<TagProps<"nav">, "children">`.


### VideoPlayer.Transcript

The transcript in a scroll region, each line behind a link to its moment; the line playing carries `aria-current` and the island keeps it in view.

| Prop | Type | Description |
| --- | --- | --- |
| `label` | `string` | The visible label and the scroll region's accessible name. |

Also accepts everything in `Omit<TagProps<"div">, "children">`.


### VideoPlayer.Controls

The custom control bar along the bottom of the screen, rendered `hidden` until the island swaps it for the native controls.

| Prop | Type | Description |
| --- | --- | --- |
| `label` | `string` | The bar's accessible name, such as "Video controls". |

Also accepts everything in `TagProps<"div">`.


### VideoPlayer.Progress

The seek slider: a native range over the video's length, so arrow keys, Home and End seek and assistive technology reads the time.

| Prop | Type | Description |
| --- | --- | --- |
| `label` | `string` | The slider's accessible name, such as "Seek". |

Also accepts everything in `Omit<
		TagProps<"input">,
		"type" | "min" | "max" | "value" | "children" | "role"
	>`.


### VideoPlayer.Play

Plays and pauses; its accessible name says what a press does next.

| Prop | Type | Description |
| --- | --- | --- |
| `pauseLabel` | `string` | The name while the video plays; `label` is the name while it is paused. |

Also accepts everything in `ButtonProps`.


### VideoPlayer.Time

The time played and the video's length, `1:12 / 11:43`.

Takes no props of its own.

### VideoPlayer.CaptionsToggle

Turns captions on and off: on shows the track last chosen in the captions menu, the first one at the start.

Takes no props of its own.

### VideoPlayer.Settings

The settings gear and its menu: a Popover API surface the gear opens through `commandfor`, holding toggles and submenus in order.

| Prop | Type | Description |
| --- | --- | --- |
| `id?` | `string` | The menu's id, which the gear's `commandfor` names. Defaults to a generated one. |
| `badge?` | `string \| false` | Mark on the gear. Left out, it is the playing source's badge and follows the quality menu; `false` draws none. |
| `children` | `RemixNode` | Rows of the menu, in order. |

Also accepts everything in `ButtonProps`.


### VideoPlayer.SettingsToggle

A page-defined switch row: a real checkbox the page reads by `name` and follows with an ordinary `change` listener, such as ambient mode or a voice boost.

| Prop | Type | Description |
| --- | --- | --- |
| `name` | `string` | The form name a `change` listener reads the switch by. |
| `label` | `RemixNode` | The row's visible label. |

Also accepts everything in `Omit<
		TagProps<"input">,
		"type" | "name" | "children"
	>`.


### VideoPlayer.SettingsMenu

A page-defined submenu: a row naming the current choice that opens a panel of VideoPlayer.SettingsOption radios under one `name`, such as a sleep timer.

| Prop | Type | Description |
| --- | --- | --- |
| `name` | `string` | The radio group's form name, which a `change` listener reads the choice by. |
| `label` | `RemixNode` | The row's visible label, repeated on the submenu's back row. |
| `backLabel` | `string` | The back row's accessible prefix, such as "Back". |
| `children` | `RemixNode` | VideoPlayer.SettingsOption elements; the one marked `checked` is chosen. |

Also accepts everything in `Omit<TagProps<"div">, "children">`.


### VideoPlayer.SettingsOption

One choice of a VideoPlayer.SettingsMenu: a real radio under the menu's name, marked with a check when chosen.

| Prop | Type | Description |
| --- | --- | --- |
| `value` | `string` | The value a `change` listener reads from the menu's `name` once this is chosen. |
| `badge?` | `RemixNode` | A short mark after the label, such as `4K`. |
| `children` | `RemixNode` | The option's visible label, which its submenu's row repeats once chosen. |

Also accepts everything in `Omit<
		TagProps<"input">,
		"type" | "name" | "children" | "value"
	>`.


### VideoPlayer.CaptionsMenu

The captions submenu: Off, then every captions and subtitles track the video holds.

| Prop | Type | Description |
| --- | --- | --- |
| `offLabel` | `string` | The option that hides every track, such as "Off". |

Also accepts everything in `BuiltInMenuProps`.


### VideoPlayer.SpeedMenu

The playback speed submenu; a choice sets the video's `playbackRate` and survives a quality change.

| Prop | Type | Description |
| --- | --- | --- |
| `rates?` | `readonly number[]` | Rates offered, in order. @default [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] |
| `normalLabel` | `string` | The name of rate 1, such as "Normal". |

Also accepts everything in `BuiltInMenuProps`.


### VideoPlayer.QualityMenu

The quality submenu: one row per labelled VideoPlayer.Source, by its `label` and `badge`; an unlabelled source is a format fallback and stays off the menu.

Takes no props of its own.

### VideoPlayer.Theater

Theater mode: sets `data-theater` on the player, which drops the side column under the screen so the video takes the full width.

Takes no props of its own.

### VideoPlayer.Fullscreen

Full screen for the screen with its bar, so the controls stay.

Takes no props of its own.

## Types

| Name | Values | What it decides |
| --- | --- | --- |
| `Tone` | `"plain" \| "theater"` | `plain` follows the page's scheme; `theater` is a dark screening room in either. |
