Video Reveal Hero
A free Next.js video hero section with native controls, captions, a transcript, and a configurable Motion mask reveal.
From the Nitrate archive
Restored, cleared, ready to cut
11,400 restored reels, every one cleared for broadcast and streaming.
Read the video transcript
Hildy calls out, asks how the other person is, and asks whether the lord of the universe is in. The reply says that he is in, but in a bad humour, and jokes that somebody must have stolen the crown jewels.
Customise
Code
<HeroVideoReveal
eyebrow="From the Nitrate archive"
title={
"Restored, cleared, " +
"ready to cut"
}
description={
"11,400 restored reels, " +
"every one cleared for " +
"broadcast and streaming."
}
primaryCta={{
label: "Search the archive",
href: "/archive",
}}
secondaryCta={{
label: "Request a quote",
href: "/licensing",
}}
video={{
src: "/video/story.mp4",
poster: "/video/story-poster.jpg",
label:
"A short film introducing " +
"the product story.",
captions: [
{
src: "/video/story.en.vtt",
srcLang: "en",
label: "English",
default: true,
},
],
transcript:
"A complete text transcript " +
"of the spoken film content.",
}}
/>Video Reveal Hero is a free Next.js video hero section for React and Tailwind that introduces a page with accessible copy, real calls to action, and one captioned native video. One Motion sequence raises the content in sequence as the section comes into view, while the media opens through a rounded, circular, or diagonal mask.
The poster and aspect ratio reserve the complete media stage before playback data arrives, while native controls, WebVTT tracks, and a visible transcript disclosure keep the film usable. The video never autoplays, and people who prefer reduced motion receive the complete final hero immediately with no clipping, translation, or scale.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/hero-video-revealUsage
import { HeroVideoReveal } from "@/components/hero-video-reveal";
export default function Page() {
return (
<HeroVideoReveal
eyebrow="From the Nitrate archive"
title="Restored, cleared, ready to cut"
description="11,400 restored reels, every one cleared for broadcast and streaming."
primaryCta={{ label: "Search the archive", href: "/archive" }}
secondaryCta={{ label: "Request a quote", href: "/licensing" }}
video={{
src: "/video/story.mp4",
poster: "/video/story-poster.jpg",
label: "A short film introducing the product story.",
captions: [
{
src: "/video/story.en.vtt",
srcLang: "en",
label: "English",
default: true,
},
],
transcript:
"A complete text transcript of the spoken film content.",
}}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| eyebrow | string | undefined | Optional introductory label rendered above the headline. |
| title | string | required | Headline copy, rendered as the hero's single h1. |
| description | string | required | Supporting copy rendered below the headline. |
| primaryCta | { label: string; href: string } | required | Primary call to action, rendered as a real anchor. |
| secondaryCta | { label: string; href: string } | undefined | Optional secondary call to action, rendered as a real anchor. |
| video | { src: string; poster: string; label: string; captions?: { src: string; srcLang: string; label: string; default?: boolean }[]; transcript?: string } | required | Native video data, optional WebVTT caption tracks, and an optional visible transcript disclosure. |
| alignment | "left" | "center" | "center" | Copy alignment within the vertical hero composition. |
| aspectRatio | number | 16 / 9 | Positive width-to-height ratio that reserves the media stage before load. |
| maskShape | "rounded" | "circle" | "diagonal" | "rounded" | Geometry used for the progressive media reveal. |
| revealOrigin | "top" | "center" | "bottom" | "bottom" | Point from which the media mask expands. |
| revealDuration | number | 1 | Media reveal duration in seconds, clamped from 0.55 to 1.7. |
| mediaScale | number | 1.045 | Initial media scale, clamped from 1 to 1.09. |
| contentOffset | number | 24 | Copy entrance distance in CSS pixels, clamped from 0 to 40. |
| radius | number | 28 | Media corner radius in CSS pixels, clamped from 0 to 48. |
| className | string | undefined | Additional classes merged onto the hero root. |
Customisation
Video Reveal Hero exposes three Tier 3 colour tokens. --hero-video-surface sets the media stage behind the poster, --hero-video-border sets its resting frame, and --hero-video-accent colours the small editorial marker. Each defaults to a semantic token, so the section follows dark and light themes without component edits:
:root {
--hero-video-surface: var(--surface);
--hero-video-border: var(--border);
--hero-video-accent: var(--ring);
}Frequently asked questions
- Is Video Reveal Hero free for commercial use?
- Yes. Video Reveal Hero is MIT licensed, so you can use it in personal and commercial projects without attribution.
- How does Video Reveal Hero handle performance and accessibility?
- The stage reserves its aspect ratio before media metadata arrives, and the entrance animates only opacity, transforms, and the documented clip-path exception. The video uses native controls, an accessible label, WebVTT caption tracks, and a visible transcript disclosure. It never autoplays, while reduced motion skips the reveal entirely and leaves every element in its final usable state.
- How can I customise the reveal and media frame?
- Use maskShape, revealOrigin, revealDuration, mediaScale, contentOffset, aspectRatio, and radius to tune the geometry. Override the three hero-video Tier 3 tokens from an ancestor to change the surface, border, and accent while retaining the semantic theme system.