overview
cheat sheet

Cheat Sheet

Every Bamboo API on one page.

Everything below is a function call that returns a class string. There is no JSX factory and no template literal syntax — one way to write a style, which is also what lets the build-time compiler resolve it completely.

Styling

import { css, cx } from '../styled-system/css'
 
css({ color: 'red.500', padding: '4' }) // tokens by name
css({ color: '#f00', padding: '13px' }) // raw values work too
css({ display: '[var(--btn-display)]' }) // escape hatch — skips token checking
 
css({ _hover: { color: 'red.700' } }) // condition as a block
css({ color: { base: 'red.500', _hover: 'red.700' } }) // …or per property
css({ fontSize: { base: 'sm', md: 'lg' } }) // responsive, mobile first
css({ color: { base: 'black', _dark: 'white' } }) // theming condition
 
cx('external', cond && 'another') // unknown external inputs remain a tiny runtime join

Composing styles

The compiler semantically composes statically analyzable Bamboo classes passed to cx. With unknown external inputs, cx is only a string join and makes no conflict guarantee. Merge the objects when the inputs are available as styles, where the last write wins per property:

css({ padding: '4' }, { padding: '8' }) // → padding 8
css(css.raw({ padding: '4' }), { padding: '8' }) // both objects are statically available
css.raw({ padding: '4' }) // a style object to merge later

See Merging styles.

Recipes

import { cva, sva } from '../styled-system/css'
 
const button = cva({
  className: 'button', // optional extraction metadata; ignored by Vite atom identity
  base: { borderRadius: 'md' },
  variants: { size: { sm: { padding: '2' }, lg: { padding: '4' } } },
  defaultVariants: { size: 'sm' },
  compoundVariants: [{ size: 'lg', tone: 'brand', css: { fontWeight: 'bold' } }],
})
 
button({ size: 'lg' }) // shared atoms for this complete selection
const [variantProps, rest] = button.splitVariantProps(props)

The Vite compiler resolves the selected recipe and any statically analyzable cx() composition before allocating globally shared atoms in utilities. Declaring the same shape in theme.recipes generates only reachable finite variant states — see inline vs config recipes.

sva is the same for multi-part components. Under Vite, each selected slot receives its complete atom string:

const checkbox = sva({ slots: ['root', 'control'] /* … */ })
const classes = checkbox({ size: 'md' })
classes.root // shared atoms for the selected root styles
classes.control // shared atoms for the selected control styles

scopeRoots remains accepted as recipe metadata for compatibility, but compiled slot selections do not emit @scope.

Patterns

Layout helpers that are css() with a transform applied. flex, grid, gridItem, center, container, spacer, divider, float, aspectRatio, bleed, linkOverlay.

import { flex } from '../styled-system/patterns'
;<div className={flex({ direction: 'column', gap: '4', align: 'center' })} />

Tokens and escape hatches

import { token } from '../styled-system/tokens'
import { css, fallback, viewTransition } from '../styled-system/css'
 
token('colors.red.500') // var(--colors-red-500)
token.value('colors.red.500') // the resolved value, for canvas and the like
css({ height: fallback('100dvh', '100vh') }) // progressive enhancement
viewTransition({
  /* … */
}) // ::view-transition-* rules, one class

See Writing styles for the full surface.