6.2 KiB
AspectRatio
(no submodules)
- aspect-ratio.variants — `aspectRatioVariants` is th…-
aspect-ratio.variants —
aspectRatioVariantsis the cva (class-variance-authority) configuration powering the<AspectRatio>outer wrapper. I… -
aspect-ratio.variants —
aspectRatioVariantsis th… -
aspect-ratio.variants —
aspectRatioVariantsis the cva (class-variance-authority) configuration powering the<AspectRatio>outer wrapper. I… -
aspect-ratio.variants —
aspectRatioVariantsis th… -
aspect-ratio.variants —
aspectRatioVariantsis the cva (class-variance-authority) configuration powering the<AspectRatio>outer wrapper. I… -
aspect-ratio.variants —
aspectRatioVariantsis th… -
aspect-ratio.variants —
aspectRatioVariantsis the cva (class-variance-authority) configuration powering the<AspectRatio>outer wrapper. I… -
aspect-ratio.variants —
aspectRatioVariantsis the cva (class-variance-authority) configuration powering the<AspectRatio>outer wrapper. I…
Purpose
<AspectRatio> is the chassis fixed-aspect-ratio container built on @radix-ui/react-aspect-ratio. Radix sizes the inner box via inline padding-bottom so the rendered element preserves the requested numeric ratio at every viewport width — the wrapping <div> then serves as a positioning context for any embedded <img>, <video>, <iframe>, or other layout-sensitive child. The chassis layers a small cva recipe (relative w-full overflow-hidden) so embedded media slot in cleanly without consumers having to remember the boilerplate every time.
The component is purely structural — it takes the requested ratio prop, sizes the box, and renders children. No translations, no theming axes, no event handlers. The Radix primitive does not assign a numeric z-index and neither does the chassis, so stacking remains implicit.
Features
- Wraps
@radix-ui/react-aspect-ratiowith a chassis-friendly cva slot. ratioprop accepts any positive number (16 / 9,4 / 3,1,21 / 9, …); Radix interprets it aswidth / height.relative w-full overflow-hiddenbaked in so embedded<img className="h-full w-full object-cover">or<iframe className="absolute inset-0 size-full">children sit correctly.- Forwards refs to the rendered
<div>. - Theme-driven cva override via
useThemedVariants("AspectRatio"). - No translations and no a11y semantics required (the box is layout-only).
Usage: Basic Example
import { AspectRatio } from "@suaveplan/react-ui";
export function CoverImage({ src, alt }: { src: string; alt: string }) {
return (
<AspectRatio ratio={16 / 9}>
<img
src={src}
alt={alt}
className="h-full w-full object-cover"
/>
</AspectRatio>
);
}
Usage: Advanced Example
import { AspectRatio, cn } from "@suaveplan/react-ui";
interface MediaTileProps {
readonly kind: "image" | "video" | "embed";
readonly src: string;
readonly alt?: string;
readonly title?: string;
}
export function MediaTile({ kind, src, alt, title }: MediaTileProps) {
return (
<AspectRatio
ratio={kind === "video" ? 16 / 9 : kind === "embed" ? 4 / 3 : 1}
className={cn(
"rounded-lg border bg-muted",
kind === "embed" && "shadow-md"
)}
>
{kind === "image" ? (
<img
src={src}
alt={alt ?? ""}
className="h-full w-full object-cover"
/>
) : kind === "video" ? (
<video
src={src}
controls
className="h-full w-full object-cover"
aria-label={title}
/>
) : (
<iframe
src={src}
title={title ?? "Embed"}
className="absolute inset-0 size-full border-0"
/>
)}
</AspectRatio>
);
}
API Reference
<AspectRatio>
Renders the Radix Root which constrains the box to the supplied numeric ratio.
| Prop | Type | Default | Description |
|---|---|---|---|
ratio |
number |
1 |
Desired width / height ratio. Radix uses it to compute the padding-bottom percentage. |
className |
string |
none | Additional classes merged via cn() after the chassis cva recipe. |
children |
ReactNode |
none | The content to be sized to the ratio. Position children with className="h-full w-full object-cover" or className="absolute inset-0 size-full" for full-bleed behaviour. |
Forwards refs to the rendered <div> element.
aspectRatioVariants(): string
Returns the chassis cva class string. Takes no arguments. Useful when assembling a custom slot that wants the same recipe without rendering an <AspectRatio>.
Implementation Notes
- The cva carries
relativeso embedded children usingabsolute inset-0(e.g. iframes) anchor correctly. Without it, the absolutely-positioned child escapes to the nearest positioned ancestor. overflow-hiddenis included so rounded corners onclassName="rounded-lg"clip the embedded media — without it,<img>overflow would leak out the corners.w-fullensures the wrapper fills the parent's width; the height is then computed by Radix from the ratio. Consumers can override withclassName="w-1/2"or similar when a fixed-width tile is desired.- The chassis NEVER assigns a numeric
z-index; stacking is the consumer's responsibility (typically managed by a surrounding overlay primitive such as<Dialog>). - Radix's primitive accepts
ratioas a number; passing0or a negative value results in invalid CSS. The chassis does not validate at runtime — supply a positive ratio. - Because the component is purely structural, there are no translation keys to override and no a11y semantics injected. Any media inside should carry its own
alt/title/aria-labelper WAI-ARIA practice.