Menu
Public repository / 439f0dcabf5cdf2b120c7724be895cf1df30507f
AkurAI-Framework / site/content/docs/design-system/foundations.md
Latest change d3aacc97a3d97591d3118c06cb7678a33241191b - docs: document v0.8.0 named theme system by Ólafur Búi Ólafsson
# Foundations
The foundations are the design tokens every component reads from. They are plain
CSS custom properties declared once on `:root` in `styles.css` — no
preprocessor, no theme compiler. Change a token, reload, and every component
that consumes it updates. Components must never hard-code a colour, radius, or
shadow; they reference a token so the system stays coherent and themeable.
> **Status legend** — ✅ shipped · 🟡 partial · ⬜ planned. Foundations marked
> ⬜ are tokens we intend to add as the system grows; they are named here so
> components can be specified against them before they land.
## Colour ✅
Surfaces, from furthest-back to nearest-front, then text, then semantic accents.
The token names below are the **stable contract** every component reads. Their
values come from the active theme — the multi-theme system ships 17 named themes
in both dark and light variants (see [Themes](/docs/design-system/themes)).
Values shown are the AkurAI default (dark).
```
--bg #0a0c11 page background (deepest)
--bg-2 #0f131b recessed background
--panel #141925 raised surface (cards, inputs)
--panel-2 #1a2030 raised surface, one step up
--border #232b3b hairline divider / control border
--border-2 #2c3650 stronger border (hover, emphasis)
--fg #e7ebf3 primary text
--muted #8a93a8 secondary text, labels
--dim #5c647a tertiary text, disabled
--accent #5b8cff brand / primary action
--accent-2 #8a6bff gradient companion to --accent
--ok #3ddc84 success
--warn #f5b945 warning
--info #58b2ff info
--danger #ff6b6b error / destructive
```
**Usage rule** — text colour comes from `--fg` / `--muted` / `--dim`; never set a
raw hex in a component. Semantic colours (`--ok`/`--warn`/`--info`/`--danger`)
are only for status meaning, never decoration. Tints are derived live with
`color-mix(in srgb, var(--ok) 10%, var(--panel))` rather than hand-mixed hexes.
## Typography 🟡
One system font stack today; a token-driven type scale is planned so headings,
body, and captions all snap to fixed steps.
```
--font-sans ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif ✅
--mono ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace ✅
--text-xs 12px / 1.4 ⬜ captions, eyebrows, table headers
--text-sm 13px / 1.5 ⬜ labels, secondary
--text-base 16px / 1.65 ⬜ body (current default)
--text-lg 19px / 1.5 ⬜ lede
--text-xl 24px / 1.2 ⬜ section titles
--text-2xl 30px / 1.15 ⬜ page titles
--text-3xl clamp(34px,6vw,60px) ⬜ hero
```
**Usage rule** — body sets `font: 16px/1.65 var(--font-sans)`. Headings use
negative letter-spacing (`-0.02em` to `-0.03em`) for tightness. Code uses
`var(--mono)` at ~0.88em of its context.
## Spacing ⬜
The grid is implicit today (per-component padding). We want one 4px-based scale
so gaps and padding are never arbitrary.
```
--space-1 4px --space-4 16px --space-8 48px
--space-2 8px --space-5 24px --space-10 64px
--space-3 12px --space-6 32px --space-12 88px
```
**Usage rule** — once shipped, every `gap`/`padding`/`margin` resolves to a
`--space-*` step. Component demos already cluster at 12/14/18/24px — those become
`--space-3`/`--space-4`/`--space-5`.
## Radius ✅
```
--radius 14px ✅ cards, panels, large surfaces
--radius-sm 9px 🟡 inputs, small controls (in use, not yet tokenised)
--radius-btn 10px 🟡 buttons (in use, not yet tokenised)
--radius-pill 999px 🟡 badges, pills, status dots
```
**Usage rule** — promote the in-use literals (9px/10px/999px) to tokens so the
whole system rounds consistently.
## Elevation & shadow ✅
```
--shadow 0 24px 60px -28px #000 ✅ floating panels, dropdowns, modals
```
Buttons and inputs carry their own focal glow rather than a drop shadow:
`box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent)` for
focus, `0 10px 26px -12px var(--accent)` for the primary button. A small set of
elevation steps (`--shadow-sm`/`-md`/`-lg`) is planned ⬜.
## Motion ⬜
Interactions today use ad-hoc durations (`transform .04s`, `filter .15s`). We
want a motion scale so every transition feels of one piece.
```
--ease cubic-bezier(.2, .7, .3, 1) ⬜
--dur-fast 80ms ⬜ press, hover
--dur-base 150ms ⬜ colour / background
--dur-slow 240ms ⬜ overlays entering
```
**Usage rule** — respect `prefers-reduced-motion`; overlays and toasts must drop
to opacity-only transitions when it is set.
## Z-index ⬜
A named stacking order prevents overlay wars. Current literals: nav `20`. Target:
```
--z-base 0 --z-dropdown 1000 --z-toast 1200
--z-sticky 20 --z-overlay 1100 --z-tooltip 1300
```
## Breakpoints 🟡
One breakpoint exists today; we name the rest for responsive component specs.
```
sm ≤ 640px ⬜
md ≤ 820px ✅ (the current grid-collapse point)
lg ≤ 1080px 🟡 (container max-width)
xl ≥ 1280px ⬜
```
## Theming ✅
Because everything is tokens on `:root`, a theme is just an alternate token set.
The framework ships 17 named themes in dark and light variants, generated by
`crates/css::theme` into `/themes.css`. Each theme is a
`:root[data-theme="slug"]{…}` block that sets all the tokens above. The first
theme (`akurai`) is also emitted as the bare `:root` default so a page without an
explicit `data-theme` still renders correctly.
A zero-dependency ESM switcher (`theme.js`) reads `localStorage` and
`prefers-color-scheme` to select a theme before first paint, and mounts an
optional picker wherever a `[data-theme-picker]` slot exists. See
[Themes](/docs/design-system/themes) for the full theme list, wiring guide, and
instructions for adding a new theme.