Initial Commit
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user