Skill / Refined UI registry
Extension authoring
Author an extension as an optional installable layered on the library — root-mounted for cross-cutting anatomy-attached behavior, anchored for component-scoped fx activated from skin.config.
Goal
Every fx lands on exactly one mechanism, costs nothing when absent, and keeps its a11y/perf guarantees in the component-owned wrapper instead of hand-rolled placement.
Registry-first guidance for installable Refined UI components, skins, hooks, and blocks.
Checks
1Sort the fx first (/architecture#extension-contract): persistent state → plain CSS on the emitted data-state/data-slot anatomy, no mechanism; transient skin-owned event → an anchored extension; per-instance decoration → call-site composition; cross-cutting uniformity → a root extension; behavior needing internals that many skins want → an integrated behavior (lazy + `RefinedSkin` field); everything else → rung 8.
2An anchor is ONE position contract owned by the component: it ships the positioned wrapper (aria-hidden, pointer-events-none, `contain: paint`, clipping) rendered only when `skinAdornment(...)` resolves, and the extension only supplies visuals — never a portal, never its own positioning.
3Anchor ctx carries plain render-time values (a render prop, not React Context); state that only feeds an anchor is guarded by `hasSkinAdornment(...)` so unfilled apps pay no extra update (the `trackSends` precedent in use-chat-input).
4One-shot replay is structural: key the layer on a ctx counter and play a mount-time keyframe/@starting-style that parks invisible; every duration rides `--duration-*` so `data-motion="reduced"` collapses it for free.
5Theme the extension through its own component-local tokens with baseline defaults in its CSS (`--aurora-*`), re-valuable by a pack and overridable inline via a typed prop — never hardcoded colors.
6Root extensions attach by anatomy (`[data-ui="agent"][data-control="true"]`), mount once above their targets (a route segment counts), delegate events, and park when their skin is inactive (liquid-metal's gated observer).
7Ship every extension as its own registry item (`registry:style` or component+CSS) so the install boundary IS the cost boundary; a pack that activates it lists the same files in its manifest so both install paths stay byte-identical (validate-registry allowlist).
8Components without an anchor carry the breadcrumb comment with the canonical slug (`{/* fx anchor candidate: "<component>:<layer>" */}`) — documentation and promotion path, never an activation channel.
Avoid
1CustomEvent buses or context providers to notify a component-scoped extension — the anchored render prop already delivers typed values with no indirection.
2Portals for anchored layers: the component's own stacking context is the contract; a portal escapes the wrapper's a11y/hit-test/containment guarantees.
3Baking an fx into a component because one design wants it — that ships bytes to every install; anchor it and let skin.config decide.
4Presenting the breadcrumb comment as wiring users must fill, or activating extensions anywhere but skin.config (anchored) / an explicit layout mount (root).
Source
Imported as local Refined UI skill guidance, with this repo owning the final wording.
Extension taxonomy & anchor contract
src/registry/skin.ts