Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tokens — core primitives

src/tokens/core.rs. The bottom layer: raw const values with no semantic meaning. The semantic layer maps meaning onto these; nothing here references anything else. Every value was decided interactively, value-by-value, against shadcn.

Design rule: atoms never read a raw hex. They read either a core::* primitive (for structural values like spacing/radius) or a Theme field (for colors). The no_raw_values guard enforces it.


Color ramps

Neutral base — Zinc (cool-neutral)

The temperature of every gray surface/border/text token. Tailwind/shadcn zinc, 50→950.

ConstRGBConstRGB
ZINC_50250 250 250ZINC_60082 82 91
ZINC_100244 244 245ZINC_70063 63 70
ZINC_200228 228 231ZINC_80039 39 42
ZINC_300212 212 216ZINC_90024 24 27
ZINC_400161 161 170ZINC_9509 9 11
ZINC_500113 113 122

Brand — Ouroboros turquoise (Teal)

The primary hue: buttons, progress/slider fill, switch-on, focus ring, selection. Kept light (300/400 in dark) per brand. The zinc ramp is left untouched, so a pure-zinc theme stays available (see Theme::zinc_dark).

ConstRGB
TEAL_200153 246 228
TEAL_30094 234 212
TEAL_40045 212 191
TEAL_50020 184 166
TEAL_60013 148 136

Status hues — Tailwind 500

The semantic layer composites the soft *_bg variants by applying ~15% alpha (STATUS_BG_ALPHA = 38) to these.

ConstMeaningRGB
GREEN_500success34 197 94
RED_500error / destructive239 68 68
AMBER_500warning245 158 11
BLUE_400info (text)96 165 250
BLUE_500info (fill base)59 130 246

Spacing — 4px base

Tailwind numeric keys (key N = N × 4px). Contiguous 1–6, then 8/10/12 for larger gaps. Used for padding, gaps, margins.

ConstpxConstpx
SPACE_00SPACE_520
SPACE_14SPACE_624
SPACE_28SPACE_832
SPACE_312SPACE_1040
SPACE_416SPACE_1248

SPACE_0 is the semantic “no gap / no padding” sentinel (tight tables, full-bleed).

Corner radius

shadcn classic base (0.5rem). FULL is the pill/circle sentinel.

ConstpxConstpx
RADIUS_NONE0RADIUS_LG8
RADIUS_SM4RADIUS_XL12
RADIUS_MD6RADIUS_FULL9999

RADIUS_NONE is the “square corners” sentinel (full-bleed rows, flush panels).

Shadows

Dark-tuned (high alpha to read on the zinc background).

ConstUseoffset / blur / alpha
SHADOW_SMfields, chips[0,1] / 2 / 61
SHADOW_MDcards, pills, popovers[0,2] / 4 / 82
SHADOW_LGmodals, overlays[0,8] / 24 / 48

shadow(offset, blur, spread, color) is a const fn builder for elevations beyond the fixed triple (egui’s Shadow is foreign, hence a free fn not an inherent constructor).


Typography primitives

Raw values only — the typography layer composes these into named styles.

Type sizes (px) — dense IDE calibration; body anchors at TEXT_BASE (14).

ConstpxConstpx
TEXT_XS12TEXT_XL20
TEXT_SM13TEXT_2XL24
TEXT_BASE14TEXT_3XL30
TEXT_LG16

Line-height multipliers (× font size): LEADING_TIGHT 1.2 (headings/display), LEADING_NORMAL 1.45 (body), LEADING_RELAXED 1.6 (long-form).

Letter-spacing (px) — scale is inverse to size for legibility (big titles stay NORMAL, smaller text gets wider tracking): TRACKING_TIGHT −0.25, TRACKING_NORMAL 0, TRACKING_SM 0.4, TRACKING_MD 0.6, TRACKING_LG 0.8, TRACKING_WIDE 1.0.


Sizing

Control heightsCONTROL_SM 26 · CONTROL_MD 32 · CONTROL_LG 38. Icon boxICON_SM 14 · ICON_MD 16 · ICON_LG 20 · ICON_XL 24. StrokesBORDER_THIN 1 (divider) · BORDER_FOCUS 2 (focus ring) · RING_OFFSET 2 (gap to ring). Hit targetHIT_MIN 32 (minimum interactive size).

Size enum — the shared control scale

One source of truth for every form control’s footprint, so density (compact toolbar vs. roomy panel) is expressible uniformly.

#![allow(unused)]
fn main() {
pub enum Size { Sm, Md /* default */, Lg }
}
MethodSmMdLg
height()263238
icon_size()141620
pad_x()121616
text_style()¹labellabelbody_strong

¹ defined in theme::typography (keeps core a leaf — see typography.md).


Motion

Animation durations (seconds) + easing curves. egui drives hover/focus transitions by duration (ctx.animate_*); Easing shapes the progress.

DurationsDURATION_INSTANT 0 · DURATION_FAST 0.10 · DURATION_NORMAL 0.18 · DURATION_SLOW 0.30. DelaysDURATION_DELAY_SHORT 0.15 · DURATION_DELAY_LONG 0.50.

Easing enum

#![allow(unused)]
fn main() {
pub enum Easing { Linear, EaseOut /* default */, EaseInOut, Spring, Bounce }
}
VariantCurveUse
Linearidentityconstant motion
EaseOutdecelerateenter/hover (the default)
EaseInOutaccel then decelmoves/reorders
Springovershoot then settle (ease-out-back)playful enters, springy toggles
Bouncedecaying bounces (ease-out-bounce)drops, attention pulls

Easing::apply(t) maps a normalized progress t ∈ 0..=1 through the curve.


Opacity & overlays

ConstValueMeaning
OPACITY_DISABLED0.5the disabled veil
OPACITY_MUTED0.7secondary/muted content
HOVER_OVERLAY0.06white veil over a surface on hover
PRESS_OVERLAY0.12stronger veil on press
SCRIMblack @ 60%backdrop behind modals

Shared helpers

Two functions every atom uses so state is identical everywhere:

#![allow(unused)]
fn main() {
/// Blend a color to its disabled appearance (alpha × OPACITY_DISABLED).
/// Atoms gate it behind `if !enabled` so the veil is applied exactly once.
pub fn disabled_color(c: Color32) -> Color32

/// Eased hover progress in 0..=1 for a widget — animates `hovered` over
/// DURATION_FAST, shaped by EaseOut. Pass a stable id (e.g. response.id).
pub fn hover_t(ctx: &egui::Context, id: egui::Id, hovered: bool) -> f32
}

These are the reason hover/disabled states look the same across the whole library: the math lives in one place, not copy-pasted into 23 atoms.