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,87 @@
# `useTheme()` — read the active theme registry
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
The primary read-side hook for the chassis theme system. Returns the
active theme, the registered theme list, the `setTheme` callback, the
React-transition `isPending` flag, and the live
`reducedMotionActive` boolean. Throws
`ReactUiError(REACT_UI.NO_PROVIDER)` outside of a `<ThemeProvider>` so
misuses fail fast rather than silently render an unthemed UI.
## Features
- Returns a `ThemeContextValue` snapshot — every field is required
- Throws when called outside a Provider so consumer code surfaces
the misuse at the call site rather than silently degrading
- Pairs cleanly with `useTheme().setTheme(name)` for an
awaitable transition; consumers can `await setTheme('dark')` and
inspect `getComputedStyle(document.documentElement)` immediately
after
## Usage: Basic example
```tsx
import { useTheme } from "@suaveplan/react-ui/theme/use-theme";
function CurrentThemeBadge() {
const { theme } = useTheme();
return <span data-theme-name={theme.name}>{theme.name}</span>;
}
```
## Usage: Advanced example
```tsx
import { useTheme } from "@suaveplan/react-ui/theme/use-theme";
function ThemeButtons() {
const { themes, theme, setTheme, isPending } = useTheme();
return (
<div role="group" aria-busy={isPending}>
{themes.map((t) => (
<button
key={t.name}
type="button"
onClick={() => {
void setTheme(t.name);
}}
aria-pressed={t.name === theme.name}
>
{t.name}
</button>
))}
</div>
);
}
```
## API Reference
- `useTheme(): ThemeContextValue`
- `theme: ThemePlugin` — currently active theme
- `themes: readonly ThemePlugin[]` — every theme registered with the
surrounding `<ThemeProvider>`
- `setTheme: (name: string) => Promise<void>` — async because the
chassis wraps the transition in `useTransition`; `await` resolves
after the React commit but `<html data-theme>` mutation runs in
the following effect cycle
- `isPending: boolean` — true while a `setTheme` transition is in
flight
- `reducedMotionActive: boolean` — live `prefers-reduced-motion`
flag resolved by the Provider
- Throws `ReactUiError(REACT_UI.NO_PROVIDER)` on missing Provider.
## Implementation notes
The hook is a thin `useContext` reader; the heavy lifting lives in
`<ThemeProvider>`. Keeping it slim means it can be called freely in
any component without added rerender cost — a `setTheme` invocation
re-emits the context value (because `theme` and `isPending` change),
which causes every reader to re-render once. Components that should
only re-render on TOKEN changes (not theme name changes) read
`useThemeTokens()` instead of pulling `theme.cssVariables` from
`useTheme()`.