Every picker was a hand-rolled popover, listbox and search input. USelectMenu
already does grouped items, an async-friendly search and custom rows, so that
component is gone and both callers use it directly. Typography collapses into
one panel with the three stacks grouped and offering every category, so a mono
heading is possible; radius and the default variants each get their own
control. `--spacing` is dropped entirely, exposing tailwind's base unit as a
theme knob was never good practice.
Fullscreen goes too. Its job was hiding the site chrome, which the page now
does unconditionally, so what remained was a mousemove listener and a manual
Esc handler buying edge-to-edge width. Controls report divergence from the
preset by turning primary instead of carrying a chip, gated on mount because
the theme is restored before first render and hydration adopts the server's
markup without patching.
Carbon, Orchard and 8-bit all set a border darker than the surface it sits
on, the opposite of the stock convention. That read as deliberate while the
borders were 2px with hard shadows behind them; at a stock 1px hairline they
became muddy seams, and 8-bit's literal black on a 21% background vanished.
Light keeps the ink, which is those themes' whole identity.
They only ever existed as static per-component class bundles, including a
verbatim copy of the private `ssr()` modifier chain from `src/theme/tabs.ts`,
plus site-wide `--shadow-*` and `--default-border-width` overrides in
`main.css`. They come back in v5 on real tokens. An 8-bit export drops from
389 config lines to 68.
Fonts become three independent stacks rather than a family plus a heading
treatment. Preflight already wires `--font-sans` and `--font-mono`, so only
the serif needs an element rule, and it is emitted only when one is set. The
two runtime channels behind them collapse into one, and the engine's nine
modules into five.
Every setting owned a localStorage key, sixteen of them, and two of those
were derived caches of the others. Restores could interleave, so the derived
stores each needed a self-heal to reconcile, and eight FOUC scripts each
re-read their own key and re-derived a slice of useTheme's style tags.
One key writes atomically, so those states cannot disagree. The style class
bundle and the custom-palette ramps are rebuilt from their source on load
instead of stored, which removes two of the three heals outright. Reads and
writes both live in the plugin, so no composable touches localStorage.
The nine keys the shipped picker wrote migrate once per browser.
Also groups the theme utils under utils/theme/, with the 646-line theme.ts
split by concern and theme-engine moved to utils/theme/engine.
A renamed preset leaves an id naming nothing while the theme it applied
still sits in the other storage keys, so the pickers read Custom against
a page no preset can name.
Shadcn, Bootstrap, Anthropic and Spotify become Mono, Cobalt, Parchment
and Signal, with generic lucide glyphs. Cobalt's palettes were named
bs-blue/bs-gray, which put the brand in every exported main.css, so they
are renamed too.
Reverts collateral edits that were out of scope for a docs branch: the
em dash replacements across src/runtime/types, test/bench and the AI
prompt text, the devtools toggle and the .gitignore entry.
Also fixes the ring-N scanner in the theme importer, whose consumed
separator hid every second adjacent token, and stops the theme engine
specs running in both vitest projects when they need neither.
- `as any` on the Modal `tv` call
- never-assigned `completed` ref in PinInput
- `@defeaultValue` typo in PricingTable
- unreachable `InferInput` branch, already matched by the first
- empty `compoundVariants` in the color-picker theme