mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
138 lines
4.8 KiB
Plaintext
138 lines
4.8 KiB
Plaintext
---
|
|
title: UI components
|
|
description: How Video.js UI components work — one element per component, data attributes for state, and compound composition.
|
|
---
|
|
|
|
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
|
import DocsLink from '@/components/docs/DocsLink.astro';
|
|
import DocsLinkCard from '@/components/docs/DocsLinkCard.astro';
|
|
|
|
UI components are controls like buttons, sliders, and time displays.
|
|
|
|
Every UI component renders exactly one HTML element, taking inspiration from projects like [shadcn/ui](https://ui.shadcn.com/) and [Base UI](https://base-ui.com/). This approach gives you control over styling and behavior while handling the complex interactions for you.
|
|
|
|
## Where to put your components
|
|
<FrameworkCase frameworks={["react"]}>
|
|
UI Components can go anywhere inside a <DocsLink slug="reference/player-provider">`<Player.Provider>`</DocsLink>.
|
|
|
|
However, you should consider placing your components in `<Player.Container>`. Components in `<Player.Container>` will go fullscreen with the player, respond to user activity, and more.
|
|
|
|
<DocsLinkCard slug="reference/player-container">Read more about `<Player.Container>`</DocsLinkCard>
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
UI Components can go anywhere inside a <DocsLink slug="reference/player-provider">`<video-player>`</DocsLink>.
|
|
|
|
However, you should consider placing your components in `<player-container>`. Components in `<player-container>` will go fullscreen with the player, respond to user activity, and more.
|
|
|
|
<DocsLinkCard slug="reference/player-container">Read more about `<player-container>`</DocsLinkCard>
|
|
</FrameworkCase>
|
|
|
|
## Styling and customization
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
|
|
### The `render` prop
|
|
|
|
The `render` prop is the primary customization mechanism. It accepts a function that receives `props` and `state`, and returns your element. The `props` object includes event handlers, ARIA attributes, data attributes, and a ref — always spread `{...props}` to keep everything working:
|
|
|
|
```tsx
|
|
<PlayButton
|
|
render={(props, state) => (
|
|
<button {...props}>
|
|
{state.paused ? 'Play' : 'Pause'}
|
|
</button>
|
|
)}
|
|
/>
|
|
```
|
|
|
|
`className` and `style` also accept functions of state for dynamic styling without a full render prop:
|
|
|
|
```tsx
|
|
<PlayButton
|
|
className={(state) =>
|
|
state.paused ? 'btn btn--paused' : 'btn btn--playing'
|
|
}
|
|
/>
|
|
```
|
|
|
|
### Data attributes and CSS custom properties
|
|
|
|
Components reflect player state as `data-*` attributes on their element. For example, `data-paused` or `data-volume-level="high"`.
|
|
|
|
This lets you style state changes in pure CSS:
|
|
|
|
```css
|
|
/* Show/hide icons based on play state */
|
|
.play-icon { display: none; }
|
|
.pause-icon { display: none; }
|
|
|
|
button[data-paused] .play-icon { display: inline; }
|
|
button:not([data-paused]) .pause-icon { display: inline; }
|
|
```
|
|
|
|
Each component's reference page documents its full set of data attributes.
|
|
|
|
Some components also expose **CSS custom properties** for continuous values like fill percentage and pointer position. Sliders, for example, set `--media-slider-fill` and `--media-slider-pointer`. See individual component reference pages for specifics.
|
|
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
|
|
Components reflect player state as `data-*` attributes on their element. For example, `data-paused` or `data-volume-level="high"`.
|
|
|
|
This lets you style state changes in pure CSS:
|
|
|
|
```html
|
|
<media-play-button class="my-play-button">
|
|
<span class="play-icon">Play</span>
|
|
<span class="pause-icon">Pause</span>
|
|
</media-play-button>
|
|
```
|
|
|
|
```css
|
|
media-play-button .play-icon { display: none; }
|
|
media-play-button .pause-icon { display: none; }
|
|
|
|
media-play-button[data-paused] .play-icon { display: inline; }
|
|
media-play-button:not([data-paused]) .pause-icon { display: inline; }
|
|
```
|
|
|
|
Each component's reference page documents its full set of data attributes.
|
|
|
|
Some components also expose **CSS custom properties** for continuous values like fill percentage and pointer position. Sliders, for example, set `--media-slider-fill` and `--media-slider-pointer`. See individual component reference pages for specifics.
|
|
|
|
</FrameworkCase>
|
|
|
|
## Compound components
|
|
|
|
Complex interactions are split into composable parts. A parent manages shared state while children consume it. Each part is still one element.
|
|
|
|
<FrameworkCase frameworks={["react"]}>
|
|
|
|
Compound components use dot notation off a shared namespace:
|
|
|
|
```tsx
|
|
<VolumeSlider.Root orientation="vertical">
|
|
<VolumeSlider.Track>
|
|
<VolumeSlider.Fill />
|
|
</VolumeSlider.Track>
|
|
<VolumeSlider.Thumb />
|
|
</VolumeSlider.Root>
|
|
```
|
|
|
|
</FrameworkCase>
|
|
|
|
<FrameworkCase frameworks={["html"]}>
|
|
|
|
```html
|
|
<media-volume-slider orientation="vertical">
|
|
<media-slider-track>
|
|
<media-slider-fill></media-slider-fill>
|
|
</media-slider-track>
|
|
<media-slider-thumb></media-slider-thumb>
|
|
</media-volume-slider>
|
|
```
|
|
|
|
</FrameworkCase>
|