Skip to Content
DocsGuidesDesign Tokens

Design Tokens

When you hardcode Colors.blue or EdgeInsets.all(16) across your app, changing your brand color or spacing scale means hunting through dozens of files. Design tokens solve this: you define a named value once, provide it at the top of your widget tree, and every style that references it updates automatically — including when you switch themes.

Mix provides built-in support for tokens through MixToken and MixScope.

Getting Started

Using a token takes three steps: declare it, provide a value, and reference it in a style.

// 1. Declare the token (the $ prefix is a naming convention to distinguish tokens from regular variables) final $primary = ColorToken('primary'); // 2. Provide the token value via MixScope MixScope( colors: { $primary: Colors.lightBlue, }, child: MyApp(), ); // 3. Reference the token in a style — call() resolves it from MixScope at build time final style = BoxStyler() .color($primary()) .size(100, 100);

MixScope

MixScope is the widget that provides token values to all its descendants. It works like Flutter’s Theme and ThemeData pattern — place it near the top of your tree and every descendant can resolve tokens from it.

MixScope( colors: { $primary: Colors.blue, $background: Colors.white, }, spaces: { $spacingMd: 16.0, }, radii: { $radiusMd: Radius.circular(8), }, child: MaterialApp(home: MyHomePage()), );

Nested MixScope widgets override token values for their subtree. The preview below shows an outer scope providing blue, and an inner scope overriding the same token to red for a child widget:

Resolving preview metadata...

Built-in Token Types

Mix provides token types for common styling needs:

Token TypeValue TypeUse Case
ColorTokenColorColors and backgrounds
SpaceTokendoubleSpacing values (padding, margin)
DoubleTokendoubleAny numeric value
RadiusTokenRadiusBorder radii
TextStyleTokenTextStyleTypography styles
BorderSideTokenBorderSideBorder definitions
ShadowTokenList<Shadow>Text shadows
BoxShadowTokenList<BoxShadow>Box shadows
FontWeightTokenFontWeightFont weights
DurationTokenDurationAnimation durations
BreakpointTokenBreakpointResponsive breakpoints

Using Tokens in Styles

Mix offers two ways to reference a token. Both resolve to the same value — the difference is ergonomics.

The simplest approach. Call the token like a function to get a reference that resolves at build time:

final style = BoxStyler() .color($primary()) .paddingAll($spacingMd());

Prop.token (for directives)

Use Prop.token() with .create() when you need to chain directives on a token value — for example, doubling a spacing token:

final style = BoxStyler.create( width: Prop.token($baseSize).multiply(2), padding: Prop.token($spacingMd), );

For most styles, use the call syntax. Reach for Prop.token() only when you need directives like .multiply(), .add(), or .clamp().

Theme Switching

Tokens make theme switching straightforward: define two maps and swap them in MixScope.

final $background = ColorToken('background'); final $foreground = ColorToken('foreground'); final lightColors = { $background: Colors.white, $foreground: Colors.black, }; final darkColors = { $background: Colors.grey[900]!, $foreground: Colors.white, }; // Swap themes by toggling the map MixScope( colors: isDark ? darkColors : lightColors, child: MyApp(), );

Every style referencing $background or $foreground updates automatically when the map changes.

Resolving preview metadata...

Resolving Tokens Programmatically

You can resolve tokens outside of styles using BuildContext. This is useful when you need a token value in non-Mix code, such as a plain Flutter widget:

@override Widget build(BuildContext context) { final primaryColor = $primary.resolve(context); final spacing = $spacingMd.resolve(context); return Container( color: primaryColor, padding: EdgeInsets.all(spacing), child: Text('Resolved tokens'), ); }

Best Practices

  • Use the $ prefix for token variables ($primary, $spacingMd) — it makes tokens visually distinct from regular values at a glance
  • Use hierarchical names for the token string identifier: ColorToken('color.primary'), SpaceToken('spacing.md')
  • Group related tokens in separate files (tokens/colors.dart, tokens/spacing.dart) to keep declarations organized
  • Prefer tokens over hardcoded values — even if you only have one theme today, tokens make future changes a single-line edit instead of a find-and-replace

Common Pitfalls

Using $token() outside of Mix APIs. Calling a token (e.g. $primary()) returns a placeholder value, not the real resolved value. Mix replaces this placeholder internally when the style is resolved. If you pass $primary() to a plain Flutter widget like Container(color: $primary()), you’ll get the placeholder — not your actual color. Use $token.resolve(context) instead:

// Wrong — $primary() is a placeholder, not a real Color Container(color: $primary()) // Correct — resolve gives you the actual value from MixScope Container(color: $primary.resolve(context))

See Also

  • Styling — using tokens inside styler chains
  • DirectivesProp.token() with .multiply(), .add(), and other transforms
  • Creating Custom Tokens — building your own token types for values not covered by built-ins
  • Theming Tutorial — step-by-step guide to building a full themed app