Video
Video player supporting YouTube, Vimeo embeds, and native HTML5 video. Detects provider from URL and builds the correct embed.
Import
import { Video } from "@hyzer-labs/ui"Demo
Every ratio below plays the same source file. The aspect box is the component's own: the footage letterboxes or pillarboxes inside whatever ratio the prop declares.
<Video src="/hero.mp4" title="A card composed from the library" /><Video src="/hero.mp4" title="A card composed from the library" aspectRatio="4/3" /><Video src="/hero.mp4" title="A card composed from the library" aspectRatio="1/1" /><Video src="/hero.mp4" title="A card composed from the library" aspectRatio="9/16" />One prop, three players. A YouTube URL becomes a youtube-nocookie.com embed
and a Vimeo URL carries dnt=1, so neither provider sets tracking cookies on
a visitor who never presses play. Both iframes carry the right allow and referrer
policies. Any other URL renders a native <video>. All three render
below: the same component, three players. Lightbox plays every video item it shows through this
component.
<!-- Provider is detected from the URL -->
<Video src="https://www.youtube.com/watch?v=XtMoGuqdFeE" title="Course flyover" />
<Video src="https://vimeo.com/102751770" title="Form check" />
<Video src="/hero.mp4" title="A card composed from the library" />poster shows before playback starts. Native provider only: embeds bring their
own thumbnails.
<Video
src="/media/round-recap.mp4"
poster="/media/recap-poster.jpg"
title="Round recap"
/>Props
| Name | Type | Default | Note |
|---|---|---|---|
src | string | — | Required. Native file URL, or a YouTube/Vimeo URL — the provider is detected and the right embed is built. |
title | string | — | Required for accessibility. |
aspectRatio | '16/9' | '4/3' | '1/1' | '9/16' | '16/9' | |
autoplay | boolean | false | Requires muted; suppressed under prefers-reduced-motion. |
muted | boolean | false | |
controls | boolean | true | |
loop | boolean | false | |
poster | string | — | Native provider only. |
loading | 'lazy' | 'eager' | 'lazy' | |
class | string | — | Merged after the hz-video class. |
Theme hooks
What this component promises your CSS. The reference theme styles exactly these — from @layer hz-theme, so your unlayered rules win. See Styling Components for the how.
Root class: .hz-video
Data attributes
| Hook | Values | Styles |
|---|---|---|
data-provider | 'youtube' | 'vimeo' | 'native' | Detected from src. Styling hook for provider-specific chrome. |
data-aspect-ratio | '16/9' | '4/3' | '1/1' | '9/16' | Mirrors the prop; the ratio lands as an inline style. Closed union — unlike Image, there is no auto. Default 16/9. |
data-state | 'idle' | 'playing' | 'paused' | 'ended' | Read-only playback state. Native embeds only — a YouTube or Vimeo iframe stays idle, because the provider owns those controls. |
Part classes
| Hook | Values | Styles |
|---|---|---|
.hz-video__el | child element | The player — the iframe or the native video, whichever the src resolved to. One class across all three branches, so it fills the ratio box either way. |
Accessibility
The title prop is required and maps to the iframe title or video aria-label. autoplay requires muted, both because browsers refuse to autoplay sound and because motion a reader did not ask for is disorienting.
References: MDN: <video>