Appearance
Entity Types
Surfaces (Level Entities)
Surfaces are the foundational background layers of a UI. Think of them as stacking cards: the base layer (Surface 0) sits at the seed tone, and each subsequent level shifts further away in contrast. In a light theme with direction "down", Surface 0 might be near-white, Surface 1 slightly darker, Surface 2 darker still.
Why surfaces matter: They establish the visual depth hierarchy. A card sits on a page, a dropdown sits on a card, a tooltip sits on a dropdown. Each nesting level needs a distinguishable background tone while maintaining the same hue character.
Level patterns explained:
- Single level (
flat) -- one surface at a fixed contrast from seed. Use when your design has no depth nesting (e.g., a flat dashboard). - Even steps (
stepped) -- N surfaces, each the same contrast step from the previous. The most common pattern: 3 levels at ×1.1 creates a smooth progression. The "step" is a contrast ratio multiplier chained from level to level. - From seed (
anchored) -- each level is computed independently from the seed tone at its own contrast ratio. Gives full control: Surface 0 at 1.1:1, Surface 1 at 1.5:1, Surface 2 at 2.0:1. Levels don't depend on each other. - Custom steps (
chained) -- like "From seed" but each level chains from the previous level's tone, not from seed. Useful when you want decreasing steps: first jump big, subsequent jumps smaller. - Alternating (
alternating) -- exactly 2 levels alternating from seed. Useful for zebra-striped lists or alternating row backgrounds.
Surfaces don't iterate interactions or conditions -- they are static backgrounds. Their token paths omit those segments.
Containers (Frame Entities)
Containers are semantic regions that sit on top of surfaces: buttons, cards, input fields, chips, tags. Each container is defined by a contrast ratio relative to the surface it sits on.
Why containers matter: A button on Surface 0 needs a distinguishable background. At contrast ratio 1.6:1, it's visually distinct but subtle. At 4.6:1, it's a strong call-to-action. By defining contrast ratios (1.6, 3.1, 4.6, 7.1), you get 4 container depth levels per surface level.
Containers iterate per-entity interactions and conditions, so the same button has different tones across pointer events (hover, focus, press) and macro-modes (Selected, Disabled).
Inverse containers (inv-containers) are automatically generated with the flipped tone direction. If your light theme pushes containers darker, inv-containers push lighter. This gives designers a pair for every container: dark-on-light and light-on-dark, both mathematically guaranteed.
Content (Top-Layer Entities)
Content sits on top of surfaces and containers: text, icons, borders, decorative elements. Each content token is a color at a specific contrast ratio from its parent background.
Why content matters: Text on a button needs WCAG-compliant contrast. By defining contrast chips (1.6, 3.1, 7.1, 12, 16), you get a range from subtle hints to maximum-contrast headings, each computed from the actual container tone.
Inverse content (inv-content) uses the base direction hue but the flipped direction tone. When a surface crosses the tone-50 threshold, normal content may be dark-on-dark -- inv-content provides the light-on-dark alternative.
Content on containers is generated per surface level × container level. Collection names include the frame level index to avoid duplicate variable names: content-on-containers/surfaces-0/containers-0, content-on-containers/surfaces-0/containers-1, etc.
Scrims (Overlay Entities)
Scrims are floating overlays: modal backdrops, bottom sheet dimming layers, toast backgrounds. They're computed from the seed tone, independent of surface hierarchy.
Why scrims matter: A modal overlay needs a semi-transparent darkening layer. By defining scrims with contrast ratios, you get mathematically computed overlay tones that maintain the theme's hue character.
Scrims don't iterate interactions or conditions (like surfaces). Their token paths omit those segments.