Files
WRNexusJS/docs/plans/2026-10-19-design-system-phase-2-implementation.md
T

7.4 KiB
Raw Blame History

Phase 2 — core component contracts, recipes and presets

Status: implemented for 14 core components. Date: 2026-10-19. The remaining 90 catalog entries keep their legacy-uncontracted status; Phase 3 handles broader rollout.

Implementation

Version-1 descriptors and additive hooks cover Button, Input, Textarea, Select, Checkbox, Radio, Switch, Card, Alert, Modal, Nav, ContextMenu, PageHeader and Container. Descriptors include source, family, parts, allowed properties, axes/defaults/values, state mappings, slots, token references, constraints, fixture targets and engine compatibility. They are available through the engine and the optional @wrnexus/ui/design-contracts export. Existing component props, outputs, slots and styles were retained.

The specification now accepts component recipes with a contract version, base part styles, ordered variant/compound rules and ordered state rules. Inherited base properties merge by part; rule arrays append. Validation rejects unsupported contracts, parts, axes, states, properties and typed references. Recipe CSS cannot change event handlers, arbitrary selectors, HTML, positioning, clipping or visibility. A bounded individual rotate property composes with existing interaction transforms; a backgroundImage: none reset handles legacy button gradients without allowing image URLs.

Each part carries its component owner and local axes, preventing ancestor-variant leakage. Conditions have zero specificity so ordered rules determine the result. Guards preserve explicit pill, radius/shadow, field variant and nondefault size/color choices. Legacy-bound token references continue through app-overridable variables. Recipe specificity and late insertion beat the existing local styles without !important.

The styles resolver attaches optional compiled recipe CSS to the resolved theme. Shared development/production SSR emits this after extracted component styles with the request CSP nonce. Custom document shells and streamed output retain the recipe block. Token delivery remains in the existing theme assets. Without recipes, no additional style block is emitted. The package root remains browser-safe and dependency-free.

Scoped compilation stops at nested design owners and works regardless of stylesheet order. Scope identifiers must be unique across nested islands. Current overlay implementations stay within their owner tree, so their panels inherit that context; this is not a promise for future externally portalled implementations. Ejected components without hooks remain application-owned.

Three systems

System Direction Button / card / dialog radius Typography Additional treatment
Square Industrial, compact 0 / 0 / 0 Monospace Black/amber dark mode, outlined actions, flat panels
Soft Organic, spacious 16 / 24 / 32 px Warm serif Sand/sage light mode and rounded surfaces
Angular Lo-Fi, expressive 0 / 0 / 0 Mixed system sans/serif Paper-yellow light mode, −2° actions, 1° panels, hard shadows

All systems provide light/dark colors, primary hover/active/contrast roles, surfaces, typography and geometry. Existing semantic feedback roles retain their semantics. These are component systems, not complete page-builder templates.

Verification

  • Engine, CLI, styles, UI, SSR and theme-runtime regression suites: 341 tests pass, zero failures across 30 files. Focused engine/theme/CLI type checking, new-source lint and formatting checks also pass.
  • All descriptor parts/axes are checked against source hooks.
  • Invalid contracts/properties/references and deterministic preset output are covered.
  • Tests cover explicit pill/size/color/radius/shadow choices, compound/state precedence, nested components and design islands, inline scoped dialogs, typography/layout props, hydration and CSP-protected SSR output.
  • Native in-app browser verification covered all 12 combinations: three systems × light/dark × linked/inline token CSS. Button gradients were removed correctly; button/input/card radii and rotations matched the systems; labels remained readable and no desktop horizontal overflow was observed.
  • Native form typing, language selection and switches worked under all three systems. Dialogs opened, received/trapped focus, closed with Escape and restored the trigger focus. Context menus opened and closed from their focusable items. Keyboard focus remained a visible 2px solid outline under all three systems.
  • All three 390×844 layouts used one column with no horizontal overflow.
  • Recipe output is approximately 65–68 kB uncompressed and 2.1–2.2 kB gzip per preset; authoring metadata is optional for UI consumers. These are current observations, not a permanent performance budget.

Screenshots and browser observations are saved in output/design-system-phase-2/: six desktop mode captures, three mobile captures, a dialog capture, browser-checks.json and focus-checks.json. They are review artifacts, not an automatically maintained screenshot-diff baseline.

Preview Screenshot
Square dark Capture
Soft light Capture
Angular light Capture
Soft mobile Capture
Soft dialog Capture

Run and use

Run bun run scripts/preview-design-systems.ts, then open the printed local URL. The preview is a developer fixture with authored static content and no submitted server mutations. The isolated ContextMenu fixture supplies trigger slot content explicitly because the test renderer has no parent slot distributor.

Use theme: { designSystem: { system: SOFT_DESIGN_SYSTEM } } to apply a preset in an application. See engine documentation for extension recipes, scope boundaries, APIs and CLI commands. The coverage matrix reports the current per-component status.

Limits and next phase

This delivery does not implement the Design Studio, AI generation or MCP mutations. Unknown/custom components need their own contracts; provider-rendered pixels and native Select option popups are outside CSS recipe control. General conformance/accessibility certification, repeatable screenshot-diff automation, additional browsers and the remaining catalog families belong to subsequent work.

Existing workspace-wide type/API drift is kept separate from this change; public API and visual hash baselines are updated only for the engine/UI contracts and the 14 reviewed core component sources. The new engine and UI-contract export baselines match extracted APIs. Global type/API checks and the full visual-hash check still fail on pre-existing issues or baseline drift outside this scope; those files were not accepted by a wholesale baseline refresh. Other uncommitted work is preserved.