Style Dictionary
The Style Dictionary build of Chassis Tokens, with its commands, build options, platforms, presets, generated files, transforms, filters, and formats.
This page is a work in progress. Parts of it may be incomplete or differ from the current version of Chassis Tokens.
Introduction
Chassis Tokens builds its tokens with Style Dictionary 5 and @tokens-studio/sd-transforms 2. The build reads the token sets that Tokens Studio writes to packages/tokens/source/, and writes SCSS, Swift, Android resources, and Kotlin to packages/tokens/dist/.
This page is the reference of the build for a team that builds its own tokens: how to run and configure the build, which platforms and presets it has, which files it writes, and which transforms, filters, and formats it registers. docs/architecture.md explains why the build works this way and holds the full output contract.
The build, its configuration, and its output are in packages/tokens/, the folder of the published package. Paths on this page that start with source/, build/, dist/, or test/ are relative to that folder.
The generated code on this page shows the format of each platform. Its values are those of the chassis brand in the current version, and differ in other brands.
Build steps
The build runs Style Dictionary once per token-set list, in these steps:
- Preprocess: the preprocessor aligns the token types, splits every font weight into a weight and a style, and numbers the tokens in source order.
- Transform: the transforms convert names, math, color modifiers, web sizes, and web shadows.
- Resolve: Style Dictionary replaces every reference with the value it points to, and stops the build on a reference that points to nothing.
- Filter: the filters select the tokens of each file.
- Format: the formats print one line per token, in source order, and encode each value for its platform.
Platform values such as UIColor(…), ARGB hex colors, and sizes in dp are encoded in the format step, after the references are resolved. A transform runs before that, and the tokens that reference a token receive its transformed value: the shadow color rgba({color.primitive.neutral.30}, {opacity.context.fg-subtle}) needs a plain color, not a UIColor(…). Add the encoding of a new platform to a format, not to a transform.
Prerequisites
The build runs in a clone of the repository. It needs:
- Node.js 22 or later
- pnpm
- The dependencies of the workspace
- Token sets in
packages/tokens/source/, with the$themes.jsonthat Tokens Studio writes; see Tokens Studio
Clone the repository and install the dependencies:
git clone https://github.com/chassis-ui/tokens.git chassis-tokens
cd chassis-tokens
pnpm installTo install the tokens package without the dependencies of the documentation site, run pnpm install --filter @chassis-ui/tokens instead. Quick Start covers the setup in more detail.
Run the build
Run the commands of this page from the repository root. Without options, the build writes the files of every brand, theme, app, platform, and screen of the build options:
pnpm tokensThe files go to dist/<platform>/<app>/<brand>/. The build runs Style Dictionary once per brand, app, and token-set list.
Command line options
The options select a part of the build, change where the build reads and writes, or print information.
| Option | Effect |
|---|---|
--brand <brands...> | Only these brands, such as chassis sinefil |
--app <apps...> | Only these apps, such as docs demo |
--platform <platforms...> | Only these platforms, such as web ios android |
--theme <themes...> | Only the color files of these themes, such as light dark |
--screen <screens...> | Only the number files of these screens, such as large medium small |
--out <dir> | Write to another output root instead of dist |
--config <file> | Read the build options from a JSON file instead of chassis.build |
--dry-run | List the builds and the files each would write, without building |
--help, -h | Show the help |
--version, -v | Show the version |
The options from --brand to --screen are filters. Each takes one or more values separated by spaces, and you can combine them:
pnpm tokens --brand chassis
pnpm tokens --app docs --platform web
pnpm tokens --brand sinefil --platform ios android --screen large small--theme and --screen limit the color and number files only: every build of a brand, an app, and a platform writes the main and string files. The iOS file Color.swift needs the color files of both themes, so a build with --theme light does not write it.
--config and --out take paths relative to packages/tokens/. The file of --config holds the keys of chassis.build at its top level. This command builds the web-px preset into dist-next/ and leaves dist/ as it is:
pnpm tokens --config test/golden/web-px.json --out dist-nextSet DEBUG=1 before a command, as in DEBUG=1 pnpm tokens --brand chassis, to print the stack trace of an error.
Dry run
A dry run shows what a set of options or filters selects before you build. It writes nothing.
pnpm tokens --brand chassis --app docs --dry-runThe build prints each token-set list with the files it writes:
• chassis_docs_light_large
dist/web/docs/chassis/: main.scss, string.scss, color-light.scss, number-large.scss
• chassis_docs_dark_large
dist/web/docs/chassis/: color-dark.scssThe lists of the other screens follow, each with its number file.
Build options
The token system is built on three core groups, brand, theme, and app, and on an optional fourth group, screen. The build options name the options of each group that the build writes, and the platforms of each app. The committed build options are in chassis.build of packages/tokens/package.json:
"chassis": {
"build": {
"brands": ["chassis", "sinefil"],
"themes": ["light", "dark"],
"screens": ["large", "medium", "small"],
"apps": {
"docs": ["web"],
"demo": ["ios", "android"]
}
}
}| Key | Required | Meaning |
|---|---|---|
brands | Yes | Options of the brand group of source/$themes.json |
themes | Yes | Options of the theme group; the first is the default |
apps | Yes | Options of the app group, each with its platforms |
screens | No | Options of the screen group; the first is the default |
options | No | Style Dictionary options by platform name; see Platform options |
The names in the block are the committed configuration, not the system. The build writes only what the keys list, so to build a brand, a theme, or an app of your own, add its name to the key of its group and give it token sets in source/$themes.json.
To build without screens, set screens to [] or leave the key out, and remove the screen group from source/$themes.json. The build then writes one number file with no screen in its name: number.scss on the web, Number.swift on iOS, and number.xml with res/values/number.xml on Android.
Token-set lists
A token-set list is the list of token sets that one run of Style Dictionary reads. The build combines one option of each group of source/$themes.json into a list named <brand>_<app>_<theme>_<screen>, or <brand>_<app>_<theme> without screens. chassis_docs_light_large is a list of the committed configuration. Every name in the build options must be an option of its group.
The files of a brand and an app that need the same token sets share one list:
| Token-set list | Files |
|---|---|
| First theme, first screen | The main file, the string file, the color file of the first theme, the number file of the first screen |
| Each other theme, first screen | The color file of the theme |
| First theme, each other screen | The number file of the screen |
A list holds its token sets in the order of source/$themes.json, so a later token set overrides an earlier one, as in Tokens Studio. Style Dictionary reports these overrides as token collisions in every build; they are expected.
Chassis Tokens is meant to be owned and customized, so you can add a group of your own. A new group adds a segment to the name of every token-set list. planBuilds in packages/tokens/build/build.js makes that name from the brand, the app, the theme, and the screen, and decides which files each list writes, so a new group needs a change there.
Platform options
The options key holds Style Dictionary options by platform name. The build merges them into the options of that platform, and fails when options names a platform that no app uses.
| Option | Platforms | Effect |
|---|---|---|
outputReferences | Every platform except web | Prints the name of the referenced token instead of the value; see References |
packageName | android-compose | The package of the Kotlin files, chassis.tokens by default |
screens | android | The resource qualifier of each screen |
options.android.screens maps each screen to the qualifier of its folder in the res/ tree, with "" for the default values folder. Every screen needs a qualifier, and exactly one screen goes into the default folder. Without the option, small goes into values, medium into values-sw600dp, and large into values-sw840dp.
Platforms
A platform is a build target that an app selects in chassis.build.apps. The committed build options use web, ios, and android, which write the published package; the other platforms are presets.
| Platform | Format | Output folder | Output |
|---|---|---|---|
web | cx/scss-chassis-css | dist/web/<app>/<brand>/ | SCSS variables for Chassis CSS, sizes in rem |
web-scss | cx/scss-variables | dist/web/<app>/<brand>/ | SCSS variables with resolved values, sizes in rem |
web-px | cx/scss-variables | dist/web/<app>/<brand>/ | The same, sizes in px |
web-vw | cx/scss-variables | dist/web/<app>/<brand>/ | The same, sizes in vw |
ios | cx/ios-swift-class | dist/ios/<app>/<brand>/ | Swift constants for UIKit, Color.swift, and Icons.xcassets |
ios-swiftui | cx/swiftui | dist/ios-swiftui/<app>/<brand>/ | Swift constants with SwiftUI values |
android | cx/android-resources | dist/android/<app>/<brand>/ | XML resources, as flat files and as a res/ tree with drawables |
android-compose | cx/compose-object | dist/android-compose/<app>/<brand>/ | Kotlin objects for Jetpack Compose |
Each platform has its own name and format for a token. space.context.medium, which references {size.unit.16}, prints as:
| Platform | Name | Format |
|---|---|---|
web, web-scss | $cx-space-context-medium | A size in rem |
web-px | $cx-space-context-medium | A size in px |
web-vw | $cx-space-context-medium | A size in vw |
ios, ios-swiftui | SpaceContextMedium | A CGFloat in points |
android | @dimen/space_context_medium | A <dimen> in dp |
android-compose | spaceContextMedium | A size with .dp |
The formats hold the value rules of each platform. The guides for web, iOS, and Android show how to use the files in an app.
Presets
A preset is a platform for a team that owns its tokens and does not use Chassis CSS, UIKit, or Android resources. Select a preset by its name in chassis.build.apps. The committed dist/ holds no preset output; the output of each preset for the chassis brand is in test/golden/.
Presets for other CSS frameworks
The web platform prints the custom properties of Chassis CSS, such as var(--default-fg-main), so its SCSS works only with Chassis CSS. The presets web-scss, web-px, and web-vw print resolved values in the unit of their name. In chassis.build of packages/tokens/package.json:
"apps": {
"docs": ["web-px"]
}The build then writes every value resolved, with sizes in pixels; cx/scss-variables shows the format. The web platforms write the same file names to the same folder, dist/web/<app>/<brand>/, so give an app one of them. Line heights and letter spacing are in em in every unit.
Each preset is a file of packages/tokens/build/config/ that calls webConfig({ unit, format }) of web.js. You can edit these files as any other platform file.
SwiftUI and Compose presets
The presets ios-swiftui and android-compose write the tokens for apps that use SwiftUI or Jetpack Compose. Select them next to, or instead of, ios and android. In chassis.build of packages/tokens/package.json:
"apps": { "demo": ["ios-swiftui", "android-compose"] },
"options": { "android-compose": { "packageName": "com.example.tokens" } }| Preset | Files | Differences |
|---|---|---|
ios-swiftui | The Swift files of ios, with the same types | Color and Font.Weight values; no Color.swift, no Icons.xcassets, no …Radius constants |
android-compose | One Kotlin object per file: ChassisTokens.kt, String.kt, ColorLight.kt, NumberLarge.kt, … | Compose values with camelCase names; no res/ tree, no drawables |
Each file of these presets holds one theme or one screen. For colors that follow the appearance in SwiftUI, build the ios platform too and wrap its ChassisTokensColor constants in Color(uiColor:). See cx/swiftui and cx/compose-object for the values.
Generated files
Every platform writes a main file, a string file, one color file per theme, and one number file per screen.
| Platform | Files |
|---|---|
| Web | main.scss, string.scss, color-<theme>.scss, number-<screen>.scss |
| iOS | ChassisTokens.swift, String.swift, Color<Theme>.swift, Number<Screen>.swift, Color.swift, Icons.xcassets |
| Android | main.xml, string.xml, color_<theme>.xml, number_<screen>.xml, and the res/ tree |
Color files use the token sets of their theme, and number files the token sets of their screen. The main and string files use the token sets of the first theme and the first screen of the build options.
The main file holds every token except the theme colors, which are color.primitive.*, color.context.*, and the gradients. Its component colors are the ones of the first theme, and its numbers the ones of the first screen. The string, color, and number files share no names with each other, and together they hold everything in the main file except the base colors.
On iOS, each file declares a caseless public enum, so all files fit in one module: ChassisTokens in ChassisTokens.swift, and ChassisTokens<File> in the others, such as ChassisTokensColorLight. When the themes include light and dark, the build writes Color.swift after the other files. Its type ChassisTokensColor holds the colors of both themes:
public static let ColorContextDefaultFgMain = UIColor { $0.userInterfaceStyle == .dark ? UIColor(red: 0.914, green: 0.925, blue: 0.929, alpha: 1) : UIColor(red: 0.086, green: 0.102, blue: 0.106, alpha: 1) }Package.swift at the repository root declares one Swift library per brand of every app with an iOS platform. Run pnpm tokens:swift-package after you change the brands or apps.
On Android, the res/ tree holds the same resources as the flat files, in the folders that Android selects by itself:
| Folder | Files |
|---|---|
res/values/ | string.xml, color_base.xml, color.xml of the first theme, number.xml of the screen with the qualifier "" |
res/values-night/ | color.xml of the dark theme |
res/values-<qualifier>/ | number.xml of each other screen |
res/drawable/ | One vector drawable per icon |
main.xml cannot share a resource folder with the flat string, color, or number files: aapt2 fails with has a conflicting value. Add either main.xml or the flat files to a module. The res/ tree needs neither.
An icon is an asset token whose value is an SVG document, such as icon.accordion.indicator. It stays a string on every platform. The ios platform also writes it to Icons.xcassets/IconAccordionIndicator.imageset/, and the android platform to res/drawable/icon_accordion_indicator.xml.
References
By default every token prints its resolved value. With outputReferences, a token that references another token prints the name of that token, wherever the result compiles and keeps the value. The web platform ignores the option: it prints the custom properties of Chassis CSS in every build.
Set the option per platform. In chassis.build of packages/tokens/package.json:
"apps": { "docs": ["web-px"], "demo": ["ios", "android"] },
"options": {
"web-px": { "outputReferences": true },
"ios": { "outputReferences": true }
}| Platform | Prints | Example |
|---|---|---|
web-scss, web-px, web-vw | The SCSS variable | $cx-color-context-default-fg-main |
ios, ios-swiftui | The constant | DimensionBase4 |
android | The resource reference | @dimen/dimension_base_4 |
android-compose | The property | dimensionBase4 |
In SCSS, a color, space, opacity, border radius, or border width token prints a variable when the Chassis CSS format prints a custom property for it. Typography maps name the variables of their family, weight, size, line height, and style. Shadows print their value. The web-px preset writes:
$cx-border-radius-accordion-main: $cx-border-radius-context-medium !default;
$cx-border-width-accordion-main: $cx-border-width-context-medium !default;With outputReferences, load color-light.scss or color-dark.scss before main.scss. The component colors of main.scss name context colors, which only the color files declare.
On iOS and Android, a token names the token it references only when that token is in the same file and encodes to the same text, and on Android to the same kind of resource. Base colors and sizes computed with math print their values. The ios platform writes in ChassisTokens.swift:
public static let SizeUnit4 = DimensionBase4
public static let SizeDatepickerWeekWidth = CGFloat(224)
public static let SpaceContextMedium = SizeUnit16
public static let BorderRadiusAccordionMain = BorderRadiusContextMediumSizeDatepickerWeekWidth is {size.datepicker.day-width}*7, so it prints its value. ColorAccordionItemFgColor prints its value in ChassisTokens.swift too, because the context colors are in the color files; in ColorLight.swift it is ColorContextDefaultFgMain. The android platform writes in main.xml:
<dimen name="size_unit_4">@dimen/dimension_base_4</dimen>
<dimen name="space_context_medium">@dimen/size_unit_16</dimen>
<dimen name="font_context_jumbo_font_size">96sp</dimen>The font size prints its value because it is in sp, and the size it references, size_unit_96, is in dp.
Check the output
These commands check the token source and the output of the build. Run the source lint before you build, and the other two after.
Lint the source
The source lint finds mistakes that the build accepts. It reads the token sets that source/$themes.json selects:
pnpm tokens:lint:sourceThe lint fails, and names the token set and the token, when:
- the options of the
themeorscreengroup declare different names in their token sets - a name has characters other than letters, digits, and single hyphens, starts with a digit, or becomes the same SCSS, Swift, Android, or Compose name as another token
- a font weight is not one the build knows
- a token has no
$type, or a value is not a token - two token sets of one token-set list declare the same name with different types
Verify the output
The golden check compares a fresh build with the committed dist/. It builds into dist-next/ and never writes to dist/:
pnpm tokens:verifyThe check ignores the timestamp and version lines of the file headers. It also fails when a name appears twice in one file, and when a reference names nothing that the output declares. Add --platform ios to build and check one platform. After you change tokens or build options, run pnpm tokens and commit the updated dist/.
Token diff report
The diff report lists what a change does to the tokens of each file: the names added, removed, renamed, and changed in value. It marks removed and renamed names as breaking.
pnpm tokens:diffThe report compares the working dist/ with the dist/ of main. Add --base with a branch, a tag, or a commit, as in pnpm tokens:diff --base v0.5.3, to compare with another one.
Preprocessor
The preprocessor cx/global prepares the tokens of every build before the transforms run. It changes the tokens in these ways:
- It aligns the types of Tokens Studio with the types of Style Dictionary, with
alignTypesof@tokens-studio/sd-transforms:fontWeightsbecomesfontWeight. - It types letter spacing tokens as
number, so the size transforms leave them alone. - It splits every font weight token into a
weightand astyletoken.typography.fontWeight.html.blockquotenames a weight and a style, and becomestypography.fontWeight.html.blockquote.weightandtypography.fontWeight.html.blockquote.style. A weight that names no style gets the stylenormal. - It numbers the tokens in source order. The formats sort by this number, so the parts of a typography or shadow token stand where the token is in the source.
Transforms
Transforms run before the references are resolved. Each platform lists its transforms in its file of packages/tokens/build/config/; no platform uses a transform group.
| Transform | Platforms | Effect |
|---|---|---|
name/kebab | Web platforms | Names in the form space-context-medium |
name/pascal | ios, ios-swiftui | Names in the form SpaceContextMedium |
name/snake | android | Names in the form space_context_medium |
name/camel | android-compose | Names in the form spaceContextMedium |
ts/resolveMath | All | Computes a value with math, such as {size.datepicker.day-width}*7 |
ts/color/modifiers | All | Applies the color modifiers of Tokens Studio |
ts/color/css/hexrgba | All | Turns a color with an alpha, such as rgba({color.primitive.neutral.30}, {opacity.context.fg-subtle}), into a CSS rgba() color |
ts/typography/fontWeight | Web platforms | Turns the name of a font weight into its number |
The name transforms come from Style Dictionary and the ts/ transforms from @tokens-studio/sd-transforms. The build registers the cx/ transforms in packages/tokens/build/transforms.js, all for the web platforms:
| Transform | Platforms | Tokens | Effect |
|---|---|---|---|
cx/size/rem | web, web-scss | Sizes | Divides the design pixels by basePxFontSize and adds rem |
cx/size/px | web-px | Sizes | Adds px to the design pixels |
cx/size/vw | web-vw | Sizes | Divides the design pixels by basePxFontSize and adds vw |
cx/shadow/web | Web platforms | Shadows | Joins the parts of each layer into a CSS box-shadow |
Sizes are the tokens typed dimension, fontSize, lineHeight, or paragraphSpacing. basePxFontSize is an option of the platform, which packages/tokens/build/config/web.js sets to 16. dimension.base.05 holds half a design pixel, and size.unit.05 references it. With cx/size/rem, the build writes in main.scss:
$cx-dimension-base-05: 0.03125rem !default;
$cx-size-unit-05: 0.03125rem !default;No size is rounded. The web platforms set mathFractionDigits to 10, so ts/resolveMath keeps the value of a size that references another size.
cx/shadow/web prints each layer of a shadow as its horizontal offset, vertical offset, blur, spread, and color, with inset after an inner shadow, and joins the layers with commas. The build writes in main.scss:
$cx-shadow-context-inset: 0rem 0.125rem 0.25rem 0rem rgba(0, 0, 0, 0.1) inset !default;Filters
A filter selects the tokens of one kind of file by their type and path. Every platform uses the same filters, so a token is in the same kind of file on every platform.
| Filter | Files | Tokens | Example |
|---|---|---|---|
cx/allTokens | Main | Every type that the build writes, without the colors under color.primitive, color.context, color.utility, and gradient.primitive | color.accordion.item-fg-color |
cx/stringTokens | String | asset, content, fontFamily, fontStyle, fontWeight, string, text, textCase, textDecoration, type | icon.accordion.indicator |
cx/themeTokens | Color | Colors whose second path segment is not base or utility, and shadows | color.context.default.fg-main |
cx/numberTokens | Number | duration, letterSpacing, number, opacity, and the sizes | space.context.medium |
cx/baseColorTokens | res/values/color_base.xml of Android | Colors whose second path segment is base | color.base.context.light.default.fg-main |
Gradients are typed color, so gradient.primitive.* is in the color files and not in the main file. Only the web keeps a shadow whole, so only the web color files hold shadows; iOS and Android split a shadow into parts, and the color of each layer is in the main file and the color files. No file holds the tokens typed boolean or other, the colors under color.utility, or the groups that exist for Figma only, figma.* and bg-blur.*.
Formats
A format prints one kind of file. Every format starts a file with a header that holds the build time, the version of the package, and the license, and prints the tokens in source order.
cx/scss-chassis-css
This format prints SCSS variables for Chassis CSS, and the web platform uses it. Each token is one $cx-<name>: <value> !default; line. The build writes in main.scss:
$cx-space-context-medium: 1rem !default;
$cx-color-accordion-item-fg-color: var(--default-fg-main) !default;
$cx-typography-line-height-text-medium: 1.5em !default;
$cx-border-radius-accordion-main: var(--border-radius-md) !default;
$cx-font-context-lead: ("font-family": var(--font-family-text), "font-weight": var(--font-weight-text-normal), "font-size": var(--font-size-text-xl), "line-height": var(--line-height-text-xl), "font-style": normal, "letter-spacing": 0em, "margin-bottom": 0rem, "text-transform": none, "text-decoration": none) !default;A token prints var(--<name>) when its value is a single reference to a token that Chassis CSS has a custom property for: color.context.*, color.primitive.*, space.context.*, opacity.context.*, opacity.level.*, shadow.context.*, borderRadius.context.*, or borderWidth.context.*. The name follows the referenced path, with the scale steps shortened as in Chassis CSS: medium becomes md, and xlarge becomes xl. Every other token prints its value:
- Sizes are in
rem. - Colors are hex, or
rgba()when they have an alpha. - A line height token is divided by the font size token of the same step, and printed in
em. - Letter spacing is in
em: the design pixels divided bybasePxFontSize. - Font weights are numbers, font families keep their whole list, and assets are in double quotes.
- A typography token is a Sass map, with a custom property for its family, weight, size, and line height.
cx/scss-variables
This format prints SCSS variables for other CSS frameworks, and the presets web-scss, web-px, and web-vw use it. It prints the file of cx/scss-chassis-css with every value resolved. The web-scss preset writes in main.scss:
$cx-space-context-medium: 1rem !default;
$cx-color-accordion-item-fg-color: #161a1b !default;
$cx-border-radius-accordion-main: 0.375rem !default;The Sass map of a typography token holds resolved values too, and quotes the list of font families as one string. With outputReferences, the format prints SCSS variables; see References.
cx/ios-swift-class
This format prints one Swift type with a public static let per token, and the ios platform uses it. The build writes in ChassisTokens.swift:
import UIKit
public enum ChassisTokens {
public static let SpaceContextMedium = CGFloat(16)
public static let ColorButtonPrimaryBgIdle = UIColor(red: 0.000, green: 0.643, blue: 0.800, alpha: 1)
public static let FontContextJumboLineHeight = CGFloat(120)
public static let FontContextJumboFontSize = CGFloat(96)
public static let FontContextJumboLetterSpacing = CGFloat(-0.5)
public static let ShadowContextSmall1Blur = CGFloat(8)
public static let ShadowContextSmall1Radius = CGFloat(4)
}- Colors are
UIColorwith three decimals per channel. Numbers and sizes areCGFloat, in points. - A font family is a string with the first family of the list. A font weight is a
UIFont.Weightconstant. - A typography or shadow token becomes one constant per part. A line height in percent prints in points, as that share of the font size of its token.
- After the blur of each shadow layer, a
…Radiusconstant holds half the blur, for theshadowRadiusof Core Animation. - A gradient becomes an angle, and a color and a position per stop:
GradientPrimitiveBlackL000Angle,GradientPrimitiveBlackL000Stop1Color,GradientPrimitiveBlackL000Stop1Position. The format readslinear-gradient()with a direction indeg, orto top,to right,to bottom, orto left.
cx/swiftui
This format prints the Swift files with SwiftUI values, and the ios-swiftui preset uses it. Colors are Color and font weights Font.Weight; every other value is the one of cx/ios-swift-class, without the …Radius constants. The preset writes in ColorLight.swift:
import SwiftUI
public enum ChassisTokensColorLight {
public static let ColorContextDefaultFgMain = Color(red: 0.086, green: 0.102, blue: 0.106, opacity: 1)
}cx/android-resources
This format prints a <resources> file with one element per token, and the android platform uses it. The build writes in main.xml:
<resources>
<dimen name="space_context_medium">16dp</dimen>
<item name="opacity_level_10" type="dimen" format="float">0.1</item>
<color name="color_button_primary_bg_idle">#ff00a4cc</color>
<dimen name="font_context_jumbo_line_height">120sp</dimen>
<dimen name="font_context_jumbo_font_size">96sp</dimen>
<item name="font_context_jumbo_letter_spacing" type="dimen" format="float">-0.0052</item>
</resources>The type of a token decides its element:
| Tokens | Element | Format |
|---|---|---|
| Opacity, letter spacing, gradient angles and positions | <item type="dimen" format="float"> | A number |
| Font weights | <integer> | A weight number |
| Colors | <color> | ARGB hex |
| Sizes | <dimen> | A size in dp or sp |
| Everything else | <string> | Text, escaped for Android |
Font sizes, line heights, and paragraph spacing are in sp, and other sizes in dp. The letter spacing of a typography token is in ems of its font size, which android:letterSpacing takes. Typography, shadow, and gradient tokens become parts as on iOS, without the …Radius constants.
cx/compose-object
This format prints one Kotlin object per file with a getter per token, and the android-compose preset uses it. The values are the ones of cx/android-resources as Compose types. The preset writes in NumberLarge.kt:
package chassis.tokens
object ChassisTokensNumberLarge {
val spaceContextMedium get() = 16.dp
val opacityLevel40 get() = 0.4f
val fontContextJumboLetterSpacing get() = (-0.0052).em
val fontContextLeadFontSize get() = 22.sp
}Colors are Color(0xAARRGGBB), font weights are FontWeight with the weight number, and strings are Kotlin string literals. Every property is a getter, because with outputReferences a property may name one that the file declares later.
Troubleshooting
The build prints the message of an error after Build failed, or after Failed: and the name of the token-set list. Run it with DEBUG=1 for the stack trace.
Unknown platform
The build stops with Unknown platform: web-rem. An app of chassis.build.apps lists a platform that the build does not have. Use one of the names of the platforms table.
Unknown filter value
The build stops with Unknown filter values: --brand chasis (configured: chassis, sinefil). A filter of the command names a brand, app, platform, theme, or screen that chassis.build does not have. Use one of the configured values. The build also stops with The filters select no build when the filters together select nothing, such as --app docs --platform ios while the docs app has only the web platform.
No token sets
The build stops with No token sets for acme_docs_light_large in source/$themes.json. A brand, app, theme, or screen of the build options is not an option of its group in source/$themes.json, or the build options have no screens and source/$themes.json has a screen group. Check the spelling of the name, or add the option in Tokens Studio.
Unused platform options
The build stops with Invalid package.json: options for platforms no app uses: web-px. chassis.build.options has a key that is not a platform of any app. Add the platform to an app, or rename the key to the platform that the app uses.
Android screen folders
The build stops with no Android resource qualifier for the screens large; set them in options.android.screens, or with options.android.screens must put exactly one screen in the default folder ("") but puts 0. The defaults cover the screens small, medium, and large, and options.android.screens replaces them as a whole. Give every screen of chassis.build.screens a qualifier in options.android.screens, and give exactly one screen the qualifier "".
Broken reference
A build fails with Some token references (1) could not be found. A token references a token that is not in the token sets of the list, because of a misspelled path or a token set that the option of source/$themes.json does not select. To list the references, add verbosity: 'verbose' to log in packages/tokens/build/config/index.js and build again.
Undeclared SCSS variable
A build with outputReferences fails with No file declares a variable for, followed by the path of a token. A token references a token that no file holds, such as a token typed boolean or other. Give the referenced token a type that the build writes, or build the platform without outputReferences.
Unknown font weight
A build of an iOS or Android platform fails with Unknown font weight "Extra Heavy" in typography.fontWeight.text.strong.weight. The build knows the weight names of ts/typography/fontWeight, and ignores case, spaces, and hyphens in them. Use one of these names in the token; pnpm tokens:lint:source finds the token before the build.
Golden check failed
pnpm tokens:verify prints Golden check failed against dist/ and the first differing lines of each file. The committed dist/ is older than the tokens or the build options. Run pnpm tokens, review the changes with pnpm tokens:diff, and commit dist/.
Next steps
The build is one part of the token workflow. Continue with the part you need:
- Use the files in a web, iOS, or Android app.
- Change the token sets in Tokens Studio, and sync them with Figma Variables.
- Read docs/architecture.md for the design decisions, the output contract, and the known oddities of the output.
- Read CONTRIBUTING.md before you change the build.