Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
# AspectRatio
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - aspect-ratio.variants — `aspectRatioVariants` is th…
- [aspect-ratio.variants](./aspect-ratio.variants.md) — `aspectRatioVariants` is the cva (class-variance-authority) configuration powering the `<AspectRatio>` outer wrapper. I…
- aspect-ratio.variants — `aspectRatioVariants` is th…
- [aspect-ratio.variants](./aspect-ratio.variants.md) — `aspectRatioVariants` is the cva (class-variance-authority) configuration powering the `<AspectRatio>` outer wrapper. I…
- aspect-ratio.variants — `aspectRatioVariants` is th…
- [aspect-ratio.variants](./aspect-ratio.variants.md) — `aspectRatioVariants` is the cva (class-variance-authority) configuration powering the `<AspectRatio>` outer wrapper. I…
- aspect-ratio.variants — `aspectRatioVariants` is th…
- [aspect-ratio.variants](./aspect-ratio.variants.md) — `aspectRatioVariants` is the cva (class-variance-authority) configuration powering the `<AspectRatio>` outer wrapper. I…
- [aspect-ratio.variants](./aspect-ratio.variants.md) — `aspectRatioVariants` is 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-ratio` with a chassis-friendly cva slot.
- `ratio` prop accepts any positive number (`16 / 9`, `4 / 3`, `1`, `21 / 9`, …); Radix interprets it as `width / height`.
- `relative w-full overflow-hidden` baked 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
```tsx
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
```tsx
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 `relative` so embedded children using `absolute inset-0` (e.g. iframes) anchor correctly. Without it, the absolutely-positioned child escapes to the nearest positioned ancestor.
- `overflow-hidden` is included so rounded corners on `className="rounded-lg"` clip the embedded media — without it, `<img>` overflow would leak out the corners.
- `w-full` ensures the wrapper fills the parent's width; the height is then computed by Radix from the ratio. Consumers can override with `className="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 `ratio` as a number; passing `0` or 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-label` per WAI-ARIA practice.