Skip to content

DesignSystem

Edgar Mesquita edited this page Jul 31, 2026 · 4 revisions

Photon Design System

The design system behind the write-once components: a complete token/component specification (authored with Claude Design, preserved in-repo at docs/design/Photon-Design-System.dc.html — the source of truth) implemented as typed C# tokens in eQuantic.UI.Primitives and consumed by every realization target.

Token layers (§01–§09)

  • Colors — every color is a paired light/dark ColorToken; components never hold raw colors. Interactive variants resolve five sub-tokens (Base, OnBase, Pressed — a real token, not an overlay — Subtle, OnSubtle). Disabled is not a color: it's a 38% opacity group.
  • Type scale — role-driven (DisplayBodyM, Caption, Label) with Dynamic Type clamps per role.
  • Spacing (Space.S1S16, 4dp base, gap-owned — no margin exists), radius (Radius.XsFull, engine-clamped), icon sizes (§07 whitelist 16/20/24/32 — arbitrary sizes throw), touch (≥48dp hit contract), elevation (one analytic shadow per node), motion (durations + curves + spring).

Spec fidelity is tested, not aspired to

  • Token values are pinned; WCAG contrast is recomputed in tests for every claimed pair.
  • Component metrics come from the spec tables (e.g. Button's size table: 32/40/48/56 heights) and are asserted on every axis: C# web realizer pins, native golden images (light + dark), transpiled-fixture execution in vitest.
  • The style resolver rules (derived Outline/Ghost/Link variants, pressed-as-token-swap, focus double-ring) live in target-neutral C# (ButtonStyles).

The "generated, never hand-written" rule

Client-side artifacts carrying design-system values are generated from the C# single source and byte-pinned in CI (a drift fails the build; env-var flows regenerate):

Artifact Generator Regenerate with
Normative stylesheet (custom properties, .eq-type-*, .eq-elevation-*, motion vars) PhotonCssGenerator (pure function — tested per value)
design-system.generated.ts (tokens, theme object, Button size table) DesignSystemTsGenerator EQ_UPDATE_DESIGN_TS=1
icons.generated.ts (glyph path data) IconTsGenerator EQ_UPDATE_ICONS_TS=1
Embedded transpiled component modules live eqc output EQ_UPDATE_TRANSPILED=1

The same rule powers hydration: SSR (C# realizer) and client lowering (TS) are held byte-identical by cross-pinned literals in both test suites.

Icons pipeline (spec A10)

A curated Icons enum (16 glyphs and growing) with the path data living once in the C# IconRegistry (24×24 single-path alpha masks): the web emits inline <svg fill="currentColor"> (the tint rides the color token exactly like text), the TS side consumes the generated module, and the future native glyph atlas rasterizes from the same registry. Outline ↔ filled are distinct glyphs; icons ignore Dynamic Type.

Styling without CSS — the atomic engine (Track S, 2026-07-30)

Authoring is 100% typed C# (BoxStyle, StyleDiff, tokens) — there is no CSS plane. Three laws govern the web realization:

  1. One semantics — the same style vocabulary drives dp values on Photon and CSS on web.
  2. No expressiveness ceiling — Wrap, Grid, AspectRatio, AlignSelf, group Opacity, static Transform2D, Hover/Focus state diffs, window-size-class adaptivity (AdaptiveNode), Sticky, ZIndex, both-axis scroll.
  3. No rewrite by construction — every regular declaration lowers to ONE deduplicated atomic class (eq- + FNV-1a hash of prop:value); theme colors reference var(--eq-color-*); SSR collects the page's rules into a single <style id="eq-atomic"> the client adopts by identity (hydration = class equality, enforced end-to-end by the e2e identity test). ~118 rules / 4.8 KB covered the entire showroom.

Pseudo-states lower to pseudo-variant atomic rules (:hover/:focus-visible — zero JS); size classes to fixed media-gate classes. The C# StyleAtomizer and the TS style-atomizer.ts are byte-identical twins (cross-pinned fixture).

Theming = providing an IAppTheme

One interface (colors as light/dark ColorToken pairs, type roles, shape scale, elevation specs, disabled opacity), selected via AddUI(...).UseTheme(...) and bridged SSR→client. Two implementations ship: PhotonTheme (the default) and MaterialTheme (real Material 3 — MaterialTheme.Instance baseline or FromSeed(color) dynamic color via a CAM16/HCT port validated against Google's values). Shape is theme-driven; the same component tree rebrands with one line.

Clone this wiki locally