---
title: Customizing Patterns
description:
  Bamboo provides the ability to customize the built-in patterns, as well as creating your own custom patterns. This is
  useful to create your own layout pattern abstractions that can be used in your application.
---

Bamboo allows you to customize built-in patterns and create custom patterns for reusable layout abstractions.

A pattern accepts the following parameters:

- `description` - The description of the pattern.
- `properties` - The list of properties that the pattern accepts.
- `defaultValues` - The default values for the properties. This is useful when you want to provide a default value for a
  property.
- `transform` - The function that accepts the properties and a set of [helpers](#transform-helpers), and returns a css
  object.
- `cssProps` - Which css properties the pattern accepts beside its own: `'all'`, `'none'`, or `{ except: [...] }`. Can
  be used to ensure strict typings when using the pattern.
- `strict` - Whether to only generate types for the specified properties. This will disallow css properties.

## Transform helpers

`transform` receives a second argument with everything it needs to shape values it cannot inspect itself:

| helper                   | returns                                                                       |
| ------------------------ | ----------------------------------------------------------------------------- |
| `map(value, fn)`         | `fn` applied to a value, or to each leaf of a conditional one                 |
| `token(path, fallback?)` | the css variable for a token path, or `fallback` when the path names no token |
| `isCssUnit(value)`       | whether the value is a css length, e.g. `10px`                                |
| `isCssVar(value)`        | whether the value is a `var(...)` reference                                   |
| `isCssFunction(value)`   | whether the value is a css function call                                      |

`token` is what lets a pattern accept either a token name or a raw css value, which is how the built-in `bleed`, `grid`
and `spacer` patterns work:

```ts
transform(props, { token, isCssUnit }) {
  // '4' → var(--spacing-4) · 'auto' → auto · '10px' → 10px
  const value = isCssUnit(props.size) ? props.size : token(`spacing.${props.size}`, props.size)
  return { flex: `0 0 ${value}` }
}
```

Resolve the token here rather than emitting a reference for the css pipeline to read later — the build, the extractor
and the browser all answer through this helper, so the value a pattern produces is the same in each.

## Creating a Pattern

To create a pattern, you can use the `patterns` property in the config. Let's say we want to create a "Scrollable"
pattern that applies preset styles to a container that allows for scrolling.

```js
const config = {
  patterns: {
    extend: {
      scrollable: {
        description: 'A container that allows for scrolling',
        defaultValues: {
          direction: 'vertical',
          hideScrollbar: true,
        },
        properties: {
          // The direction of the scroll
          direction: { type: 'enum', value: ['horizontal', 'vertical'] },
          // Whether to hide the scrollbar
          hideScrollbar: { type: 'boolean' },
        },
        // disallow the `overflow` property (in TypeScript)
        cssProps: { except: ['overflow'] },
        transform(props) {
          const { direction, hideScrollbar, ...rest } = props
          return {
            overflow: 'auto',
            height: direction === 'horizontal' ? '100%' : 'auto',
            width: direction === 'vertical' ? '100%' : 'auto',
            scrollbarWidth: hideScrollbar ? 'none' : 'auto',
            WebkitOverflowScrolling: 'touch',
            '&::-webkit-scrollbar': {
              display: hideScrollbar ? 'none' : 'auto',
            },
            ...rest,
          }
        },
      },
    },
  },
}
```

Then you can run the following command to generate the pattern JS code:

```bash
pnpm bamboo codegen
```

Now you can import the pattern and use it in your application:

```js
import { scrollable } from '../styled-system/patterns'

const App = () => {
  return (
    <div className={scrollable({ direction: 'vertical', hideScrollbar: true })}>
      <div>Scrollable content</div>
    </div>
  )
}
```

## Customizing Built-in Patterns

You can extend the [default patterns](/docs/concepts/patterns#predefined-patterns) by using the `patterns.extend`
property in the config.

```ts filename="bamboo.config.ts"
import { defineConfig } from '@bamboocss/dev'

export default defineConfig({
  patterns: {
    extend: {
      // Extend the default `flex` pattern
      flex: {
        properties: {
          // only allow row and column
          direction: { type: 'enum', value: ['row', 'column'] },
        },
      },
    },
  },
})
```

Then you can run the following command to update the pattern JS code:

```bash
pnpm bamboo codegen
```
