Basic Modal
A titled dialog with a focus trap, Escape to close and focus returned to the trigger.
6 frameworksIntermediate
A video dialog with a CSS play mockup - no real media - ready to drop your player into.
<!--
A video dialog, mocked. There is no real <video> here - the poster is a
gradient and the play button toggles a CSS timeline - so the snippet ships no
media. Drop your <video> into the aspect-video frame and wire the play button
to its .play()/.pause(). The controls are real buttons at least 40px.
-->
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
<div class="absolute inset-0 bg-black/70" data-modal-close></div>
<div role="dialog" aria-modal="true" aria-labelledby="video-modal-title" class="relative flex max-h-[calc(100dvh-2rem)] w-full max-w-2xl flex-col overflow-y-auto rounded-2xl border border-gray-800 bg-gray-950 shadow-2xl">
<div class="flex items-center justify-between gap-4 px-4 py-3">
<h2 id="video-modal-title" class="min-w-0 truncate text-sm font-semibold text-gray-100">Product tour (2:14)</h2>
<button type="button" aria-label="Close" data-modal-close class="inline-flex h-10 w-10 flex-none items-center justify-center rounded-lg text-gray-400 hover:bg-white/10 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white">
<svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18M6 6l12 12" /></svg>
</button>
</div>
<div class="relative flex aspect-video w-full items-center justify-center bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500">
<button type="button" aria-label="Play video" data-modal-play class="inline-flex h-16 w-16 items-center justify-center rounded-full bg-white/90 text-gray-900 shadow-lg transition-transform hover:scale-105 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white motion-reduce:transition-none">
<svg class="ml-1 h-7 w-7" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z" /></svg>
</button>
</div>
<div class="flex items-center gap-3 px-4 py-3">
<button type="button" aria-label="Play" class="inline-flex h-10 w-10 flex-none items-center justify-center rounded-lg text-gray-200 hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white">
<svg class="ml-0.5 h-5 w-5" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" focusable="false"><path d="M8 5v14l11-7z" /></svg>
</button>
<div class="h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-white/20"><div class="h-full w-0 rounded-full bg-white"></div></div>
</div>
</div>
</div>| Prop | Type | Default | Description |
|---|---|---|---|
openrequired | boolean | - | Whether the component is currently shown. |
titlerequired | string | - | Heading text for the card. |
posterGradient | string | 'from-indigo-500 via-purple-500 to-pink-500' | Poster gradient |
onDismissrequired | () => void | - | Fired when the user dismisses the notification. |
There is no real `<video>` here: the poster is a gradient and the play button toggles a CSS timeline, so the snippet ships no media. Drop your `<video>` into the `aspect-video` frame and wire the play button to its `.play()`/`.pause()`. The controls are real buttons at least 40px, the progress animation is dropped under `motion-reduce`, and the whole thing keeps a focus trap and Escape.