---
title: Migrating from Theme UI
description: Migrate your project from Theme UI to Bamboo.
---

This guide outlines the steps needed to migrate your project from Theme UI to Bamboo and highlights key design
differences between the two libraries.

Here are some similarities between the two libraries.

- Both support design tokens and themes.
- Both ship layout primitives — Theme UI as components (`Box`, `Flex`, `Grid`), Bamboo as pattern **functions** that
  return a class name.

Below are some of the differences between the two libraries. The one that shapes the whole migration: Bamboo has no JSX
style props and no `sx` prop. Every style is a `css()`, `cva()` or pattern call whose class name you put on an element.

## Performance

Theme UI relies on `@emotion/styled` to style components. This means that every time you use the `sx` prop, runtime
CSS-in-JS is required to compute the styles in the browser. This can lead to performance issues in larger applications.

Bamboo relies on `postcss` and converts CSS-in-JS styles to static CSS at build-time, leading to better performance in
larger applications.

## Theming

In Theme UI, you need to wrap your application in a `ThemeProvider` component which is a wrapper around `@emotion/react`
theme context.

```jsx
import { ThemeProvider } from 'theme-ui'

const theme = {
  fonts: {
    body: 'system-ui, sans-serif',
    heading: '"Avenir Next", sans-serif',
  },
  colors: {
    text: '#000',
    background: '#fff',
  },
}

export default function App({ Component, pageProps }) {
  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}
```

In Bamboo, you don't need to wrap your application in a `ThemeProvider` component. Instead, you can pass the theme
object to the `bamboo.config.js` file.

The theme object in Bamboo is broken down into multiple parts, `tokens` and `semanticTokens`. The theme specification
also required passing the tokens as `{ value: XX }`

```js
// bamboo.config.js
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  theme: {
    extend: {
      tokens: {
        fonts: {
          body: { value: 'system-ui, sans-serif' },
          heading: { value: '"Avenir Next", sans-serif' },
        },
        colors: {
          text: { value: '#000' },
          background: { value: '#fff' },
        },
      },
    },
  },
})
```

## The `sx` prop

In Theme UI, you can use the `sx` prop to style any component when you add the `jsxImportSource` pragma to the top of
your file.

```jsx
/** @jsxImportSource theme-ui */

export const Demo = (props) => (
  <div
    {...props}
    sx={{
      color: 'white',
      bg: 'primary',
      fontSize: 4,
    }}
  />
)
```

Bamboo has no `sx` prop. Write the same object with the `css` function and pass the class name it returns. Numeric scale
steps become named tokens — the default preset's `fontSizes` run `2xs` through `9xl`.

```jsx
import { css } from '../styled-system/css'

export const Demo = (props) => (
  <div
    {...props}
    className={css({
      color: 'white',
      bg: 'primary',
      fontSize: 'xl',
    })}
  />
)
```

Reach for [`cva`](/docs/concepts/recipes) instead when the styles need a name and variants.

## Variants

In Theme UI, variants are used to create groups of styles based on the theme. It offers variant groups in the theme for
several components.

- `Grid` maps to `theme.grids`
- `Button`, `IconButton` maps to `theme.buttons`
- `NavLink`, `Link` maps to `theme.links`
- `Input`, `Select`, `Textarea` maps to `theme.forms`
- `Heading`, `Text` maps to `theme.text`

```js
// theme.js

export default {
  colors: {
    primary: '#07c',
    secondary: '#30c',
    accent: '#609'
  },
  buttons: {
    primary: {
      color: 'white',
      bg: 'primary'
    },
    secondary: {
      color: 'white',
      bg: 'secondary'
    },
    accent: {
      color: 'white',
      bg: 'accent'
    }
  }
}

// Button.js
<button sx={{ variant: 'buttons.primary' }} />
```

In Bamboo, multi-variant styles are called recipes. Under Vite, inline and configured recipes resolve into the same
globally shared declaration atoms as `css()`. What you choose is where the recipe lives and how its typed API is
generated; recipe identity does not affect emitted CSS identity.

Colocated with the component, using the `cva` function:

```js
import { cva } from '../styled-system/css'

const buttonStyles = cva({
  className: 'button',
  base: {
    display: 'inline-flex',
  },
  variants: {
    variant: {
      primary: { color: 'white', bg: 'primary' },
      secondary: { color: 'white', bg: 'secondary' },
      accent: { color: 'white', bg: 'accent' },
    },
  },
})

const Demo = () => <button className={buttonStyles({ variant: 'accent' })} />
```

Or in the `theme.recipes` property of the bamboo config — 'config recipes' — which shares the recipe across components
and projects and generates only the variants the project uses. You then import it from `../styled-system/recipes`. See
[Recipes](/docs/concepts/recipes).

## Color Modes

In Theme UI, colors modes can be used to create a user-configurable light and dark mode values that are automatically
applied to components depending on color mode.

```jsx
// theme.js
const theme = {
  colors: {
    primary: '#07c',
    modes: {
      dark: {
        primary: '#0cf',
      },
    },
  },
}

// Button.js
const Demo = () => <button sx={{ color: 'primary' }} />
```

In Bamboo, color mode values are defined as `semanticTokens` in the theme. Semantic tokens change depending on the color
mode, so the call site stays an ordinary `css({ color: 'primary' })`.

```js
// bamboo.config.js
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  theme: {
    extend: {
      semanticTokens: {
        colors: {
          primary: { value: { base: '#07c', _dark: '#0cf' } },
        },
      },
    },
  },
})
```

## Global Styles

Theme UI offers a Global component (that wraps Emotion’s) for adding global CSS with theme-based values.

```jsx
import { Global } from 'theme-ui'

export default (props) => (
  <Global
    styles={{
      button: {
        m: 0,
        bg: 'primary',
        color: 'background',
        border: 0,
      },
    }}
  />
)
```

In Bamboo, global styles are defined in the top-level `global.css` property of the bamboo config — not under `theme`.

```js
// bamboo.config.js
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  global: {
    css: {
      button: {
        m: 0,
        bg: 'primary',
        color: 'background',
        border: 0,
      },
    },
  },
})
```

## Component Styles

Theme UI offers pre-defined layout components like `Box`, `Stack`, `Grid`, `Flex`

```jsx
import { Box, Grid } from 'theme-ui'

const Demo = () => (
  <Grid width={[128, null, 192]}>
    <Box bg="primary">Box</Box>
    <Box bg="muted">Box</Box>
    <Box bg="primary">Box</Box>
    <Box bg="muted">Box</Box>
  </Grid>
)
```

In Bamboo, these are called "layout patterns", or "patterns" for short. Each one is a function that returns a class
name, so it composes with any element.

```jsx
import { css } from '../styled-system/css'
import { grid } from '../styled-system/patterns'

const Demo = () => (
  <div className={grid({ width: [128, null, 192] })}>
    <div className={css({ bg: 'primary' })}>Box</div>
    <div className={css({ bg: 'muted' })}>Box</div>
  </div>
)
```
