@rei/cdr-tokens
v14.0.2
Published
Tokens for REI cedar design system
Downloads
1,263
Keywords
Readme
rei-cedar-tokens
tokens for cedar design system
Consuming
Install the package
npm i -D @rei/cdr-tokens(may need to remove the '-D' depending on your use case).Import/require the tokens in your needed format. Platforms specific formats are available in each directory with the same name -- i.e.
dist/scss/cdr-tokens.scss.- JS: commonjs (default) and es module
- SCSS: variables, maps, and mixins
- CSS: custom properties (CSS variables)
- Android: XML style sheets for Colors and Dimensions
- iOS: Swift classes for Color and Size
** REI Internal teams should use the internal iOS and Android packages.
Semantic Contract (Recommended)
For teams building framework integrations (Tailwind, styled-components, etc.), use the semantic contract:
import { CdrColorText, CdrSpace, CdrBreakpoint } from '@rei/cdr-tokens';The semantic entrypoint provides a stable export of semantic foundation tokens with a guaranteed interface within a major version. This is the recommended way to consume Cedar tokens in production applications.
For flat runtime values, use @rei/cdr-tokens/tokens:
import { CdrSpaceScale2 } from '@rei/cdr-tokens/tokens';See Architecture Guide for details and Consumer TypeScript Contract for the full import contract reference.
Updating
If you are consuming tokens in SCSS, there are deprecation warnings for variables, mixins, etc. that will appear in the console during your build. These can be silenced by adding a variable to your code called cdr-warn and setting it to false like this: $cdr-warn: false;
All other formats should consult the changelog for a migration path.
Contributing
Initial set up
- Clone repo
npm installnpm run build(output tokens)
Tokens are generated using Style Dictionary v4.
Documentation:
- Architecture Guide - System architecture and design decisions
- Transform Guide - Transform ordering, usage, and creation
- Contract Alignment Review Map - Reviewer-oriented summary of source and generated output changes for contract-alignment PRs
Testing
This project uses Vitest for unit testing.
npm test # Run tests once
npm run test:watch # Watch mode for development
npm run test:ui # Visual test UI
npm run test:coverage # Generate coverage reportProject structure
The project is made of these files and folders:
tokens/contains the design tokens input files (in JSON format)tokens/_options/contains "option" tokens see belowtokens/global/contains design tokens that are output for all platformstokens/<platform>/contains design tokens specific to a platform (web or mobile)tokens/themes/contains theme-specific token overrides
style-dictionary/contains the build script, configs, transforms, actions, and formats used to generate the output files- See ARCHITECTURE.md for detailed documentation
dist/contains the generated output files (in different formats)docs/contains app that is generated for gh-pages examples
Tokens
In the
tokens/directory. Files are in JSON format.
Token Structure
See style-dictionary properties docs.
We follow the basic structure of style-dictionary with the exception being that our tokens don't follow the implicit CTI structure and we abstract that into a separate "category" key (see Categories below).
Token Properties
The following properties can be added to tokens to support different options
$value # *required* The token value (most token values should be referenced from options)
$type # *required* The tokens type (used to transform values for their specific platform)
docs # Object to define meta data for docs
category # The category tokens are grouped in on the examples page
type # The sub category tokens are grouped in on the examples page
example # Defines how the token should be presented on the examples page -- Current example types are: color, spacing, sizing, radius, prominence, text, inset, and breakpoint
mixin # The name of the generated SCSS/LESS mixin (must be used with property)
property # Used with mixin -- the css property the value is applied to within the mixin
'utility-class' # Boolean -- Used to create scss maps of properties to more easily generate utility classes in cedarOptions
Found in tokens/_options/
Options are skipped and do not get exported for consumers. However they can be referenced in creating tokens that will be exported.
NOTE: "options" needs to be the root key in the file.
{
options: { // <-- anything beneath this will be ignored in output
color: {
'easily-excited': {
'$value': '#3278ae',
'$type': 'color',
},
'heart-of-darkness': {
'$value': '#292929',
'$type': 'color',
},
// ...
},
}
}Output won't have a token named options-color-easily-excited.
Naming
Token names are defined by the hierarchy of the object:
{
text: {
body: {
default: {
size: {
'$value': '23px',
'$type': 'fontSize',
},
height: {
'$value': '25px',
'$type': 'size',
},
},
},
}
}Token output of above:
text-body-default-size: 23px;
text-body-default-height: 25px;
Types
Types need to be attached to both options and tokens (due to limitations of style-dictionary resolve order. This may change in the future)
Types define how style-dictionary should transform values between platforms.
For example, a type of "dimension" will transform to 'rem' for SCSS/LESS but 'dp' for Android. A type of "fontSize" will still transform values to 'rem' for SCSS/LESS but 'sp' for Android.
Categories are one of the following:
dimension: Anything that would have a value in px. With the exception of fontSizefontSize: Anything that defines a text sizeletterSpacing: Anything that defined a letter spacingcolor: Anything that defines a colortime: Anything the defines a timing- Values without a category will not be transformed: Anything that is a string like
'normal'or'italic'
Referencing Options (or other values)
{
color: {
text: {
primary: {
'on-dark': {
'$value': '{options.color.heart-of-darkness}',
'$type': 'color',
docs: {
category: 'colors',
type: 'text',
example: 'color'
}
}
}
}
}
}Documentation within tokens
Tokens also have data that can be added to them to help generate documentation & examples. To get an idea of how this data is used see the tokens example page. This data is mostly used to create groupings of tokens and is not used to do transforms on token values, only for display in docs.
The docs object looks like this:
docs: {
category: String, // Large, broad groupings of things (i.e. color, spacing)
type: String, // Sub category (i.e. background (color) or inset (spacing))
example: String, // Used to determine how to display a visual representation of a token
// Current options (see docs/src/components/PropSorter.vue): color, spacing, sizing, radius, prominence, text, inset, breakpoint, timing, duration, an empty example defaults to 'token' which is just a string representation of the value.
description: String, // Short description of the token and/or suggested usage (displayed on the cedar docs site)
}Deprecating tokens
Deprecated tokens should be moved to a seprate file (or into the existing file) which corresponds to the release cycle in which they will be deprecated.
For example, if tokens will be considered deprecated in the "Winter 2019" release they would be moved into a file called deprecated-2024-summer.json in whichever directory they currently reside. Structure for naming the file is : deprecated-<year>-<release>
Additionally, the contents will be wrapped inside an object with a key that corresponds to the release as well (so we can auto generate some deprecation warnings with the correct release). The key matches the naming of the file. See below for an example.
{
'deprecated-2024-q4': { // <-------- `deprecated-<year>-<release>`
color: {
text: {
primary: {
'on-dark': {
'$value': '{options.color.heart-of-darkness}',
'$type': 'color',
docs: {
category: 'colors',
type: 'text',
example: 'color'
}
}
}
}
}
// ...
}
}Providing a migration path
When tokens are deprecated they can also be provided a new token name or new mixin name to use instead which will be provided in the SASS deprecation warning:
{
'deprecated-2024-q4': {
text: {
header: {
'1': {
family: {
'$value': '{options.font.family.serif.$value}',
mixin: 'textHeader1',
property: 'font-family',
newMixin: 'new-mixin-name', //<--- a new mixin name to use instead of the deprecated one
newToken: 'new-token-name', //<--- a new token name to use instead of the deprecated one
docs: {
category: '{text.docCategory}',
type: 'header',
example: '{text.docExample}',
},
},
}
}
}
}
}Style Dictionary
Build
Main build script that is executed with npm run build is at style-dictionary/build.ts. The build process generates all theme × platform combinations. See ARCHITECTURE.md for details on the build flow.
All actions, configs, formats, transforms, and filters are imported in this file and registered with Style Dictionary.
Transforms
Found in style-dictionary/transforms
Transforms modify token values or attributes. See TRANSFORMS.md for comprehensive documentation on:
- Transform ordering and dependencies
- Custom transform usage and creation
- Platform-specific transform patterns
See Style Dictionary API for creating transforms
Actions
Found in style-dictionary/actions
Actions perform post-build file operations (e.g., copying utility files to output). The include-utility-file.ts provides a reusable factory for creating file-copy actions.
See Style Dictionary API for creating actions
Configs
Found in style-dictionary/configs
Platform-specific configurations that define transforms, formats, and build paths. All configs use the remove-source-tokens filter to exclude internal options and theme tokens from output.
See config docs
Formats
Found in style-dictionary/formats
Formats define how tokens are output to files (SCSS variables, CSS custom properties, JSON, etc.).
See Style Dictionary API for creating formats
Filters
Found in style-dictionary/filters
Filters determine which tokens are included in outputs. The remove-source-tokens filter excludes internal configuration tokens.
See Style Dictionary API for creating filters
Transform Groups
See API for creating a transform group
Transforms
Found in style-dictionary/transforms
See API for creating a transform
See transform docs.
Validation
Because this library has many dependencies, there is a validation script that performs some checks. One of the tests is verifying the file structure has not changed. If a change is intentional, you may execute npm run validate -- --update or delete the validate-structure.json file and then execute npm run validate. The validate-structure.json file should be commited.
