Zetta v0.10

Foundations

Theming

One foundation, three themes. Light, Dark and Accessibility share every structural token — typography, spacing, radius, motion — and only re-map colour and shadow. A theme is selected by a single data-theme scope; the same markup reskins with zero layout shift.

The same UI, three themes

Identical markup — only the data-theme on the wrapper changes.

Active Draft

A card, a badge and a button — reskinned by the scope alone.

LightWhite canvas and cards; lime brand.
Active Draft

A card, a badge and a button — reskinned by the scope alone.

DarkSlate surfaces; same lime, deeper shadows.
Active Draft

A card, a badge and a button — reskinned by the scope alone.

AccessibilityPure black, white brand, no shadow, 44px targets.

How a theme is applied

Set the scope on <html>. Everything inside resolves its tokens from that theme.

<!-- whole document -->
<html data-theme="dark"> … </html>

<!-- or scope a single region (e.g. a theme preview) -->
<div data-theme="accessibility"> … </div>

Switching at runtime

  • Persist the choice to localStorage and apply it with an inline pre-paint script in <head> — so the theme is set before first paint and there is no flash.
  • Accessibility is explicit. Never auto-flip to it from prefers-contrast or system settings — let the user choose it, and keep their choice.
  • Because only colour and shadow change, switching never moves layout — no reflow, no CLS.

Adding a fourth theme

Define a new [data-theme="…"] scope that supplies the full colour and shadow token set (copy a theme and re-map values — don't leave gaps, or nested scopes inherit the wrong values). Structural tokens stay shared. Then add it to the theme switcher.

The full per-theme values live on the Color tokens and Shadow tokens pages; the high-contrast theme is detailed on Accessibility.