theming
usage

Using Tokens

There are various ways to consume Bamboo tokens depending on your need at that point in time.

Learn the various ways to consume Bamboo tokens in your project.

Style Properties

The recommended way to consume your tokens is in the css function.

import { css } from '../styled-system/css'
 
const App = () => (
  <div
    className={css({
      color: 'green.400',
      background: 'gray.200',
    })}
  />
)

Composite values

Some CSS properties like border, box-shadow allow you to specify multiple properties in its value. Reference a token inside one with token(path.to.token) — the same spelling used for semantic token values.

import { css } from '../styled-system/css'
 
const className = css({ border: '1px solid token(colors.red.400)' })

You can also use it in media queries or any other CSS at-rule.

import { css } from '../styled-system/css'
 
const className = css({
  '@media screen and (min-width: token(sizes.4xl))': {
    color: 'green.400',
  },
})

Earlier versions also accepted a curly form, {'{colors.red.400}'}, which meant exactly the same thing. It has been removed so there is one way to write a reference, and so was the second fallback argument. Both are errors rather than silent fallbacks: a retired reference in a token value fails the build naming the token and its replacement, and one in a style value throws where it is used. A value that may not name a token is resolved where that can be answered — PatternHelpers.token(path, fallback) inside a pattern — rather than deferred into a string.

Vanilla JS

Use the generated token function to query design tokens in your project. This is useful if you need direct access to your design tokens in the style attribute or when using CSS-in-JS libraries like styled-components or @emotion/styled

šŸ’”

This approach is useful for incrementally adopting Bamboo in existing projects or dynamic styling

Style Attribute

src/App.tsx

import { token } from '../styled-system/tokens'
 
function App() {
  return (
    <div
      style={{
        background: token('colors.blue.200'),
      }}
    />
  )
}

Each of your design tokens will be available in the generated /tokens folder. It looks like this:

styled-system/tokens/index.mjs

const tokens = {
  // ...
  'colors.blue.200': {
    value: '#bfdbfe',
    variable: 'var(--colors-blue-200)',
  },
  // ...
}
  • The token() function returns the CSS custom property that references the token — the same for every token.
  • The token.value() function returns the resolved raw value.

Both are typesafe and expect a known dot-separated token path. Neither takes a fallback argument: a path that names no token returns undefined, so token('colors.brand') ?? '#fff' supplies one in the language.

Using the example above, token('colors.blue.200') returns var(--colors-blue-200) and token.value('colors.blue.200') returns #bfdbfe.

Which one to reach for

Prefer token(). A variable reference keeps responding to whatever the cascade decides, so a value read through it still changes when the theme does.

Reach for token.value() only where a CSS variable cannot be resolved — a <canvas> fill, a charting library, or a <meta name="theme-color"> tag. It is a snapshot: it stops tracking the theme.

It also only accepts a token that has a literal. A conditional token has no single value to snapshot, a virtual one none of its own, and a negative one resolves to a calc() over its counterpart — so token.value('colors.primary') is a type error rather than a variable reference handed to a canvas that cannot resolve it. Those are what token() is for.

āš ļø

Before Bamboo 2, token() returned the raw value for a plain token and the variable reference for a conditional one — so which kind you got was decided by the theme rather than by the call, and adding a _dark variant to a token silently changed what every caller received. token() now always returns the reference. If you were relying on the literal, rename those calls to token.value(). token.var() and the second fallback argument are both gone — token() is the reference, and ?? fallback is the fallback.

The extractor follows a path built from a constant or a template literal, so token(KEY) is seen by the reachability analysis behind prune.tokens as well as a path spelled out at the call. A template with a substitution is bounded rather than lost: token(`colors.${shade}`) keeps the colors category, because that is what its static head can reach.

A path with no static head — token(key), token('colors.' + shade) — is the one the build cannot follow. Name the category those land in with prune.keepTokens, or set prune: { tokens: false }.

Styled Components

import styled from 'styled-components'
 
const Button = styled.button`
  background: ${token('colors.blue.200')};
`

Emotion

import styled from '@emotion/styled'
 
const Button = styled.button`
  background: ${token('colors.blue.200')};
`