Anvil2 supports theming so apps can reflect product branding and react to user mode preferences. This page covers how the token cascade works and where to apply overrides.Documentation Index
Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
Use this file to discover all available pages before exploring further.
How the token cascade works
Anvil2 tokens are organized in three tiers: primitives (raw values), semantic tokens (values with purpose — e.g.background.color.primary), and component tokens (values scoped to one component — e.g. button.primary.background.color). Each tier references the tier below it: component tokens reference semantic tokens, and semantic tokens reference primitives. Tiers are never skipped.
Overriding a token fans out to everything that references it. Override background.color.primary and every component that consumes it — Button, Alert, Badge, and many more — updates together. Override button.primary.background.color and only Button changes. Primitive overrides do not cascade at runtime; see Cascading limitations below.
Overriding at the semantic level (tier 2)
Use this for bulk theming — reshaping the design system to match a product brand. The standard way isThemeProvider:
Overriding at the component level (tier 3)
Use this to customize a single component without touching anything else. Same shape as semantic overrides, with acomponent object:
/tokens tab.
Cascading limitations
Tier-1 primitive overrides don’t cascade at runtime. Component and semantic tokens embed the resolved primitive value at build time (vialight-dark()), so changing ColorBlue500 through ThemeProvider has no effect on BackgroundColorPrimary or ButtonPrimaryBackgroundColor. Override at tier 2 or tier 3 instead.
Prefer ThemeProvider over raw CSS variables. ThemeProvider kebabizes keys, prefixes with --a2-, and wraps light/dark values in light-dark() automatically. A raw CSS override has to do all three manually and drops dark mode support if only a light value is supplied.
Dark mode
Design
Anvil2 Figma assets use variables for light and dark mode. Refer to Figma’s guidance on how to switch between modes.Code
Toggle app-wide mode viaAnvilProvider:
AnvilProvider includes a ThemeProvider under the hood. To change the theme of part of a page without affecting the rest, use ThemeProvider directly:
How light-dark() works under the hood
Every themed CSS variable is authored as light-dark(<light>, <dark>). The ThemeProvider component flips which branch is live by applying a .mode-light or .mode-dark class that sets color-scheme: light or dark on the subtree:
light-dark() against color-scheme, so toggling the class is enough — no JavaScript re-render of styles is needed.
How ThemeProvider picks up dark values automatically
When you override a token without supplying a dark value, ThemeProvider falls back to the base token’s extensions.appearance.dark.value for the dark branch. In practice this means you can write a single-value light override and dark mode keeps working.
Related
- Design Tokens — complete tier and category reference.
- Each component’s
/tokenspage lists its tier-3 tokens and override examples.