ContainersEmbed
Embed
A video, an iframe, or an audio block. Always 16:9 by default; the parent decides the cap on width.
Demo
The default is a 16:9 video placeholder. The aspect ratio is enforced by the parent, not the embed.
Default
Anatomy
- 1 px
--line-strongborder, 4 px radius - Aspect ratio enforced by
aspect-ratioCSS, not padding-hack - Title attribute is set on the iframe for screen-reader access
- Caption sits below, optional, same style as the Figure caption
Implementation
embed.tsx
import { type ReactNode } from "react"
import { cn } from "@/lib/utils"
type Kind = "video" | "iframe" | "audio"
type Ratio = "16/9" | "4/3" | "1/1" | "9/16"
interface EmbedProps {
kind?: Kind
src: string
ratio?: Ratio
title: string
caption?: string
}
export function Embed({ kind = "iframe", src, ratio = "16/9", title, caption }: EmbedProps) {
return (
<figure className="ds-embed">
<div className="ds-embed__frame" style={{ aspectRatio: ratio }}>
{kind === "video" ? (
<video src={src} title={title} controls preload="metadata" />
) : kind === "audio" ? (
<audio src={src} title={title} controls preload="metadata" />
) : (
<iframe
src={src}
title={title}
loading="lazy"
allowFullScreen
referrerPolicy="no-referrer-when-downgrade"
/>
)}
</div>
{caption ? (
<figcaption className="ds-figure__caption">
<span className="ds-figure__caption-title">{title}</span>
{caption}
</figcaption>
) : null}
</figure>
)
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
kind | "video" | "iframe" | "audio" | "iframe" | Embed kind |
src | string | None | Required: the source URL |
ratio | "16/9" | "4/3" | "1/1" | "9/16" | "16/9" | Aspect ratio |
title | string | None | Required: accessible title |
caption | string | None | Caption below the embed |
Accessibility
- The
titleprop is required and is the accessible name. - Captions are encouraged for video, required for any embed with dialogue or audio.
- Autoplay is disabled by default. Autoplay with muted audio is allowed only on the marketing home hero loop.