Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# `useMobile()` — viewport-width breakpoint hook
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Returns `true` when the viewport width is at or below the supplied
`breakpointPx` (defaulting to 768px, which mirrors Tailwind's `md`
breakpoint). The hook subscribes to a `matchMedia` listener — NOT a
polling timer — so layout changes propagate without forcing a re-render
on every scroll/resize tick. SSR-safe.
## Features
- Subscribes via `matchMedia` so re-renders happen only on actual
threshold crossings
- Returns `false` server-side (no `window`) so SSR HTML matches the
desktop layout by default
- Configurable breakpoint per-call site
- Cleans up the listener on unmount
## Usage: Basic example
```tsx
import { useMobile } from "@suaveplan/react-ui/hooks/use-mobile";
function Layout() {
const isMobile = useMobile();
return <div data-mobile={isMobile}>{isMobile ? <Drawer /> : <Sidebar />}</div>;
}
```
## Usage: Advanced example
```tsx
import { useMobile } from "@suaveplan/react-ui/hooks/use-mobile";
function ResponsiveTable() {
const isCompact = useMobile(640);
return (
<table>
<thead>
{isCompact ? <th>Item</th> : <><th>SKU</th><th>Name</th><th>Price</th></>}
</thead>
…
</table>
);
}
```
## API Reference
- `useMobile(breakpointPx?: number = 768): boolean`
## Implementation notes
The hook holds a `useState` initialised by reading
`window.matchMedia(...).matches` synchronously inside the initialiser
when `window` is available — this gets the post-mount state right
without an extra render. The post-mount `useEffect` then calls the
listener once to sync against any state drift between SSR and the
client. The `change` listener tears down on unmount AND when
`breakpointPx` changes so a parent that swaps the breakpoint mid-life
gets a fresh subscription. The chassis defaults to 768px (Tailwind's
`md` boundary) but consumers picking other breakpoints get the same
zero-extra-render behaviour. Defensive guards: when `matchMedia`
itself throws (some restricted-permissions browsers), the listener
setup short-circuits and `isMobile` stays at its initial value.

View File

@@ -0,0 +1,91 @@
# `useToast()` — global toast queue
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Global toast queue exposed as a single hook so any component anywhere
in the React tree can enqueue a toast. The chassis treats toasts as a
process-wide UX surface — not a per-tree concern — so the queue lives
in module scope rather than under a Provider. A single root-level
renderer (the `Sonner` component shipping in Wave 3g) reads the queue
and renders the active items.
## Features
- `useToast()` returns the live queue, the `toast(...)` enqueue
callback, and the `dismiss(id)` callback
- Subscribed via `useSyncExternalStore` so re-renders happen only on
actual queue changes
- Branded `TranslationKey` typing on `titleKey` / `descriptionKey`
prevents hardcoded strings from leaking through the toast surface
- OTel counter `react_ui.toast.shown_total{toast.kind}` increments on
every enqueue
- `resetToastQueueForTests()` exposed so tests can isolate per-case
state
## Usage: Basic example
```tsx
import { useToast } from "@suaveplan/react-ui/hooks/use-toast";
function SaveButton() {
const { toast } = useToast();
return (
<button
type="button"
onClick={() => {
toast({
titleKey: "react-ui.loading",
kind: "success",
});
}}
/>
);
}
```
## Usage: Advanced example
```tsx
import { useToast } from "@suaveplan/react-ui/hooks/use-toast";
function ToastList() {
const { toasts, dismiss } = useToast();
return (
<ul>
{toasts.map((t) => (
<li
key={t.id}
data-kind={t.kind}
onClick={() => dismiss(t.id)}
>
[{t.kind}] {t.titleKey}
</li>
))}
</ul>
);
}
```
## API Reference
- `useToast(): { toasts, toast, dismiss }`
- `toast(input: ToastInput): string` — returns the new toast `id`
- `dismiss(id: string): void`
- `interface ToastItem` — `{ id, kind, titleKey, descriptionKey?, createdAt }`
- `type ToastKind = 'default' | 'success' | 'error' | 'info' | 'warning'`
- `resetToastQueueForTests(): void` — test isolation only
## Implementation notes
The queue is intentionally module-level state subscribed via
`useSyncExternalStore` so the React 18+ concurrent-mode guarantees
about subscription consistency apply. Tests that exercise the hook
should call `resetToastQueueForTests()` in `afterEach` to clear the
queue and the listener set; otherwise listener references from prior
tests can leak across the file boundary in some runners. The OTel
counter fires on enqueue; dismissal does not record telemetry by
design (auto-dismiss timers in the renderer would otherwise emit
duplicates).