first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# Skeleton
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - skeleton.variants — `skeletonVariants` is the cva (…
- [skeleton.variants](./skeleton.variants.md) — `skeletonVariants` is the cva (class-variance-authority) configuration that powers every `<Skeleton>` render. It is spl…
- skeleton.variants — `skeletonVariants` is the cva (…
- [skeleton.variants](./skeleton.variants.md) — `skeletonVariants` is the cva (class-variance-authority) configuration that powers every `<Skeleton>` render. It is spl…
- skeleton.variants — `skeletonVariants` is the cva (…
- [skeleton.variants](./skeleton.variants.md) — `skeletonVariants` is the cva (class-variance-authority) configuration that powers every `<Skeleton>` render. It is spl…
- skeleton.variants — `skeletonVariants` is the cva (…
- [skeleton.variants](./skeleton.variants.md) — `skeletonVariants` is the cva (class-variance-authority) configuration that powers every `<Skeleton>` render. It is spl…
- [skeleton.variants](./skeleton.variants.md) — `skeletonVariants` is the cva (class-variance-authority) configuration that powers every `<Skeleton>` render. It is spl…
## Purpose
`<Skeleton>` is the chassis loading-placeholder primitive for `@suaveplan/react-ui`. It renders a muted-background `<div>` with a pulse animation that occupies the layout space of content the consumer has not yet finished loading. The pulse animation is gated behind `motion-safe:animate-pulse` so users with `prefers-reduced-motion: reduce` see a static placeholder block; everyone else gets the standard shadcn pulse.
The component is a pure visual placeholder — sizing, layout, and aspect-ratio control come from consumer-supplied `className` (`h-4 w-32`, `h-12 w-12 rounded-full` for an avatar placeholder, etc.). The chassis surface is intentionally minimal so consumers can compose any skeleton layout they need without fighting opinionated defaults.
## Features
- Single `default` cva variant; consumer-supplied `className` carries the sizing.
- `motion-safe:animate-pulse` + `motion-reduce:animate-none` — animation is gated by `prefers-reduced-motion` so reduced-motion users see a static placeholder.
- `data-skeleton="true"` attribute on the rendered element so tests / screen-readers / consumer CSS can target every skeleton placeholder via a single selector.
- Forwards refs to the underlying `<div>`.
- All native `HTMLAttributes` are forwarded as-is so consumers can drop `aria-hidden`, `role`, `id`, `aria-label`, etc.
- Theme variant overrides via `useThemedVariants("Skeleton", skeletonVariants)`. A `ThemePlugin.variantOverrides.Skeleton` may add brand-new variants (e.g. `variant: "shimmer"` for a more elaborate animation).
## Usage: Basic Example
```tsx
import { Skeleton } from "@suaveplan/react-ui";
export function PostPreview() {
return (
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-1/2" />
</div>
);
}
```
## Usage: Advanced Example
```tsx
import { Skeleton } from "@suaveplan/react-ui";
export function UserCardSkeleton() {
return (
<div className="flex items-center gap-3" role="status" aria-busy="true">
<Skeleton
className="h-12 w-12 rounded-full"
aria-label="loading-avatar"
/>
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-32" />
<Skeleton className="h-4 w-48" />
</div>
</div>
);
}
```
## API Reference
### `<Skeleton>`
`forwardRef<HTMLDivElement, SkeletonProps>` — renders a `<div>` with the variant classes + consumer-supplied `className` merged via `cn()`.
#### `SkeletonProps`
| Prop | Type | Default | Description |
|---|---|---|---|
| `variant` | `"default"` | `"default"` | Visual variant; the chassis ships only `default` so themes carry the variation. |
| _all_ `HTMLAttributes<HTMLDivElement>` | _native_ | _native_ | Forwarded as-is (`className`, `style`, `id`, `aria-*`, `role`, etc.). |
#### `skeletonVariants`
The bare cva resolver. Exported so external consumers (`@suaveplan/react-ui-theme-*`, ejected source under `npx shadcn@latest add @suaveplan/skeleton`) can re-use the variants directly without going through `useThemedVariants`.
#### Errors
The Skeleton component does NOT call `useTranslation()` so it does not interact with the i18n provider at all. It is safe to render outside a `<TranslationProvider>` / `<ReactUiProvider>`.
## Implementation Notes
- The chassis hardcodes `motion-safe:animate-pulse` and `motion-reduce:animate-none` into the cva base rather than driving them off `motionTokens.respectReducedMotion` because Tailwind's `motion-safe` / `motion-reduce` variants honour `prefers-reduced-motion` natively at the CSS layer — no JS reactivity required.
- `data-skeleton="true"` is always written so consumer CSS / tests can target every skeleton via `[data-skeleton="true"]`. The chassis does not omit it when other attributes change.
- The variants module is intentionally separate (`skeleton.variants.ts`) so an ejected source copy keeps the cva config in a dedicated file, mirroring the upstream shadcn convention.
- `useThemedVariants("Skeleton", skeletonVariants)` is called unconditionally so the hook order is stable across renders. The hook's memoisation key is `(themeName, "Skeleton")` so a re-render with the same theme returns the same resolver reference.
- `bg-muted` is the cva-applied background colour; the actual colour value comes from the active theme's `cssVariables.muted` token.
- The chassis does NOT inject `role="status"` automatically — consumer composition decides whether the surrounding container should be an ARIA live region. A user-card skeleton is typically wrapped in `<div role="status" aria-busy="true">` so AT announces the loading state once for the whole group, not once per skeleton primitive.