Skip to content

Overview

Mirror splits its tokens into a primitive layer and a semantic one. Read this when a token path turns up in a theme file, a stack trace or an --app-* variable.

View source View as Markdown

Day to day you write class names rather than token paths, so this page is here for the moments when a name in a theme file, a stack trace or an --app-* variable needs decoding.

Mirror tokenises colour, radius, shadow and typography, plus border width and outline width.

Border width and outline width are the exception because they set the focus ring, and a theme that shrinks that ring to nothing leaves keyboard users with no way to see where they are.

Two layers

config holds the primitives, meaning the palettes, the radius base and the font weights. It is referenced and never consumed directly.

app holds the semantics, meaning what a thing is for, and it is the layer application code reads.

config.color.palette.grey.solid.15     a colour
app.color.component.primary.bg.solid   the default fill of a primary control

Reading a colour path

Every colour token is app.color.<group>.<role>.<rung>[.<state>].

  • The group is surface for page and container chrome, or an intent such as primary, secondary, accent, danger, success, warning, neutral, disabled, focus and shadow, with the intents nesting one segment deeper under app.color.component.
  • The role is bg, fg or border.
  • The rung is solid for opaque, muted for the stronger overlay and subtle for the lighter one, while ink that sits on a fill is onSolid, onMuted or onSubtle.
  • The state is default, hover or active, wherever the rung has them.

Border has a single rung on the intent groups, subtle, which is covered in Color.

A path is longer than its class

Two segments drop out everywhere a name is produced, the component segment and default.

app.color.component.primary.bg.solid.hover
--app-color-primary-bg-solid-hover
bg-primary-solid-hover

The difference is mechanical, so a class name maps back to a path and a path forward to a class name. Both segments stay in the source because the compiled js, ts and json outputs are nested trees that the utility generator addresses literally.

Where the values come from

Mirror ships no compiled token file of its own. mirror tokens reads the source named in mirror.config.ts, either a Git repository or a directory in your project, and compiles it into .maas/tokens/, one directory per platform.

Further reading

  • Configuration: which platforms build, and which targets come out.
  • CLI: the three commands and the config file they read.