Variables
Export the compiled tokens as Figma variables, and update every mode in place as the tokens change.
Mirror’s tokens reach Figma in two halves. Colors, dimensions and the singular typography values become Figma variables, imported with Figma’s own variable import, and the composites a variable cannot hold, meaning text styles and effect styles, go in through a plugin we ship. This page covers the variables half; Styles covers the plugin. Both halves update what is already in the file when you re-run them, and neither ever deletes anything.
Everything below describes the export built from our standard token set. The same commands work against a token set of your own, with the collections read off your config instead of ours; see Custom Tokens for what changes.
Generating the export
pnpm mirror tokens
pnpm mirror figma
mirror tokens compiles the token source into .maas/tokens/, and
mirror figma reads that compiled output and nothing else, so the two run in
this order. The command needs the json platform in options.platforms of
mirror.config.ts and stops with an error naming the key without it.
The export is written to .maas/figma/, one directory per variable collection
with one DTCG file per mode, plus the styles.json payload the plugin reads.
Built from our own token set, that comes out as follows.
.maas/figma/
color/base.json
color/dark.json
dimension/base.json
typography/base.json
typography/mono.json
typography/sm.json
styles.json
styles.json takes no part in the variable import. It is the one input of the
Mirror Styles plugin, and Styles covers what it does.
Which collections and modes come out is stated in figma.collections of
mirror.config.ts, and the key is required. Our stock config, which
mirror init scaffolds, declares the three collections in the listing
above; this is its color entry.
figma: {
collections: [
{
name: 'Color',
types: ['color'],
modes: [
{ name: 'Base', targets: ['application'] },
{ name: 'Dark', targets: ['application', 'theme/dark/application'] },
],
},
],
}
name is the collection in Figma and the directory its mode files are
written into, types names the source $type values that belong to it, and
each mode lists the targets it reads. Typography declares Base, Mono and
SM modes the same way, which is why the mono theme’s file sits under
typography and not under color, and Dimension declares Base alone. A run
without the key fails, and the error prints a suggested roster read off your
targets, ready to paste into the config.
Custom Tokens documents the
full shape of the key.
Every value in the files is a resolved literal, with colors converted to sRGB and rem sizes multiplied out to pixels, so no collection depends on another being imported. Each entry includes a description naming the token path and its authored value, so a variable in Figma traces back to the token it came from.
Before anything is written, the command checks that every mode file of a collection holds the identical set of variable names and types, and a mismatch fails the run naming the collection, the mode and the missing names. Figma creates a variable only when it appears in every file a new collection is built from, so a hole in one file would silently drop the variable from all of them. The output directory is cleared and rewritten on every run, so a mode that leaves the config also leaves the disk.
Importing the variables
The mode files go in through Figma’s own variable import rather than through the plugin. A variable is addressed by an internal ID, and every layer and style that uses it points at that ID, so an update has to change values without recreating variables, and Figma’s importer is where that is handled correctly.
To create a collection, open the Variables panel in your Figma file, create an empty collection, and drag all of the collection’s mode files into it together. Each file becomes one mode.
To update after a re-run, right-click the mode, choose Import mode, and pick
the regenerated file. Variables are matched by name and type, and their
values are updated under the same ID, so everything pointing at them keeps
working. Mode names take no part in the matching, so a designer who renames
Base to Light in Figma changes nothing about how updates arrive.
To adopt a theme later, import its file as a new mode of the same collection, once.
Names
The variable names are the token paths, slash-joined. Color names drop
app.color. and the component segment, since nearly every semantic color
lives under it, and they keep default, so the hover and active variables
sit next to it in the panel. Everything else drops the leading app. alone.
The import never deletes. A renamed token arrives as a new variable and leaves the old one behind with nothing pointing at it, and removing the orphan is a decision made in Figma rather than by the import.
What a re-run changes
The variables and the text styles split the work. The styles are bound to the variables, so a value-only token change is finished once the affected modes are re-imported, and the plugin only enters when the set of styles itself changes. That second case is covered on Styles; the rows below are the variable half.
Further reading
- Styles: the text and effect styles, and the plugin that writes them.
- Custom Tokens: the same export built from a token set of your own.
- CLI: the command, and the arguments the build commands share.
- Configuration:
mirror.config.ts, which holds the targets and thefigma.collectionsroster the export reads.