# Bamboo CSS Complete Documentation > Bamboo CSS is a build-time, type-safe, zero-runtime CSS-in-JS framework. It prunes unused tokens, tree-shakes the runtime, and folds static styles into plain class strings. This document contains the complete Bamboo CSS documentation, organized by category for easy navigation. ## Table of Contents ### Overview - [Browser Support](#browser-support) - [Frequently Asked Questions](#frequently-asked-questions) - [Get started with Bamboo](#get-started-with-bamboo) - [Why Bamboo](#why-bamboo) ### Installation - [Using Angular](#using-angular) - [Using Astro](#using-astro) - [Bamboo CLI](#bamboo-cli) - [Using Ember](#using-ember) - [Using Gatsby](#using-gatsby) - [Using Next.js](#using-next.js) - [Using Nuxt](#using-nuxt) - [Using PostCSS](#using-postcss) - [Using Preact](#using-preact) - [Using Qwik](#using-qwik) - [Using React Router](#using-react-router) - [Using Redwood](#using-redwood) - [Using Remix](#using-remix) - [Using Rsbuild](#using-rsbuild) - [Using SolidJS](#using-solidjs) - [Using Storybook](#using-storybook) - [Using Svelte](#using-svelte) - [Using Vite](#using-vite) - [Using Vue](#using-vue) ### Concepts - [Cascade Layers](#cascade-layers) - [Color opacity modifier](#color-opacity-modifier) - [Conditional Styles](#conditional-styles) - [The extend keyword](#the-extend-keyword) - [Global Styles](#global-styles) - [Bamboo Integration Hooks](#bamboo-integration-hooks) - [JSX Style Context](#jsx-style-context) - [Merging Styles](#merging-styles) - [Patterns](#patterns) - [Recipes](#recipes) - [Responsive Design](#responsive-design) - [Slot Recipes](#slot-recipes) - [Style props](#style-props) - [Styled System](#styled-system) - [Template Literals](#template-literals) - [Virtual Color](#virtual-color) - [Writing Styles](#writing-styles) ### Theming - [Animation Styles](#animation-styles) - [Layer Styles](#layer-styles) - [Spec](#spec) - [Using Bamboo Studio](#using-bamboo-studio) - [Text Styles](#text-styles) - [Tokens](#tokens) - [Using Tokens](#using-tokens) ### Utilities - [Background](#background) - [Border](#border) - [Display](#display) - [Divide](#divide) - [Effects](#effects) - [Flex and Grid](#flex-and-grid) - [Focus Ring](#focus-ring) - [Gradients](#gradients) - [Helpers](#helpers) - [Interactivity](#interactivity) - [Layout](#layout) - [List](#list) - [Outline](#outline) - [Sizing](#sizing) - [Spacing](#spacing) - [SVG](#svg) - [Tables](#tables) - [Transforms](#transforms) - [Transitions](#transitions) - [Typography](#typography) ### Customization - [Conditions](#conditions) - [Config Functions](#config-functions) - [Deprecations](#deprecations) - [Customizing Patterns](#customizing-patterns) - [Presets](#presets) - [Theme](#theme) - [Utilities](#utilities) ### Guides - [Using Bamboo in a Component Library](#using-bamboo-in-a-component-library) - [Debugging](#debugging) - [Dynamic styling](#dynamic-styling) - [Custom Font](#custom-font) - [Minimal Setup](#minimal-setup) - [Multi-Theme Tokens](#multi-theme-tokens) - [Source Transformation](#source-transformation) - [Static CSS Generator](#static-css-generator) ### Migration - [Migrating from Panda CSS](#migrating-from-panda-css) - [Migrating from Stitches](#migrating-from-stitches) - [Migrating from Styled Components](#migrating-from-styled-components) - [Migrating from Theme UI](#migrating-from-theme-ui) ### References - [CLI Reference](#cli-reference) - [Configuring Bamboo](#configuring-bamboo) --- # Overview ## Browser Support Learn about the browser support for Bamboo Bamboo CSS is built with modern CSS features and uses [PostCSS](https://postcss.org/) to add support for older browsers. Bamboo supports the latest, stable releases of major browsers that support the following features: - [CSS Variables](https://caniuse.com/css-variables) - [CSS Cascade Layers](https://caniuse.com/css-cascade-layers) - Modern selectors, such as [`:where()`](https://caniuse.com/mdn-css_selectors_where) and [`:is()`](https://caniuse.com/css-matches-pseudo) ## Browserlist Based on the above criteria, the following browsers are supported: ```txt >= 1% last 1 major version not dead Chrome >= 99 Edge >= 99 Firefox >= 97 iOS >= 15.4 Safari >= 15.4 Android >= 115 Opera >= 73 ``` ## Polyfills In event that you need to support older browsers, you can use the following polyfills in your PostCSS config: - [autoprefixer](https://github.com/postcss/autoprefixer): Adds vendor prefixes to CSS rules using values from [Can I Use](https://caniuse.com/). - [postcss-cascade-layers](https://www.npmjs.com/package/@csstools/postcss-cascade-layers): Adds support for CSS Cascade Layers. Here is an example of a `postcss.config.js` file that uses these polyfills: ```js module.exports = { plugins: ['@bamboocss/dev/postcss', 'autoprefixer', '@csstools/postcss-cascade-layers'], } ``` --- ## Frequently Asked Questions Frequently asked questions and how to resolve common issues ## How does Bamboo manage style conflicts ? When you combine shorthand and longhand properties, Bamboo will resolve the styles in a predictable way. The shorthand property will take precedence over the longhand property. ```jsx import { css } from '../styled-system/css' const styles = css({ paddingTop: '20px', padding: '10px', }) ``` The styles generated at build time will look like this: ```css @layer utilities { .p_10px { padding: 10px; } .pt_20px { padding-top: 20px; } } ``` --- ## Imported Image is not working in Vite App This is a known limitation of Bamboo due to our static extraction approach. > Think of it this way: there's no way for the compiler to know what the final asset URL will be since Vite controls it. We recommend moving the imported `backgroundImage` to the `style` attribute. ```jsx import myImageBackground from './my-image.png' const Demo = () => { return (

Hello World

) } ``` --- ## How to get Bamboo to work with Jest? If you run into error messages like `SyntaxError: Unexpected token 'export'` when running Jest tests. Here's what you can: In your tsconfig, add ```json { "compilerOptions": { "allowJs": true } } ``` In your Jest configuration, add the `ts-jest` transformer: ```ts export default { // ... transform: { '^.+\\.tsx?$': 'ts-jest', '^.+\\.(ts|tsx|js|jsx)?$': 'ts-jest', }, } ``` In your Bamboo config, set the `outExtension` to `js`: ```ts export default defineConfig({ // ... outExtension: 'js', }) ``` --- ## HMR does not work when I use `tsconfig` paths? Bamboo tries to automatically infer and read the custom paths defined in `tsconfig.json` file. However, there might be scenarios where the hot module replacement doesn't work. To fix this add the `importMap` option to your `bamboo.config.js` file, setting it's value to the specified `paths` in your `tsconfig.json` file. ```json // tsconfig.json { "compilerOptions": { "baseUrl": "./src", "paths": { "@my-path/*": ["./styled-system/*"] } } } ``` ```js // bamboo.config.js module.exports = { importMap: '@my-path', } ``` This will ensure that the paths are resolved correctly, and HMR works as expected. --- ## HMR not triggered If you are having issues with HMR not being triggered after a `bamboo.config.ts` change (or one of its [dependencies](/docs/references/config#dependencies)), you can manually specify the files that should trigger a rebuild by adding the following to your `bamboo.config.ts`: ```js filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... dependencies: ['path/to/files/**.ts'], }) ``` --- ## Why are my styles not applied? Check that the [`@layer` rules](/docs/concepts/cascade-layers#layer-css) are set and the corresponding `.css` file is included. [If you're not using `postcss`](/docs/installation/cli), ensure that `styled-system/styles.css` is imported and that the `bamboo` command has been run (or is running with `--watch`). --- ## How can I debug the styles? You can use the `bamboo debug` to debug design token extraction & css generated from files. If the issue persists, you can try looking for it in the [issues](https://github.com/bamboocss/bamboo/issues). If you can't find it, please create a minimal reproduction and submit [a new github issue](https://github.com/bamboocss/bamboo/issues/new/choose) so we can help you. --- ## Why is my IDE not showing `styled-system` imports? If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your tsconfig.json file. --- ## How do I get a type with each recipe properties? You can get a [`config recipe`](/docs/concepts/recipes#config-recipe) properties types by using `XXXVariantProps`. Let's say you have a `config recipe` named `button`, you can import its type like this: ```ts import { button, type ButtonVariantProps } from '../styled-system/recipes' ``` --- You can get an [`atomic recipe`](/docs/concepts/recipes#atomic-recipe) properties types by using `RecipeVariantProps`. Let's say you have a `atomic recipe` named `button`, you can get its type like this: ```ts import { cva, type RecipeVariantProps } from '../styled-system/css' export type ButtonVariantProps = RecipeVariantProps ``` --- ## How do I split recipe props from the rest? You can split recipe props by using `xxx.splitVariantProps`. Let's say you have a `recipe` named `button`, you can split its props like this: ```tsx Button.tsx {8} import { css, cx } from '../styled-system/css' import { ButtonVariantProps, button } from '../styled-system/recipes' interface ButtonProps extends ButtonVariantProps { children: React.ReactNode } export function Button(props: ButtonProps) { const { children, ...rest } = props const [buttonProps, cssProps] = button.splitVariantProps(rest) return } ``` The same `xxx.splitVariantProps` method is available for both `config recipes` and `atomic recipes`. --- ## How do I reference a token value or css var? You can reference a token value or it's associated css variable using the [`token` function](/docs/theming/usage#vanilla-js). This function allows you to access and use the values stored in your theme tokens at runtime. ```tsx import { token } from '../styled-system/tokens' function App() { return (
) } ``` --- ## Should I commit the styled-system folder? Just like the `node_modules` folder, you most likely don't want to commit the `styled-system` folder. It contains code that is auto-generated and can be re-generated at any time. --- ## How is Bamboo CSS different from Panda CSS? Bamboo CSS is a fork of Panda CSS v1, so the styling API is the same and [migrating](/docs/migration/panda) is mostly a rename. What has changed since the fork is everything below: what gets shipped to the browser, what it costs at runtime, and how quickly the build turns around. Every number here was measured against this repository's own sandboxes and fixtures. Your project will differ — the output-size wins in particular scale with the size of your design system rather than the size of your app. ### Less CSS - [`pruneUnusedTokens`](/docs/references/config#pruneunusedtokens) drops token CSS variables nothing can reach. The token layer declares every token in your theme while an app uses a fraction of them. On the `vite-ts` sandbox this takes `styles.css` from 24,433 to 12,293 bytes — 6,398 to 3,504 gzipped. - [`pruneUnusedKeyframes`](/docs/references/config#pruneunusedkeyframes) does the same for `@keyframes` rules a preset declares and your app never animates. Both are opt-in and change nothing until switched on. ### Less JavaScript - The generated output now declares `sideEffects`, so a bundler can tree-shake the barrels. Previously `import { Box } from 'styled-system/jsx'` retained every pattern module. - The JSX property list is emitted once rather than twice. It carried the browser CSS properties and your project's properties as two constants that the runtime immediately concatenated, with 285 entries appearing in both; the module drops from 15,684 to 11,468 bytes. Together a JSX barrel import goes from 41.2 KB to 30.1 KB minified, and 12.6 KB to 10.2 KB gzipped. ### A faster runtime - `css()` and the pattern helpers memoize their class names on a structural hash confirmed by an exact comparison. Repeated `css()` calls get roughly 4-5x faster, multi-argument calls about 4x, and the pattern helpers — which were not memoized at all — about 1.3x. Class name output is unchanged. - That cache is bounded. It previously grew for the lifetime of the process, which leaked in long-lived SSR. - Copying styles now happens at the `raw()` boundary rather than on every merge, so the two places that need an independent object pay for it instead of every caller. - The JSX factory no longer memoizes its props. Both `useMemo` calls keyed off a rest-destructured object, so neither could ever hit. About 3% on an unfolded tree. - `splitProps` reads each key's descriptor on demand rather than building one for the whole object: 2.4-2.9x on plain and frozen props. Accessor props, which is what Solid compiles to, keep the descriptor path. ### Optional zero-runtime output [`@bamboocss/vite`](/docs/guides/source-transformation) rewrites statically-resolvable calls into the class string they would have returned, so they cost nothing at runtime: ```tsx // you write export const title = css({ fontSize: 'lg', fontWeight: 'bold' }) // the bundle gets export const title = 'fs_lg fw_bold' ``` It also collapses `styled.*` elements to the intrinsic tag they render, folds config recipes, pattern elements and a static `as` prop, and follows named imports across files. CSS output is unchanged — only the JavaScript changes. It is off by default, build-only, and reports how much of your source it managed to fold. ### Less HTML [`cssMode: 'grouped'`](/docs/references/config#cssmode) emits one class per `css()` call rather than one per property, so an element carrying a dozen atomic classes carries one instead. Atomic CSS is a good default, but at scale it puts long class sequences into the markup and multiplies the declarations the browser walks during style recalculation — a cost `hash` does not address, since it shortens class names rather than reducing their count. Grouped trades some CSS duplication for the other side of that: a shared declaration is repeated in every group instead of deduping into one class. Which way that goes depends on whether your bottleneck is the CSS bundle or the HTML payload, so it is opt-in and atomic stays the default. It matters most under SSR and SSG, where the HTML is rarely cached and lands on every initial render. The [upstream proposal](https://github.com/chakra-ui/panda/pull/3531) has the benchmarks behind that. ### Faster builds - The dependency graph resolves imports without initializing the TypeScript type checker, which was costing hundreds of milliseconds on a cold build for what is only a filesystem question. - Watch mode builds the stylesheet once per edit rather than once per affected file. Editing a shared style file with 60 importers previously ran the full optimize pipeline and wrote to disk 61 times. - Editing a shared style file now re-parses the files importing it, so consumers stop emitting stale styles. --- ## How does Bamboo work? When running `pnpm bamboo`, here's what's happening under the hood: - **Load Bamboo context**: - Find and evaluate app config, merge result with presets. - Create bamboo context: prepare code generator from config, parse user's file as AST. - **Generating artifacts**: - Write lightweight JS runtime and types to output directory - **Extracting used styles in app code**: - Run parser on each user's file: identify and extract styles, compute CSS, write to styles.css. --- ## I'm seeing a "Could not resolve xxx" error with esbuild/tsdown. What should I do? In such a case, check the [`outExtension`](/docs/references/config#outextension) in your `bamboo.config` and set it to "js". This will ensure your modules are resolved correctly. --- ## Why does importing `styled` not exist? You should use [`config.jsxFramework`](/docs/concepts/style-props#configure-jsx) when you need to import styled components. You can then use the [`jsxFactory`](/references/config#jsxfactory) option to set the name of the factory component. --- ## Why is my preset overriding the base one, even after adding it to the array? You might have forgotten to include the `extend` keyword in your config. Without `extend`, your preset will completely replace the base one, instead of merging with it. --- ## Why is my base condition not working in this example? ```ts css({ color: { _base: 'red.600', _dark: 'white' } }) ``` You used `_base` instead of `base`, there is no underscore `_`. --- ## What's the difference between using `defineConfig()` vs `definePreset()` `defineConfig` is intended to be used in your app config, and will show you all the config keys that are available. `definePreset` will only show you the config keys that will be merged into an app's config, the rest will be ignored. --- ## How can I completely override the default tokens?. If you want to **completely override all** of the default presets theme tokens, you can omit the `extends` keyword from your `theme` config object. If you want to **keep some of the defaults**, you can install the `@bamboocss/preset-bamboo` package, import it, then specifically pick what you need in there (or use the JS spread operator `...` and override the other keys). --- ## How do I make a design system / component library with Bamboo? There is a detailed guide on how to do this [here](/docs/guides/component-library). --- ## Can I use dynamic styles with Bamboo? Yes, you can use dynamic styles with Bamboo. More on that [here](/docs/guides/dynamic-styling#runtime-conditions). --- ## Can Bamboo resolve styles at build time instead of at runtime? Yes, for the parts it can see. `@bamboocss/vite` rewrites statically-resolvable style calls into the class string they would have returned, so those calls cost nothing on render: ```tsx export const title = css({ fontSize: 'lg' }) export const title = 'fs_lg' ``` It covers `css()`, pattern and recipe calls, `styled.*` and pattern elements, and the static half of anything only partly static. The CSS is unchanged; only the JavaScript is. Off by default and build-only — see [Source Transformation](/docs/guides/source-transformation). --- ## Should I use atomic or config recipes ? [Config recipes](/docs/concepts/recipes#config-recipe) are generated just in time, meaning that only the recipes and variants you use will exist in the generated CSS, regardless of the number of recipes in the config. This contrasts with [Atomic recipes](/docs/concepts/recipes#atomic-recipe) (cva), which generates all of the variants regardless of what was used in your code. The reason for this difference is that all `config.recipes` are known at the start of the bamboo process when we evaluate your config. In contrast, the CVA recipes are scattered throughout your code. To get all of them and find their usage across your code, we would need to scan your app code multiple times, which would not be ideal performance-wise. When dealing with simple use cases, or if you need code colocation, or even avoiding dynamic styling, atomic recipes shine by providing all style variants. Config recipes are preferred for design system components, delivering leaner CSS with only the styles used. Choose according to your component needs. --- ## Why does the bamboo codegen command fail ? If you run into any error related to "Transforming const to the configured target environment ("es5") is not supported yet", update your tsconfig to use es6 or higher: ```json filename="tsconfig.json" { "compilerOptions": { "target": "es6" } } ``` --- ## How can I generate all possible CSS variants at build time? While it's possible to generate all variants, even unused ones, by using [`config.staticCss`](https://bamboocss.com/docs/guides/dynamic-styling#using-static-css), it's generally **not recommended** to use it for more than a few values. However, keep in mind this approach compromises one of Bamboo's strengths: lean, usage-based CSS generation. --- ## Can I use one-off media query and other at rules? Yes, you can! You can apply one-off media queries and other at rules (such as `@container`, `@supports`) in your CSS as shown below: ```javascript css({ containerType: 'size', '@media (min-width: 10px)': { fontSize: 'xl', color: 'blue.300', }, '@container (min-width: 10px)': { fontSize: '2xl', color: 'green.300', }, '@supports (display: flex)': { fontSize: '3xl', color: 'red.300', }, }) ``` --- ## How can I prevent other libraries from overriding my styles? You can use [Layer Imports]() to prevent other libraries from overriding your styles. First of all you cast the css from the other library(s) to a css layer: ```css @import url('bootstrap.css') layer(bootstrap); @import url('ionic.css') layer(ionic); ``` Then update the default layer list to deprioritize the styles from the other library(s): ```css @layer bootstrap, reset, base, token, recipes, utilities; @layer ionic, reset, base, token, recipes, utilities; ``` --- ## Get started with Bamboo The universal design system solution for the web Bamboo is a styling engine that generates styling primitives to author atomic CSS and recipes in a type-safe and readable manner. Bamboo combines the developer experience of CSS-in-JS and the performance of atomic CSS. It leverages static analysis to scan your JavaScript and TypeScript files for JSX style props and function calls, generating styles on-demand (aka Just-in-Time) > TLDR; Bamboo is a CSS-in-JS engine that generates atomic CSS at build time (via CLI or PostCSS) ## How is this different from Panda CSS? Bamboo CSS is a fork of [Panda CSS](https://panda-css.com/) v1, so the styling API is identical and [migrating](/docs/migration/panda) is mostly a rename. What has changed since the fork is what reaches the browser and what it costs: - **Less CSS** — [`pruneUnusedTokens`](/docs/references/config#pruneunusedtokens) drops token variables nothing can reach, taking `styles.css` from 24.4 KB to 12.3 KB on our own sandbox. - **Less JavaScript** — the generated output declares `sideEffects` and stops emitting the JSX property list twice, so a barrel import falls from 41.2 KB to 30.1 KB minified. - **A faster runtime** — repeated `css()` calls are roughly 4-5x faster, and the class-name cache is bounded rather than growing for the life of the process, which used to leak under long-lived SSR. - **Optional zero runtime** — [`@bamboocss/vite`](/docs/guides/source-transformation) folds statically-resolvable `css()` calls into plain class strings at build time. - **Less HTML** — [`cssMode: 'grouped'`](/docs/references/config#cssmode) emits one class per `css()` call instead of one per property, trading CSS duplication for shorter class attributes and faster style recalculation. Every figure is measured against this repository's own sandboxes; the output-size wins scale with the size of your design system rather than your app. The [full comparison](/docs/overview/faq#how-is-bamboo-css-different-from-panda-css) has the rest. ## Installation ### General Guides - [Bamboo CLI](/docs/installation/cli): The simplest way to use Bamboo is with the Bamboo CLI tool. - [Using PostCSS](/docs/installation/postcss): (**Recommended**) Installing Bamboo as a PostCSS plugin is the recommended way to integrate it with your project. ### Framework Guides Start using Bamboo CSS in your JavaScript framework using our framework-specific guides that cover our recommended approach. ## Next Steps Get familiar with the core features and concepts in Bamboo. ## Acknowledgement Bamboo CSS started as a fork of [Panda CSS](https://panda-css.com/). --- ## Why Bamboo From the endless list of CSS-in-JS libraries, why should you choose Bamboo? Runtime CSS-in-JS and style props are powerful features that allow developers to build dynamic UI components that are composable, predictable, and easy to use. However, it comes at the cost of performance and runtime. ## Backstory With the release of Server Components and the rise of server-first frameworks, most existing runtime CSS-in-JS styling solutions (like emotion, styled-components) either can't work reliably, or can't work anymore. This new paradigm is a huge win for performance, development, and user experience, however, it poses a new "Innovate or Die" challenge for CSS-in-JS libraries. > **Fun Fact:** Most CSS-in-JS libraries have a pinned issue on their GitHub repo about "Next app dir" or/and "Server > Components" 😅, making the challenge even more obvious. So, the question is, **is CSS-in-JS dead?** The answer is **no, but it needs to evolve!** ## The new era of CSS-in-JS Bamboo is a new CSS-in-JS engine that aims to solve the challenges of CSS-in-JS in the server-first era. It provides styling primitives to create, organize, and manage CSS styles in a type-safe and readable manner. - **Static Analysis:** Bamboo uses static analysis to parse and analyze your styles at build time, and generate CSS files that can be used in any JavaScript framework. - **PostCSS:** After static analysis, Bamboo uses a set of PostCSS plugins to convert the parsed data to atomic css at build time. **This makes Bamboo compatible with any framework that supports PostCSS.** - **Codegen:** Bamboo generates a lightweight runtime JS code that is used to author styles. **Think of it as an optimized function that joins key-value pairs of an object**. It doesn't generate styles in the browser nor inject styles in the ``. - **Type-Safety:** Bamboo combines `csstype` and auto-generated typings to provide type-safety for css properties and design tokens. - **Performance:** Bamboo uses a unique approach to generate atomic CSS files that are optimized for performance and readability. - **Developer Experience:** Bamboo provides a great developer experience with a rich set of features like recipes, patterns, design tokens, JSX style props, and more. - **Modern CSS**: Bamboo uses modern CSS features like cascade layers, css variables, modern selectors like `:where` and `:is` in generated styles. ## When to use Bamboo? ### Styling engine If you're building a JavaScript application with a framework that supports PostCSS, Bamboo is a great choice for you. ```jsx import { css } from '../styled-system/css' import { circle, stack } from '../styled-system/patterns' function App() { return (
avatar
John Doe
john@doe.com
) } ``` > If your framework doesn't support PostCSS, you can use the [Bamboo CLI](/docs/installation/cli) ### Token generator Bamboo has first-class support for design tokens. It provides a way to express raw and semantic tokens for your project. The generator can be used to create a set of CSS variables for your design tokens. ```ts filename="bamboo.config.ts" export default defineConfig({ emitTokensOnly: true, theme: { tokens: { colors: { gray50: { value: '#F9FAFB' }, gray100: { value: '#F3F4F6' }, }, }, semanticTokens: { colors: { primary: { value: '{colors.gray50}' }, success: { value: { _light: '{colors.green500}', _dark: '{colors.green200}' }, }, }, }, }, }) ``` Running the `bamboo codegen` will generate ```css filename="styled-system/tokens/index.css" :root { --colors-gray50: #f9fafb; --colors-gray100: #f3f4f6; --colors-primary: var(--colors-gray50); --colors-success: var(--colors-green500); } [data-theme='dark'] { --colors-primary: var(--colors-gray50); --colors-success: var(--colors-green200); } ``` Then you have a set of css variables that you can use in your project. ```css @import '../styled-system/tokens/index.css'; .card { background-color: var(--colors-gray50); } ``` ## When not to use Bamboo? Bamboo isn't the right fit for your project if: - You're building with HTML and CSS. - You're using a template-based framework like PHP. - You're looking for an absolute zero JS solution. In these scenarios, we recommend that you use vanilla CSS (which is getting awesome by the day), or other utility based CSS libraries. --- # Installation ## Using Angular Easily use Bamboo with Angular with our dedicated integration. This guide shows you how to set up Bamboo CSS in an Angular project using PostCSS. ## Start a new project ### Create Vite project To get started, we will need to create a new Angular project using the official [scaffolding tool](https://angular.dev/tools/cli). If you don't enter any parameter, the CLI will guide you through the process of creating a new Angular app. ```bash ng new test-app ``` You will be asked a few questions, answer them as follows: ```bash ? Which stylesheet format would you like to use? CSS ? Do you want to enable Server-Side Rendering (SSR) and Static Site Generation (SSG/Prerendering)? No ``` ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init ``` ```bash npm install -D @bamboocss/dev npx bamboo init ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init ``` ```bash bun add -D @bamboocss/dev bun bamboo init ``` {/* */} ### Configure PostCSS Create a `postcss.config.json` file in the root of your project and add the following code: ```json filename="postcss.config.json" { "plugins": { "@bamboocss/dev/postcss": {} } } ``` > You must use a JSON file for the PostCSS configuration, as the Angular CLI does not support JavaScript PostCSS > configuration files. ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "ng": "ng", "start": "ng serve", "build": "ng build", } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Angular components are included in the `include` section of the `bamboo.config.ts` file. ```js {8,17} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/index.css` file and import it in the root component of your project. ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/app.component.ts` file. ```typescript filename="src/app.component.ts" import { Component } from '@angular/core' import { css } from '../styled-system/css' @Component({ selector: 'app-root', standalone: true, template: `
`, }) export class App { redBg = css({ bg: 'red.400' }) } ```
--- ## Using Astro Easily use Bamboo with Astro with our dedicated integration. This guide shows you how to set up Bamboo CSS in an Astro project using our dedicated integration. ## Setup ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} { "scripts": { + "prepare": "bamboo codegen", "dev": "astro dev", "start": "astro start", "build": "astro build", "preview": "astro preview" } } ``` The `prepare` script that will run codegen after dependency installation. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Add your bamboo config to your `bamboo.config.js` file, or wherever bamboo is configured in your project. ```js {6} import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, // define the content to scan 👇🏻 include: ['./src/**/*.{ts,tsx,js,jsx,astro}', './pages/**/*.{ts,tsx,js,jsx,astro}'], exclude: [], outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add the layer css code to the `src/index.css` file ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` Then, import the `src/index.css` file in your page or layout file ```md filename="src/pages/index.astro" --- import '../index.css'; --- ``` ### Update the postcss config Astro requires a little change for the `postcss.config.[c]js`: ```diff {3} filename="postcss.config.js" module.exports = { - plugins: { - '@bamboocss/dev/postcss': {} - } + plugins: [require('@bamboocss/dev/postcss')()] } ``` ### Start your build process Run your build process with `npm run dev` or whatever command is configured in your package.json file. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Use the generated style utilities in your code, and bamboo will extract them to the generated CSS file. ```jsx --- import { css } from '../../styled-system/css'; ---
Hello !
```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Bamboo CLI An alternative way to use Bamboo is by running the Bamboo CLI tool. This guide shows you how to use Bamboo as an alternative approach by running the Bamboo CLI tool. ### Install Bamboo {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init ``` ```bash npm install -D @bamboocss/dev npx bamboo init ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init ``` ```bash bun add -D @bamboocss/dev bun bamboo init ``` {/* */} ### Configure the content Add the paths to all of your JavaScript or TypeScript code where you intend to use bamboo. ```js {5} import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, include: ['./src/**/*.{ts,tsx,js,jsx}', './pages/**/*.{ts,tsx,js,jsx}'], exclude: [], outdir: 'styled-system', }) ``` ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} { "scripts": { + "prepare": "bamboo codegen", } } ``` The `prepare` script that will run codegen after dependency installation. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Import the generated CSS For each Bamboo run, it emits the generated CSS at the `styled-system/styles.css` file path. Import this file at the root component of your project. ```jsx {1} import './styled-system/styles.css' export function App() { return
Page
} ``` ### Start the Bamboo build process Run the CLI tool to scan your JavaScript and TypeScript files for style properties and call expressions. {/* */} ```bash # Run it once pnpm bamboo # Run it in watch mode pnpm bamboo --watch ``` ```bash # Run it once npx bamboo # Run it in watch mode npx bamboo --watch ``` ```bash # Run it once yarn bamboo # Run it in watch mode yarn bamboo --watch ``` ```bash # Run it once bun bamboo # Run it in watch mode bun bamboo --watch ``` {/* */} ### Start using Bamboo Use the generated style utilities in your code and bamboo will extract them to the generated CSS file. Then run your build process. ```jsx import { css } from './styled-system/css' export function App() { return
} ``` ## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Ember Easily use Bamboo with Ember with our dedicated integration. This guide shows you how to set up Bamboo CSS in an Ember project using PostCSS. ## Start a new project ### Create Ember project To get started, we will need to create a new Ember project using the `embroider` build system. We will name our project `test-app` but you can name it whatever you want. {/* */} ```bash pnpm dlx ember-cli@latest new test-app --embroider --no-welcome --typescript --pnpm ``` ```bash npx ember-cli@latest new test-app --embroider --no-welcome --typescript ``` ```bash yarn dlx ember-cli@latest new test-app --embroider --no-welcome --typescript --yarn ``` ```bash bunx ember-cli@latest new test-app --embroider --no-welcome --typescript --skip-install ``` {/* */} Enter the newly created directory: ```bash cd test-app ``` ### Install Bamboo Install bamboo and its peer dependencies, as well as `postcss-loader`. Run the init command to generate the `bamboo.config.ts` and `postcss.config.js` file. {/* */} ```bash pnpm install -D @bamboocss/dev postcss postcss-loader pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev postcss postcss-loader npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev postcss postcss-loader yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev postcss postcss-loader bun bamboo init --postcss ``` {/* */} ### Enable PostCSS support In your `ember-cli-build.js` file, configure PostCSS to process your CSS files. ```js {12-23} filename="ember-cli-build.js" 'use strict' const EmberApp = require('ember-cli/lib/broccoli/ember-app') module.exports = function (defaults) { const app = new EmberApp(defaults, { // Add options here }) const { Webpack } = require('@embroider/webpack') return require('@embroider/compat').compatBuild(app, Webpack, { packagerOptions: { webpackConfig: { module: { rules: [ { test: /\.css$/i, use: ['postcss-loader'], }, ], }, }, }, // other options... }) } ``` ### Configure the PostCSS plugin Add the `.embroider` folder to the allow list so the Bamboo PostCSS plugin picks up your app CSS files. ```js {4} filename="postcss.config.cjs" module.exports = { plugins: { '@bamboocss/dev/postcss': { allow: [/node_modules\/.embroider/], }, }, } ``` ### Update package.json scripts Open the `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", // ... } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Ember components are included in the `include` section of the `bamboo.config.ts` file. Set the `outdir` to the app folder so the code can be imported in your Ember app. Adjust the `importMap` accordingly to reflect your app name. ```js {8,19-22} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./app/**/*.{js,ts,gjs,gts}'], // Files to exclude exclude: [], // Useful for theme customization theme: { extend: {}, }, // The output directory for your css system outdir: 'app/styled-system', // Configure the import map to use your project name importMap: 'test-app/styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `app/index.css` file. ```css filename="app/index.css" @layer reset, base, tokens, recipes, utilities; ``` Next, import the file in your `app/app.ts` file. ```ts {5} filename="app/app.ts" import Application from '@ember/application' import Resolver from 'ember-resolver' import loadInitializers from 'ember-load-initializers' import config from 'test-app/config/environment' import 'test-app/index.css' export default class App extends Application { modulePrefix = config.modulePrefix podModulePrefix = config.podModulePrefix Resolver = Resolver } loadInitializers(App, config.modulePrefix) ``` ### Start your build process Run the following command to start your development server. {/* */} ```bash pnpm start ``` ```bash npm run start ``` ```bash yarn start ``` ```bash bun start ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. ```ts filename="app/components/hello-bamboo.ts" import Component from '@glimmer/component' import { css } from 'test-app/styled-system/css' export default class HelloBamboo extends Component { style = css({ fontSize: '5xl', fontWeight: 'bold' }) } ``` ```hbs filename="app/components/hello-bamboo.hbs"
Hello 🎋!
``` ```hbs {5} filename="app/templates/application.hbs" {{page-title 'TestApp'}}

Welcome to Ember

{{outlet}} ``` > For the best developer experience, set up > [template tag component authoring format](https://guides.emberjs.com/release/components/template-tag-format/) in > Ember.
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["app/styled-system"] } ``` --- ## Using Gatsby Easily use Bamboo with Gatsby with our dedicated integration. This guide shows you how to set up Bamboo CSS in a Gatsby project using PostCSS. ### Create Gatsby project To get started, we will need to create a new Gatsby project. We will name our project `test-app` but you can name it whatever you want. If you don't enter any parameter, the CLI will guide you through the process of creating a new Gatsby app. ```bash npm init gatsby ``` You will be asked a few questions, answer them as follows: ``` ✔ What would you like to call your site? ... My Gatsby Site ✔ What would you like to name the folder where your site will be created? ... projects/ test-app ✔ Will you be using JavaScript or TypeScript? ... TypeScript ✔ Will you be using a CMS? ... No (or I'll add it later) ✔ Would you like to install a styling system? ... No (or I'll add it later) ✔ Would you like to install additional features with other plugins? ... No items were selected ``` Enter the newly created directory: ```bash cd test-app ``` ### Install Bamboo CSS Install Bamboo CSS and `gatsby-plugin-postcss` to your project. After that run the `bamboo init` command to setup Bamboo CSS in your project. ```bash npm install -D @bamboocss/dev postcss gatsby-plugin-postcss npx bamboo init --postcss ``` ### Setup the Gatsby PostCSS plugin Include the plugin in your `gatsby-config.ts` file. Check out the [official documentation](https://www.gatsbyjs.com/plugins/gatsby-plugin-postcss/) for more information. ```ts {9} filename="gatsby-config.ts" import type { GatsbyConfig } from 'gatsby' const config: GatsbyConfig = { siteMetadata: { title: `My Gatsby Site`, siteUrl: `https://www.yourdomain.tld`, }, graphqlTypegen: true, plugins: [`gatsby-plugin-postcss`], } export default config ``` ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "develop": "gatsby develop", "start": "gatsby develop", "build": "gatsby build", "serve": "gatsby serve", "clean": "gatsby clean", "typecheck": "tsc --noEmit" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your React components are included in the `include` section of the `bamboo.config.ts` file. > If you use [GraphQL Typegen](/docs/how-to/local-development/graphql-typegen/), you'll need to update the `include` to > avoid infinite loop due to generated `src/gatsby-types.d.ts`. ```js {6} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, // Where to look for your css declarations include: ['./src/pages/*.{js,jsx,ts,tsx}', './src/components/**/*.{js,jsx,ts,tsx}'], exclude: [], outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Create `src/styles/index.css` file and add the following content: ```css filename="src/styles/index.css" @layer reset, base, tokens, recipes, utilities; ``` ### Import the entry CSS Create a `gatsby-browser.ts` file in the root of your project and add the following content: ```ts filename="gatsby-browser.ts" import './src/styles/index.css' ``` ### Start your build process Run the following command to start your development server. ```bash npm run develop ``` ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/pages/index.tsx` file. ```tsx {3,7} filename="src/pages/index.tsx" import * as React from 'react' import type { HeadFC, PageProps } from 'gatsby' import { css } from '../../styled-system/css' const IndexPage: React.FC = () => { return
Hello 🎋!
} export default IndexPage export const Head: HeadFC = () => Home Page ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Next.js Easily use Bamboo with Next.js with our dedicated integration. Setting up Bamboo CSS with Next.js is straightforward. Follow the steps below to get started. If you don't have Next.js app installed, you can follow the [Create a Next.js app](#create-a-nextjs-app) section to create a new Next.js app, otherwise you can skip to the [Install Bamboo CSS](#install-bamboo-css) section. ## Start a new project You can chose between these two options to start a new project: ### Create a Next.js app First, create a Next.js app using the official [Create Next App](https://nextjs.org/docs/api-reference/create-next-app) CLI. We will name our project `test-app` but you can name it whatever you want. If you don't enter any parameter, the CLI will guide you through the process of creating a new Next.js app. {/* */} ```bash pnpm dlx create-next-app@latest --use-pnpm ``` ```bash npx create-next-app@latest --use-npm ``` ```bash yarn dlx create-next-app@latest --use-yarn ``` ```bash bunx create next-app@latest --use-bun ``` {/* */} You will be asked a few questions, answer them as follows: {/* */} ```bash ✔ What is your project named? … test-app ✔ Would you like to use TypeScript with this project? … Yes ✔ Would you like to use ESLint with this project? … Yes ✔ Would you like to use Tailwind CSS with this project? … No ✔ Would you like to use `src/` directory with this project? … Yes ✔ Use App Router (recommended)? … Yes ✔ Would you like to customize the default import alias? … No ``` {/* */} {/* */} ```bash ✔ What is your project named? … test-app ✔ Would you like to use TypeScript with this project? … Yes ✔ Would you like to use ESLint with this project? … Yes ✔ Would you like to use Tailwind CSS with this project? … No ✔ Would you like to use `src/` directory with this project? … Yes ✔ Use App Router (recommended)? … No ✔ Would you like to customize the default import alias? … No ``` {/* */} Enter the newly created directory: ```bash cd test-app ``` ### Install Bamboo CSS Install Bamboo CSS dependency using your favorite package manager. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} `bamboo init --postcss` command will automatically create a `postcss.config.js` file at the root of your project with the following code: ```js {3} module.exports = { plugins: { '@bamboocss/dev/postcss': {}, }, } ``` For advanced configuration follow the Next.js PostCSS guide to set up a custom PostCSS configuration by referring to this [link](https://nextjs.org/docs/pages/building-your-application/configuring/post-css#customizing-plugins). ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} { "scripts": { + "prepare": "bamboo codegen", "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" } } ``` The `prepare` script that will run codegen after dependency installation. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your React components are included in the `include` section of the `bamboo.config.ts` file. ```ts {7} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/components/**/*.{ts,tsx,js,jsx}', './src/app/**/*.{ts,tsx,js,jsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ```ts {7} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/components/**/*.{ts,tsx,js,jsx}', './src/pages/**/*.{ts,tsx,js,jsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers In your Next.js project, navigate to the `src/app` folder and open `globals.css` file. Replace all the content with the following code: In your Next.js project, navigate to the `src/styles` folder and open `globals.css` file. Replace all the content with the following code: ```css @layer reset, base, tokens, recipes, utilities; ``` > **Note:** Feel free to remove the `page.module.css` file as we don't need it anymore. > **Note:** Feel free to remove the `Home.module.css` file as we don't need it anymore. ### Import the entry CSS in your app Make sure that you import the `globals.css` file in your `src/app/layout.tsx` file as follows: ```tsx {1} filename="./src/app/layout.tsx" import './globals.css' import type { Metadata } from 'next' import localFont from 'next/font/local' const geistSans = localFont({ src: './fonts/GeistVF.woff', variable: '--font-geist-sans', weight: '100 900', }) const geistMono = localFont({ src: './fonts/GeistMonoVF.woff', variable: '--font-geist-mono', weight: '100 900', }) export const metadata: Metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( {children} ) } ``` Make sure that you import the `globals.css` file in your `src/pages/_app.tsx` file as follows: ```tsx {1} filename="./src/pages/_app.tsx" import '../styles/globals.css' import type { AppProps } from 'next/app' export default function App({ Component, pageProps }: AppProps) { return } ``` ### Start using Bamboo We will update the contents of `src/app/page.tsx` with the following snippet that uses Bamboo CSS: We will update the contents of `src/pages/index.tsx` with the following snippet that uses Bamboo CSS: ```tsx import { css } from '../../styled-system/css' export default function Home() { return
Hello 🎋!
} ``` ### Start the development server Run the following command to start the development server: {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
## Troubleshooting ### I don't see any styles Sometimes Next.js caches PostCSS generated styles and when that happens you need to clear the cache. To do that, delete the `.next` folder and restart your development server. You can also update you `package.json` scripts to delete the `.next` folder before each build: ```diff {3,4} { "scripts": { - "dev": "next dev", + "dev": "rm -rf .next && next dev", }, } ``` This is a known issue with Next.js and you can track the progress here: - [vercel/next.js#39410](https://github.com/vercel/next.js/issues/39410) - [vercel/next.js#48748](https://github.com/vercel/next.js/issues/48748) - [vercel/next.js#47533](https://github.com/vercel/next.js/issues/47533) ### I don't see any import autocomplete in my IDE If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` ### Codegen fails using es5 If you run into any error related to "Transforming const to the configured target environment ("es5") is not supported yet", update your tsconfig to use es6 or higher: ```json filename="tsconfig.json" { "compilerOptions": { "target": "es6" } } ``` --- ## Using Nuxt Easily use Bamboo with Nuxt with the vue integration. Learn how to set up Bamboo CSS in a Nuxt project using PostCSS. ## Start a new project ### Create Nuxt project To get started, we will need to create a new Nuxt project using npx. {/* */} ```bash npx nuxi@latest init test-app ``` ```bash pnpm dlx nuxi@latest init test-app ``` ```bash bunx nuxi@latest init test-app ``` {/* */} Enter the newly created directory and install the dependencies. {/* */} ```bash cd test-app pnpm install ``` ```bash cd test-app npm install ``` ```bash cd test-app yarn install ``` ```bash cd test-app bun install ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init ``` ```bash npm install -D @bamboocss/dev npx bamboo init ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init ``` ```bash bun add -D @bamboocss/dev bun bamboo init ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "build": "nuxt build", "dev": "nuxt dev", "generate": "nuxt generate", "preview": "nuxt preview" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Vue components are included in the `include` section of the `bamboo.config.ts` file. ```js {8,17} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./app.vue', './components/**/*.{js,jsx,ts,tsx,vue}', './pages/**/*.{js,jsx,ts,tsx,vue}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `assets/css/global.css` file. ```css filename="assets/css/global.css" @layer reset, base, tokens, recipes, utilities; ``` ### Configure Nuxt Add the following configuration to the `nuxt.config.ts` file ```js {1-2,5-17} filename="nuxt.config.ts" import { createResolver } from '@nuxt/kit' const { resolve } = createResolver(import.meta.url) export default defineNuxtConfig({ alias: { 'styled-system': resolve('./styled-system'), }, css: ['@/assets/css/global.css'], postcss: { plugins: { '@bamboocss/dev/postcss': {}, }, }, }) ``` With the above we've performed the following: - imported the global css file '@/assets/css/global.css' at the root of the system. - created an alias that points to the `styled-system` directory. - added bamboo into the postcss plugins section. ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. As an example here is a snippet of code for a `components/Demo.vue` file. ```xml filename="components/Demo.vue" ``` --- ## Using PostCSS Installing Bamboo as a PostCSS plugin is the recommended way to integrate it with your project. This guide shows you how to install Bamboo as a PostCSS plugin, which is the recommended way to integrate it with your project. ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev postcss pnpm bamboo init -p ``` ```bash npm install -D @bamboocss/dev postcss npx bamboo init -p ``` ```bash yarn add -D @bamboocss/dev postcss yarn bamboo init -p ``` ```bash bun add -D @bamboocss/dev postcss bun bamboo init -p ``` {/* */} ### Add Bamboo to your PostCSS config Add bamboo to your `postcss.config.cjs` file, or wherever PostCSS is configured in your project. ```js module.exports = { plugins: { '@bamboocss/dev/postcss': {}, }, } ``` ### Configure the content Add your bamboo config to your `bamboo.config.js` file, or wherever bamboo is configured in your project. ```js {5} import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, include: ['./src/**/*.{ts,tsx,js,jsx}', './pages/**/*.{ts,tsx,js,jsx}'], exclude: [], outdir: 'styled-system', }) ``` ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} { "scripts": { + "prepare": "bamboo codegen", } } ``` The `prepare` script will run codegen after dependency installation. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the entry CSS with layers Add this code to an `index.css` file which is going to be the root css of your project. ```css @layer reset, base, tokens, recipes, utilities; ``` ### Start your build process Run your build process by feeding the [root css](#configure-the-entry-css-with-layers) to PostCSS in your preferred way. {/* */} ```bash postcss -o output.css index.css ``` ```js const postcss = require("postcss"); const fs = require("fs"); fs.readFile("index.css", (err, css) => { postcss() .process(css, { from: "index.css", to: "output.css" }) .then((result) => { console.log(result.css); }); }); ``` {/* */} > If you're using a framework, PostCSS is probably already integrated with your build process. Check our other guides or > the documentation of your framework to see how to configure PostCSS. ### Start using Bamboo Use the generated style utilities in your code and bamboo will extract them to the generated CSS file. ```jsx import { css } from './styled-system/css' export function App() { return
} ``` ## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Preact Easily use Bamboo with Preact with our dedicated integration. This guide shows you how to set up Bamboo CSS in a Preact project using PostCSS. ## Start a new project ### Create Vite project To get started, we will need to create a new Preact project using `typescript` template. {/* */} ```bash npx preact-cli create typescript test-app cd test-app ``` ```bash npx preact-cli create typescript test-app --yarn cd test-app ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact build", "serve": "sirv build --cors --single", "dev": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact watch", "lint": "eslint src", "test": "jest" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Preact components are included in the `include` section of the `bamboo.config.ts` file. ```js {6} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}', './pages/**/*.{js,jsx,ts,tsx}'], exclude: [], outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/style/index.css` file imported in the root component of your project. ```css filename="src/style/index.css" @layer reset, base, tokens, recipes, utilities; ``` ## Start your build process Run the following command to start your development server. {/* */} ```bash npm run dev ``` ```bash yarn dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/routes/home/index.tsx` file. ```tsx filename="src/routes/home/index.tsx" import { h } from 'preact' import { css } from '../../../styled-system/css' const Home = () => { return
Hello 🎋!
} export default Home ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Qwik Easily use Bamboo with Qwik with our dedicated integration. Learn how to set up Bamboo CSS in a Qwik project using PostCSS. ## Start a new project ### Create Qwik project To get started, we will need to create a new Qwik project using `typescript` template. {/* */} ```bash npm create qwik@latest ``` ```bash pnpm create qwik@latest ``` ```bash yarn create qwik ``` ```bash bun create qwik@latest ``` {/* */} ### Install and Configure Bamboo Qwik provies an official script that installs bamboo and configures it for you. {/* */} ```bash npm run qwik add bamboocss ``` ```bash pnpm qwik add bamboocss ``` ```bash yarn qwik add bamboocss ``` ```bash bun qwik add bamboocss ``` {/* */} ## Start your build process Run the following command to start your development server. {/* */} ```bash npm run dev ``` ```bash pnpm dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. ```tsx filename="src/routes/layout.tsx" import { component$, Slot } from '@builder.io/qwik' import { routeLoader$ } from '@builder.io/qwik-city' import { css } from 'styled-system/css' export const useServerTimeLoader = routeLoader$(() => { return { date: new Date().toISOString(), } }) export default component$(() => { return (
) }) ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using React Router Easily use Bamboo with React Router with our dedicated integration. This guide will show you how to set up Bamboo CSS in a React Router project using PostCSS. ## Start a new project ### Create project To get started, we will need to create a new React Router project using the official [Create React Router](https://reactrouter.com/start/framework/installation) CLI. In this guide, we will use TypeScript. If you don't enter any parameter, the CLI will guide you through the process of creating a new React Router app. {/* */} ```bash pnpm dlx create-react-router@latest ``` ```bash npx create-react-router@latest ``` ```bash yarn dlx create-react-router@latest ``` ```bash bunx create-react-router@latest ``` {/* */} You will be asked a few questions, answer these as follows: ```sh ? Where should we create your new project? test-app ? Install dependencies? No ``` > **Note:** You should decline the dependency installation step as we will install dependencies together with Bamboo > CSS. ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "build": "cross-env NODE_ENV=production react-router build", "dev": "react-router dev", "start": "cross-env NODE_ENV=production react-router-serve ./build/server/index.js", "typecheck": "react-router typegen && tsc" }, } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the Bamboo CSS output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your React Router components are included in the `include` section of the `bamboo.config.ts` file. ```ts {5,8,11} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./app/**/{**,.client,.server}/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Replace TailwindCSS with BambooCSS Update the `vite.config.ts` file to use BambooCSS instead of TailwindCSS. ```ts {3,10} filename="vite.config.ts" import { reactRouter } from '@react-router/dev/vite' import autoprefixer from 'autoprefixer' import bamboocss from '@bamboocss/dev/postcss' import { defineConfig } from 'vite' import tsconfigPaths from 'vite-tsconfig-paths' export default defineConfig({ css: { postcss: { plugins: [bamboocss, autoprefixer], }, }, plugins: [reactRouter(), tsconfigPaths()], }) ``` ### Configure the entry CSS with layers Create a new file `app/app.css` and add the following content: ```css filename="app/app.css" @layer reset, base, tokens, recipes, utilities; ``` ### Update the root component Import the `app.css` file in your `app/root.tsx` file and add the `styles` variable to the `links` function. Please note the `?url` query parameter in the `import` statement. This is required by Vite to generate the correct path to the CSS file. ```tsx {4,8} filename="app/root.tsx" import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router' import type { Route } from './+types/root' import stylesheet from './app.css?url' export const links: LinksFunction = () => [ // ... { rel: 'stylesheet', href: stylesheet }, ] export function Layout({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` ### Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `app/routes/home.tsx` file. ```tsx filename="app/routes/home.tsx" import type { Route } from './+types/home' import { css } from 'styled-system/css' export function meta({}: Route.MetaArgs) { return [{ title: 'New React Router App' }, { name: 'description', content: 'Welcome to React Router!' }] } export default function Home() { return (

Welcome to the home page

) } ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["app", "styled-system"] } ``` --- ## Using Redwood Easily use Bamboo with Redwood.js with our dedicated integration. This guide shows you how to set up Bamboo CSS in a Redwood project using PostCSS. > Redwood uses `yarn` as its primary package manager. ## Start a new project ### Create Redwood project To get started, we will need to create a new Redwood project using `typescript` template. ```bash yarn create redwood-app app ``` Respond to the prompts as follows: ```bash ✔ Compatibility checks passed ✔ Select your preferred language · TypeScript ✔ Do you want to initialize a git repo? · no / Yes ✔ Enter a commit message · Initial commit ✔ Do you want to run yarn install? · no / Yes ✔ Project files created ✔ Initialized a git repo with commit message "Initial commit" ✔ Installed node modules ✔ Generated types ``` ### Install Bamboo Install bamboo and generate the `bamboo.config.ts` and `postcss.config.js` file. ```bash cd web yarn add -D @bamboocss/dev postcss postcss-loader yarn bamboo init --postcss ``` ### Move to config folder Redwood uses a `config` folder for all of the configuration files. Move the `bamboo.config.ts` and `postcss.config.js` files to the `config` folder. ```bash mv bamboo.config.ts postcss.config.js config/ ``` ### Update configs Update the postcss config file to use the `bamboo.config.ts` file. ```diff filename="web/config/postcss.config.js" + const path = require('path') module.exports = { plugins: { "@bamboocss/dev/postcss": { + configPath: path.resolve(__dirname, 'bamboo.config.ts'), }, }, } ``` Update the tsconfig file to include the `styled-system` folder. ```json {6} filename="web/tsconfig.json" { // ... "compilerOptions": { "paths": { // ... "styled-system/*": ["./styled-system/*"] } } } ``` ### Update package.json scripts Open the `web/package.json` file and update the `scripts` section as follows: ```diff {3} filename="web/package.json" { "scripts": { + "prepare": "bamboo codegen" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Redwood components are included in the `include` section of the `bamboo.config.ts` file. ```js {5} filename="web/config/bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, include: ['./src/**/*.{js,jsx,ts,tsx}'], exclude: [], outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/style/index.css` file imported in the root component of your project. ```css filename="web/src/index.css" @layer reset, base, tokens, recipes, utilities; ``` ## Start your build process Run the following command to start your development server. ```bash yarn rw dev ``` ### Start using Bamboo Now you can start using Bamboo CSS in your project. ```tsx filename="web/src/pages/HomePage/HomePage.tsx" import { css } from 'styled-system/css' import { stack } from 'styled-system/patterns' import { Link, routes } from '@redwoodjs/router' import { MetaTags } from '@redwoodjs/web' const HomePage = () => { return ( <>

HomePage

Hello World

) } export default HomePage ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="web/tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Remix How to use Bamboo with Remix with our dedicated integration. This guide will show you how to set up Bamboo CSS in a Remix project using PostCSS. ## Start a new project ### Create Remix project To get started, we will need to create a new Remix project using the official [Create Remix](https://remix.run/docs/en/main/start/quickstart) CLI. In this guide, we will use TypeScript. If you don't enter any parameter, the CLI will guide you through the process of creating a new Remix app. {/* */} ```bash pnpm dlx create-remix@latest ``` ```bash npx create-remix@latest ``` ```bash yarn dlx create-remix@latest ``` ```bash bunx create-remix@latest ``` {/* */} You will be asked a few questions, answer these as follows: ```sh ? Where should we create your new project? test-app ? Install dependencies? No ``` > **Note:** You should decline the dependency installation step as we will install dependencies together with Bamboo > CSS. ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "build": "remix build", "dev": "remix dev", "start": "remix-serve build", "typecheck": "tsc" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the Bamboo CSS output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Remix components are included in the `include` section of the `bamboo.config.ts` file. ```js {5, 11} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./app/routes/**/*.{ts,tsx,js,jsx}', './app/components/**/*.{ts,tsx,js,jsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Create a new file `app/index.css` and add the following content: ```css filename="app/index.css" @layer reset, base, tokens, recipes, utilities; ``` Import the `index.css` file in your `app/root.tsx` file and add the `styles` variable to the `links` function. Please note the `?url` query parameter in the `import` statement. This is required by Vite to generate the correct path to the CSS file. ```tsx filename="app/root.tsx" {4,6} import type { LinksFunction } from '@remix-run/node' import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react' import styles from './index.css?url' export const links: LinksFunction = () => [{ rel: 'stylesheet', href: styles }] export default function App() { return ( ) } ``` ### Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `app/routes/_index.tsx` file. ```tsx filename="app/routes/_index.tsx" import type { MetaFunction } from '@remix-run/node' import { css } from 'styled-system/css' export const meta: MetaFunction = () => { return [{ title: 'New Remix App' }, { name: 'description', content: 'Welcome to Remix!' }] } export default function Index() { return
Hello 🎋!
} ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` If your app doesn't reload when making changes to the `bamboo.config.ts` file, consider adding `watchPaths` in your remix config file. ```js filename="remix.config.js" export default { // ... watchPaths: ['bamboo.config.ts'], } ``` --- ## Using Rsbuild Easily use Bamboo with Rsbuild, React and Typescript with our dedicated integration. This guide shows you how to set up Bamboo CSS in a Rsbuild project using PostCSS. ## Start a new project ### Create Rsbuild project To get started, we will need to create a new Rsbuild project using `react-ts` template. {/* */} ```bash pnpm create rsbuild@latest --dir test-app --template react-ts cd test-app pnpm install ``` ```bash npm create rsbuild@latest --dir test-app -- --template react-ts cd test-app npm install ``` ```bash yarn create rsbuild@latest --dir test-app --template react-ts cd test-app yarn ``` ```bash bun create rsbuild@latest --dir test-app --template react-ts cd test-app bun install ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {5} filename="package.json" { "scripts": { "build": "rsbuild build", "dev": "rsbuild dev --open", + "prepare": "bamboo codegen", "preview": "rsbuild preview" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your React components are included in the `include` section of the `bamboo.config.ts` file. ```js {8} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}', './pages/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // Generates JSX utilities with options of React, Preact, Qwik, Solid, Vue jsxFramework: 'react', // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/App.css` file imported in the root component of your project. ```css filename="src/App.css" @layer reset, base, tokens, recipes, utilities; ``` ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/App.tsx` file. ```tsx filename="src/App.tsx" import { css } from '../styled-system/css' function App() { return
Hello 🎋!
} export default App ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using SolidJS Easily use Bamboo with SolidJS with our dedicated integration. This guide will show you how to set up Bamboo CSS in a Solid.js project using PostCSS. ## Start a new project ### Create Vite project To get started, we will need to create a new SolidJS project using `solidjs/templates/ts` template. {/* */} ```bash pnpm dlx degit solidjs/templates/ts test-app cd test-app pnpm install ``` ```bash npx degit solidjs/templates/ts test-app cd test-app npm install ``` ```bash yarn dlx degit solidjs/templates/ts test-app cd test-app yarn ``` ```bash bunx degit solidjs/templates/ts test-app cd test-app bun install ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "dev": "vite", "build": "tsc && vite build", "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your SolidJS components are included in the `include` section of the `bamboo.config.ts` file. ```ts {8,17} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}', './pages/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/index.css` file imported in the root component of your project. ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` > **Note:** Feel free to remove `src/App.module.css` file as we don't need it anymore, and make sure to remove the > import from the `src/App.tsx` file. ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/App.tsx` file. ```tsx filename="src/App.tsx" import type { Component } from 'solid-js' import { css } from '../styled-system/css' const App: Component = () => { return
Hello 🎋!
} export default App ```
## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Storybook Easily use Bamboo with Storybook with our dedicated integration. Learn how to set up Bamboo CSS in a Storybook project using PostCSS. ## Setup We are assuming that you already have a project set up with a framework like React, Vue or Svelte. ### Install Storybook Storybook needs to be installed into a project that is already set up with a framework. It will not work on an empty project. {/* */} ```bash pnpm dlx storybook@latest init ``` ```bash npx storybook@latest init ``` ```bash yarn dlx storybook@latest init ``` ```bash bunx storybook@latest init ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} If you are using Storybook with the Vite builder, you will have to update your PostCSS config file to use the array syntax for the plugins instead of the object syntax. Simply change `postcss.config.[c]js`: ```diff filename="postcss.config.js" module.exports = { - plugins: { - '@bamboocss/dev/postcss': {} - } + plugins: [require('@bamboocss/dev/postcss')()] } ``` ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="web/package.json" { "scripts": { + "prepare": "bamboo codegen" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Storybook components are included in the `include` section of the `bamboo.config.ts` file. ```ts {7} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}', './pages/**/*.{js,jsx,ts,tsx}', './stories/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Locate your main CSS file and add the following layers: ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` ### Import the CSS in your Storybook config Locate your `.storybook/preview.ts` file and import the CSS file. In this example CSS file is located in the `src` folder. ```ts {1} filename=".storybook/preview.ts" import '../src/index.css' import type { Preview } from '@storybook/react' const preview: Preview = { parameters: { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }, } export default preview ``` ### Start the Storybook server Run the following command to start your Storybook server. {/* */} ```bash pnpm storybook ``` ```bash npm run storybook ``` ```bash yarn storybook ``` ```bash bun storybook ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in Storybook. Here is the example of a Button component and its corresponding Storybook story: ```tsx filename="src/stories/Button.tsx" import { ReactNode } from 'react' import { css } from '../../styled-system/css' export interface IButtonProps { children: ReactNode } export const Button = ({ children }: IButtonProps) => { return ( ) } ``` ```tsx filename="src/stories/Button.stories.tsx" import type { Meta, StoryObj } from '@storybook/react' import { css } from '../../styled-system/css' import { Button } from './Button' const meta = { title: 'Example/Button', component: Button, tags: ['autodocs'], decorators: [ (Story) => (
), ], } satisfies Meta export default meta type Story = StoryObj export const Default: Story = { args: { children: 'Hello 🎋!', }, } ```
## Configuring Dark Mode To enable dark mode in Storybook, you can use the `@storybook/addon-themes` package. ```bash pnpm add -D @storybook/addon-themes ``` Then, update your `.storybook/preview.ts` file to include the following: ```ts filename=".storybook/preview.ts" import { withThemeByClassName } from '@storybook/addon-themes' import type { Preview, ReactRenderer } from '@storybook/react' const preview: Preview = { // ... decorators: [ withThemeByClassName({ themes: { light: '', dark: 'dark', }, defaultTheme: 'light', }), ], } export default preview ``` With that in place, you should see the light/dark switcher in Storybook's toolbar. ## Troubleshooting ### Cannot find postcss plugin If you are having issues with the PostCSS plugin similar to `Cannot find module '@bamboocss/dev/postcss'`, update the PostCSS config as follows: ```js filename="postcss.config.js" module.exports = { plugins: [require('@bamboocss/dev/postcss')], } ``` ### HMR not triggered If you are having issues with HMR not being triggered after a `bamboo.config.ts` change (or one of its [dependencies](/docs/references/config#dependencies), you can manually specify the files that should trigger a rebuild by adding the following to your `bamboo.config.ts`: ```js filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... dependencies: ['path/to/files/**.ts'], }) ``` ### Styles in `args` is not generated If you are having issues with your `args` not generating the expected CSS, it's probably because of: - you didn't add a file glob for the Storybook files in your [`config.include`](/docs/references/config#include) like `"./stories/**/*.{js,jsx,ts,tsx}"` - you didn't wrap your `args` object (or some part of it) with the [`.raw()` marker that helps Bamboo find style usage](https://bamboocss.com/docs/guides/dynamic-styling#alternative) ```tsx filename="stories/Button.stories.tsx" import type { Meta, StoryObj } from '@storybook/react' import { button } from '../../styled-system/recipes' export const Funky: Story = { // mark this as a button recipe usage args: button.raw({ visual: 'funky', shape: 'circle', size: 'sm', }), } ``` ### Some recipes styles are missing If you are having issues with your config `recipes` or `slotRecipes` not generating the expected CSS, it's probably because of: - you didn't add a file glob for the Storybook files in your [`config.include`](/docs/references/config#include) like `"./stories/**/*.{js,jsx,ts,tsx}"` - you haven't used every recipes variants in your app, so you might want to pre-generate it (only for storybook usage) with [`staticCss`](/docs/guides/static) ```tsx filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... staticCss: { recipes: '*', }, }) ``` --- ## Using Svelte Easily use Bamboo with Svelte with our dedicated integration. This guide will show you how to set up Bamboo CSS in a Svelte project using PostCSS. ## Start a new project ### Create Svelte project To get started, we will need to create a new Svelte project. {/* */} ```bash pnpm create svelte@latest test-app ``` ```bash npm create svelte@latest test-app ``` ```bash yarn create svelte@latest test-app ``` ```bash bun create svelte@latest test-app ``` {/* */} You will be asked a few questions, answer them as follows: ```sh ┌ Welcome to SvelteKit! │ ◇ Which Svelte app template? │ Skeleton project │ ◇ Add type checking with TypeScript? │ Yes, using TypeScript syntax │ ◇ Select additional options (use arrow keys/space bar) │ ◼ Add ESLint for code linting │ ◼ Add Prettier for code formatting │ ◻ Add Playwright for browser testing │ ◻ Add Vitest for unit testing │ └ Your project is ready! ``` Enter the newly created directory and install the dependencies. {/* */} ```bash cd test-app pnpm install ``` ```bash cd test-app npm install ``` ```bash cd test-app yarn ``` ```bash cd test-app bun install ``` {/* */} ### Install Bamboo To install Bamboo and corresponding dependencies run the following commands: {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```json {3} { "scripts": { "prepare": "bamboo codegen", "dev": "vite dev", "build": "vite build", "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --plugin-search-dir . --check . && eslint .", "format": "prettier --plugin-search-dir . --write ." } } ``` This `"prepare"` script will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Svelte components are included in the `include` section of the `bamboo.config.ts` file. ```js {8} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,ts,svelte}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Update Svelte config To configure Svelte preprocess to use PostCSS and add Bamboo alias update the `svelte.config.js` file as follows: ```js {15} filename="svelte.config.js" import adapter from '@sveltejs/adapter-auto' import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' /** @type {import('@sveltejs/kit').Config} */ const config = { // Consult https://kit.svelte.dev/docs/integrations#preprocessors // for more information about preprocessors preprocess: [vitePreprocess()], kit: { // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // If your environment is not supported or you settled on a specific environment, switch out the adapter. // See https://kit.svelte.dev/docs/adapters for more information about adapters. adapter: adapter(), alias: { 'styled-system': './styled-system/*', }, }, } export default config ``` ### Update Vite config To be able to import `styled-system` files in your Svelte components you will need to update the `vite.config.js` file as follows: ```js {6-10} filename="vite.config.js" import { sveltekit } from '@sveltejs/kit/vite' import { defineConfig } from 'vite' export default defineConfig({ plugins: [sveltekit()], server: { fs: { allow: ['styled-system'], }, }, }) ``` If you’re using Storybook for a SvelteKit project, you need to replicate the same Vite server config changes. In your .storybook folder, you likely have a `main.js` (or `vite.config.js` in older Storybook versions). Update it as follows: ```js filename="main.js" import { defineConfig, mergeConfig } from 'vite' /** @type { import('@storybook/sveltekit').StorybookConfig } */ const config = { // other Storybook config... viteFinal: async (config) => { return mergeConfig( config, defineConfig({ server: { fs: { allow: ['styled-system'], }, }, }), ) }, } export default config ``` ### Configure the entry CSS with layers Create the `app.css` file in the `src` directory and add the following content: ```css filename="src/app.css" @layer reset, base, tokens, recipes, utilities; ``` ### Import styles in the layout file Create the `src/routes/+layout.svelte` file and add the following content: ```svelte {2} filename="src/routes/+layout.svelte" ``` ### Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/routes/+page.svelte` file. ```svelte filename="src/routes/+page.svelte"
Hello 🎋!
```
## Troubleshooting ### Autocomplete not working If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your TypeScript config. However, in Svelte your main `tsconfig.json` file is extending the autogenerated one. To extend it without overriding the defaults adjust your `svelte.config.js` to include following entry: ```js filename="svelte.config.js" import adapter from '@sveltejs/adapter-auto' import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' /** @type {import('@sveltejs/kit').Config} */ const config = { // ... kit: { // ... typescript: { config: (config) => { config.include.push('../styled-system') return config }, }, }, } export default config ``` --- ## Using Vite Easily use Bamboo with Vite, React and Typescript with our dedicated integration. This guide will show you how to set up Bamboo CSS in a Vite project using PostCSS. ## Start a new project ### Create Vite project To get started, we will need to create a new Vite project using `react-ts` template. {/* */} ```bash pnpm create vite test-app --template react-ts cd test-app pnpm install ``` ```bash npm create vite@latest test-app -- --template react-ts cd test-app npm install ``` ```bash yarn create vite test-app --template react-ts cd test-app yarn ``` ```bash bun create vite test-app --template react-ts cd test-app bun install ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "dev": "vite", "build": "tsc && vite build", "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your React components are included in the `include` section of the `bamboo.config.ts` file. ```js {8} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx}', './pages/**/*.{js,jsx,ts,tsx}'], // Files to exclude exclude: [], // Generates JSX utilities with options of React, Preact, Qwik, Solid, Vue jsxFramework: 'react', // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/index.css` file imported in the root component of your project. ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` > **Note:** Feel free to remove `src/App.css` file as we don't need it anymore, and make sure to remove the import from > the `src/App.tsx` file. ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/App.tsx` file. ```tsx filename="src/App.tsx" import { css } from '../styled-system/css' function App() { return
Hello 🎋!
} export default App ```
## Optional: fold static styles at build time The setup above resolves styles at runtime — `css({ color: 'red.300' })` runs on every render and returns a class string. The result is cached, but for a call whose arguments never change that work buys nothing. `@bamboocss/vite` removes it. During a production build it rewrites statically-resolvable calls into the string they would have returned: ```tsx // you write export const title = css({ fontSize: 'lg', fontWeight: 'bold' }) // the bundle gets export const title = 'fs_lg fw_bold' ``` ```bash pnpm add -D @bamboocss/vite ``` ```ts filename="vite.config.ts" import { defineConfig } from 'vite' import bamboocss from '@bamboocss/vite' export default defineConfig({ plugins: [bamboocss({ transform: true })], }) ``` This does not replace the PostCSS setup above. The plugin emits no CSS — PostCSS stays responsible for the stylesheet, and the CSS output is identical either way. Only the JavaScript changes. The fold is also **off by default**; you have to pass `transform: true`. Calls that cannot be resolved at build time are left alone and keep working as they do today, so this is safe to add to an existing project. See [Source Transformation](/docs/guides/source-transformation) for exactly what folds, what does not, and why. ## Troubleshooting If you're not getting import autocomplete in your IDE, you may need to include the `styled-system` directory in your `tsconfig.json` file: ```json filename="tsconfig.json" { // ... "include": ["src", "styled-system"] } ``` --- ## Using Vue Easily use Bamboo with Vue with our dedicated integration. Learn how to set up Bamboo CSS in a Vue project using PostCSS. ## Start a new project ### Create Vite project To get started, we will need to create a new Vue project using the official [scaffolding tool](https://github.com/vuejs/create-vue). If you don't enter any parameter, the CLI will guide you through the process of creating a new Vue app. {/* */} ```bash pnpm create vue@latest ``` ```bash npm create vue@latest ``` ```bash yarn create vue@latest ``` ```bash bun create vue@latest ``` {/* */} You will be asked a few questions, answer them as follows: ```bash Vue.js - The Progressive JavaScript Framework ✔ Project name: … test-app ✔ Add TypeScript? … Yes ✔ Add JSX Support? … Yes ✔ Add Vue Router for Single Page Application development? … No / Yes ✔ Add Pinia for state management? … No / Yes ✔ Add Vitest for Unit Testing? … No / Yes ✔ Add an End-to-End Testing Solution? › No ✔ Add ESLint for code quality? … No / Yes ✔ Add Prettier for code formatting? … No / Yes ``` Enter the newly created directory and install the dependencies. {/* */} ```bash cd test-app pnpm install ``` ```bash cd test-app npm install ``` ```bash cd test-app yarn ``` ```bash cd test-app bun install ``` {/* */} ### Install Bamboo Install bamboo and create your `bamboo.config.ts` file. {/* */} ```bash pnpm install -D @bamboocss/dev pnpm bamboo init --postcss ``` ```bash npm install -D @bamboocss/dev npx bamboo init --postcss ``` ```bash yarn add -D @bamboocss/dev yarn bamboo init --postcss ``` ```bash bun add -D @bamboocss/dev bun bamboo init --postcss ``` {/* */} ### Update package.json scripts Open your `package.json` file and update the `scripts` section as follows: ```diff {3} filename="package.json" { "scripts": { + "prepare": "bamboo codegen", "dev": "vite", "build": "run-p type-check build-only", "preview": "vite preview", "build-only": "vite build" } } ``` - `"prepare"` - script that will run Bamboo CSS CLI codegen before each build. Read more about [codegen](/docs/references/cli#bamboo-codegen) in the CLI section. > This step ensures that the bamboo output directory is regenerated after each dependency installation. So you can add > the output directory to your `.gitignore` file and not worry about it. ### Configure the content Make sure that all of the paths of your Vue components are included in the `include` section of the `bamboo.config.ts` file. ```js {8, 17} filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // Whether to use css reset preflight: true, // Where to look for your css declarations include: ['./src/**/*.{js,jsx,ts,tsx,vue}'], // Files to exclude exclude: [], // The output directory for your css system outdir: 'styled-system', }) ``` ### Configure the entry CSS with layers Add this code to an `src/index.css` file and import it in the root component of your project. ```css filename="src/index.css" @layer reset, base, tokens, recipes, utilities; ``` ## Start your build process Run the following command to start your development server. {/* */} ```bash pnpm dev ``` ```bash npm run dev ``` ```bash yarn dev ``` ```bash bun dev ``` {/* */} ### Start using Bamboo Now you can start using Bamboo CSS in your project. Here is the snippet of code that you can use in your `src/App.vue` file. ```vue-html filename="src/App.vue" ``` --- # Concepts ## Cascade Layers CSS cascade layers refer to the order in which CSS rules are applied to an HTML element. When multiple CSS rules apply to the same element, the browser uses the cascade to determine which rule should take precedence. See the [MDN article](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) to learn more. Bamboo takes advantage of the cascade to provide a more efficient and flexible way to organize styles. This allows you to define styles in a modular way, using CSS rules that are scoped to specific components or elements. ## Layer Types Bamboo supports five types of cascade layers out of the box: - `@layer reset` - The reset layer is used to reset the default styles of HTML elements. This is used when `preflight: true` is set in the config. You can also use this layer to add your own reset styles. The generated CSS for the reset layer looks like this: ```css @layer reset { * { box-sizing: border-box; margin: 0; padding: 0; } /* ... */ } ``` - `@layer base` - The base layer contains global styles defined in the `globalStyles` key in the config. You can also use this layer to add your own global styles. The generated CSS for the base layer looks like this: ```css @layer base { a { color: #000; text-decoration: none; } /* ... */ } ``` - `@layer recipes` - The recipes layer contains styles for recipes created within the config (aka config recipes). You can also use this layer to add your own component styles. The generated CSS for the recipes layer looks like this: ```css @layer recipes { .button { /* ... */ } .button--variant-primary { /* ... */ } /* ... */ } ``` - `@layer tokens` - The tokens layer contains css variables for tokens and semantic tokens. You can also use this layer to add your own design tokens. The generated CSS for the tokens layer looks like this: ```css @layer tokens { :root { --color-primary: #000; --color-secondary: #fff; --color-tertiary: #ccc; --shadow-sm: 0 0 0 1px rgba(0, 0, 0, 0.05); } /* ... */ } ``` - `@layer utilities` - Styles that are scoped to a specific utility class. These styles are only applied to elements that have the utility class applied. ## Layer Order The cascade layers are applied in the following order: - `@layer utilities` (Highest priority) - `@layer recipes` - `@layer tokens` - `@layer base` - `@layer reset` (Lowest priority) This means that styles defined in the `@layer utilities` will take precedence over styles defined in the `@layer recipes`. This is useful when you want to override the default styles of a component. ## Layer CSS The generated CSS in Bamboo is organized into layers. This allows you to define styles in a modular way, using CSS rules that are scoped to specific components or elements. Here's what the first line of the generated CSS looks like: ```css @layer reset, base, tokens, recipes, utilities; ``` Adding this line to the top of your CSS file will determine the order in which the layers are applied. This is the most exciting feature of CSS cascade layers. ## Customize layers Bamboo lets you customize the cascade layers, so your project can coexist with other solutions. Learn more about customizing layers [here](/docs/references/config#layers). ## Polyfills In event that you need to support older browsers, you can use the following postcss plugin in your PostCSS config: - [postcss-cascade-layers](https://www.npmjs.com/package/@csstools/postcss-cascade-layers): Adds support for CSS Cascade Layers. Here is an example of a `postcss.config.js` file that uses these polyfills: ```js module.exports = { plugins: ['@bamboocss/dev/postcss', '@csstools/postcss-cascade-layers'], } ``` Since CSS `@layer`s have a lower priority than other CSS rules, this postcss plugin is also useful in cases where your styles are being overridden by some other stylesheets that you're not in total control of, since it will remove the `@layer` rules and still emulate their specificity. --- ## Color opacity modifier How to dynamically set the opacity of a raw color or color token Every utilities connected to the `colors` tokens in the `@bamboocss/preset-base` (included by default) can use the [`color-mix`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix) CSS function. This means for example: `background`, `backgroundColor`, `color`, `border`, `borderColor`, etc. This function allows you to mix two colors together, and we use it to change the opacity of a color using the `{color}/{opacity}` syntax. You can use it like this: ```ts css({ bg: 'red.300/40', color: 'white', }) ``` This will generate: ```css @layer utilities { .bg_red\.300\/40 { --mix-background: color-mix(in srgb, var(--colors-red-300) 40%, transparent); background: var(--mix-background, var(--colors-red-300)); } .text_white { color: var(--colors-white); } } ``` - If you're not using any opacity, the utility will **not** use `color-mix` - The utility will automatically fallback to the original color if the `color-mix` function is not supported by the browser. - You can use any of the color tokens, and any of the opacity tokens. --- The `utilities` transform function also receives a `utils` object that contains the `colorMix` function, so you can also use it on your own utilities: ```ts export default defineConfig({ utilities: { background: { shorthand: 'bg', className: 'bg', values: 'colors', transform(value, args) { const mix = args.utils.colorMix(value) // This can happen if the value format is invalid (e.g. `bg: red.300/invalid` or `bg: red.300//10`) if (mix.invalid) return { background: value } return { background: mix.value, } }, }, }, }) ``` --- Here's a cool snippet (that we use internally !) that makes it easier to create a utility transform for a given property: ```ts import type { PropertyTransform } from '@bamboocss/types' export const createColorMixTransform = (prop: string): PropertyTransform => (value, args) => { const mix = args.utils.colorMix(value) if (mix.invalid) return { [prop]: value } const cssVar = '--mix-' + prop return { [cssVar]: mix.value, [prop]: `var(${cssVar}, ${mix.color})`, } } ``` then the same utility transform as above can be written like this: ```ts export default defineConfig({ utilities: { background: { shorthand: "bg", className: "bg", values: "colors", transform: createColorMixTransform("background"), }, }); ``` --- ## Conditional Styles Learn how to use conditional and responsive styles in Bamboo. When writing styles, you might need to apply specific changes depending on a specific condition, whether it's based on breakpoint, css pseudo state, media query or custom data attributes. Bamboo allows you to write conditional styles, and provides common condition shortcuts to make your life easier. Let's say you want to change the background color of a button when it's hovered. You can do it like this: ```jsx ``` ## Overview ### Property based condition This works great, but might be a bit verbose. You can apply the condition `_hover` directly to the `bg` property, leading to a more concise syntax: ```diff ``` > Note: The `base` key is used to define the default value of the property, without any condition. ### Nested condition Conditions in Bamboo can be nested, which means you can apply multiple conditions to a single property or another condition. Let's say you want to change the background color of a button when it's focused and hovered. You can do it like this: ```jsx ``` ### Built-in conditions Bamboo includes a set of common pseudo states that you can use to style your components: - Pseudo Class: `_hover`, `_active`, `_focus`, `_focusVisible`, `_focusWithin`, `_disabled` - Pseudo Element: `_before`, `_after` - Media Query: `sm`, `md`, `lg`, `xl`, `2xl` - Data Attribute Selector: `_horizontal`, `_vertical`, `_portrait`, `_landscape` ## Arbitrary selectors What if you need a one-off selector that is not defined in your config's conditions? You can use the `css` function to generate classes for arbitrary selectors: ```tsx import { css } from '../styled-system/css' const App = () => { return (
*': { margin: '2' }, })} /> ) } ``` This also works with the supported at-rules (`@media`, `@layer`, `@container`, `@supports`, and `@page`): ```tsx import { css } from '../styled-system/css' const App = () => { return (
) } ``` ## Pseudo Classes ### Hover, Active, Focus, and Disabled You can style the hover, active, focus, and disabled states of an element using their `_` modifier: ```jsx ``` ### First, Last, Odd, Even You can style the first, last, odd, and even elements of a group using their `_` modifier: ```jsx
    {items.map((item) => (
  • {item}
  • ))}
``` You can also style even and odd elements using the `_even` and `_odd` modifier: ```jsx {items.map((item) => ( ))}
{item}
``` ## Pseudo Elements ### Before and After You can style the `::before` and `::after` pseudo elements of an element using their `_before` and `_after` modifier: ```jsx
Hello
``` #### Notes - **Before and After**: Ensure you wrap the content value in double quotes. - **Mixing with Conditions**: When using condition and pseudo elements, prefer to place the condition **before** the pseudo element. ```jsx css({ // This works ✅ _dark: { _backdrop: { color: 'red' } } // This doesn't work ❌ _backdrop: { _dark: { color: 'red' } } }) ``` The reason `_backdrop: { _dark: { color: 'red' } }` doesn't work is because it generated an invalid CSS structure that looks like: ```css &::backdrop { &.dark, .dark & { color: red; } } ``` ### Placeholder Style the placeholder text of any input or textarea using the `_placeholder` modifier: ```jsx ``` ### File Inputs Style the file input button using the `_file` modifier: ```jsx ``` ## Media Queries ### Reduced Motion Use the `_motionReduce` and `_motionSafe` modifiers to style an element based on the user's motion preference: ```jsx
Hello
``` ### Color Scheme The `prefers-color-scheme` media feature is used to detect if the user has requested the system use a light or dark color theme. Use the `_osLight` and `_osDark` modifiers to style an element based on the user's color scheme preference: ```jsx
Hello
``` Let's say your app is dark by default, but you want to allow users to switch to a light theme. You can do it like this: ```jsx
Hello
``` ### Color Contrast The `prefers-contrast` media feature is used to detect if the user has requested the system use a high or low contrast theme. Use the `_highContrast` and `_lessContrast` modifiers to style an element based on the user's color contrast preference: ```jsx
Hello
``` ### Orientation The `orientation` media feature is used to detect if the user has a device in portrait or landscape mode. Use the `_portrait` and `_landscape` modifiers to style an element based on the user's device orientation: ```jsx
Hello
``` ## Group Selectors When you need to style an element based on its parent element's state or attribute, you can add the `group` class to the parent element, and use any of the `_group*` modifiers on the child element. ```jsx

Hover me

``` This modifer for every pseudo class modifiers like `_groupHover`, `_groupActive`, `_groupFocus`, and `_groupDisabled`, etc. ## Sibling Selectors When you need to style an element based on its sibling element's state or attribute, you can add the `peer` class to the sibling element, and use any of the `_peer*` modifiers on the target element. ```jsx

Hover me

I'll change by bg

``` > Note: This only works for when the element marked with `peer` is a previous siblings, that is, it comes before the > element you want to start. ## Data Attribute ### LTR and RTL You can style an element based on the direction of the text using the `_ltr` and `_rtl` modifiers: ```jsx
Hello
``` For this to work, you need to set the `dir` attribute on the parent element. In most cases,you can set this on the `html` element. > **Note:** Consider using logical css properties like `marginInlineStart` and `marginInlineEnd` instead their physical > counterparts like `marginLeft` and `marginRight`. This will reduce the need to use the `_ltr` and `_rtl` modifiers. ### State You can style an element based on its `data-{state}` attribute using the corresponding `_{state}` modifier: ```jsx
Hello
``` This also works for common states like `data-active`, `data-disabled`, `data-focus`, `data-hover`, `data-invalid`, `data-required`, and `data-valid`. ```jsx
Hello
``` > Most of the `data-{state}` attributes typically mirror the corresponding browser pseudo class. For example, > `data-hover` is equivalent to `:hover`, `data-focus` is equivalent to `:focus`, and `data-active` is equivalent to > `:active`. ### Orientation You can style an element based on its `data-orientation` attribute using the `_horizontal` and `_vertical` modifiers: ```jsx
Hello
``` ## ARIA Attribute You can style an element based on its `aria-{state}=true` attribute using the corresponding `_{state}` modifier: ```jsx
Hello
``` > Most of the `aria-{state}` attributes typically mirror the support ARIA states in the browser pseudo class. For > example, `aria-checked=true` is styled with `_checked`, `aria-disabled=true` is styled with `_disabled`. ## Container queries You can define container names and sizes in your theme configuration and use them in your styles. ```ts export default defineConfig({ // ... theme: { extend: { containerNames: ['sidebar', 'content'], containerSizes: { xs: '40em', sm: '60em', md: '80em', }, }, }, }) ``` The default container sizes in the `@bamboocss/preset-bamboo` preset are shown below: ```ts export const containerSizes = { xs: '320px', sm: '384px', md: '448px', lg: '512px', xl: '576px', '2xl': '672px', '3xl': '768px', '4xl': '896px', '5xl': '1024px', '6xl': '1152px', '7xl': '1280px', '8xl': '1440px', } ``` Then use them in your styles by referencing using `@/` syntax: > The default container syntax is `@/`. ```ts import { css } from '/styled-system/css' function Demo() { return ( ) } ``` This will generate the following CSS: ```css .cq-type_inline-size { container-type: inline-size; } @container (min-width: 60em) { .\@\/sm:fs_md { container-type: inline-size; } } ``` You can also named container queries: ```ts import { cq } from 'styled-system/patterns' function Demo() { return ( ) } ``` ## Reference Here's a list of all the condition shortcuts you can use in Bamboo: | Condition name | Selector | | ---------------------- | ------------------------------------------------------------------------------------------------ | | \_hover | `&:is(:hover, [data-hover])` | | \_focus | `&:is(:focus, [data-focus])` | | \_focusWithin | `&:focus-within` | | \_focusVisible | `&:is(:focus-visible, [data-focus-visible])` | | \_disabled | `&:is(:disabled, [disabled], [data-disabled], [aria-disabled=true])` | | \_active | `&:is(:active, [data-active])` | | \_visited | `&:visited` | | \_target | `&:target` | | \_readOnly | `&:is(:read-only, [data-read-only], [aria-readonly=true])` | | \_readWrite | `&:read-write` | | \_empty | `&:is(:empty, [data-empty])` | | \_checked | `&:is(:checked, [data-checked], [aria-checked=true], [data-state="checked"])` | | \_enabled | `&:enabled` | | \_expanded | `&:is([aria-expanded=true], [data-expanded], [data-state="expanded"])` | | \_highlighted | `&[data-highlighted]` | | \_complete | `&[data-complete]` | | \_incomplete | `&[data-incomplete]` | | \_dragging | `&[data-dragging]` | | \_before | `&::before` | | \_after | `&::after` | | \_firstLetter | `&::first-letter` | | \_firstLine | `&::first-line` | | \_marker | `&::marker, &::-webkit-details-marker` | | \_selection | `&::selection` | | \_file | `&::file-selector-button` | | \_backdrop | `&::backdrop` | | \_first | `&:first-child` | | \_last | `&:last-child` | | \_only | `&:only-child` | | \_even | `&:nth-child(even)` | | \_odd | `&:nth-child(odd)` | | \_firstOfType | `&:first-of-type` | | \_lastOfType | `&:last-of-type` | | \_onlyOfType | `&:only-of-type` | | \_peerFocus | `.peer:is(:focus, [data-focus]) ~ &` | | \_peerHover | `.peer:is(:hover, [data-hover]) ~ &` | | \_peerActive | `.peer:is(:active, [data-active]) ~ &` | | \_peerFocusWithin | `.peer:focus-within ~ &` | | \_peerFocusVisible | `.peer:is(:focus-visible, [data-focus-visible]) ~ &` | | \_peerDisabled | `.peer:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) ~ &` | | \_peerChecked | `.peer:is(:checked, [data-checked], [aria-checked=true], [data-state="checked"]) ~ &` | | \_peerInvalid | `.peer:is(:invalid, [data-invalid], [aria-invalid=true]) ~ &` | | \_peerExpanded | `.peer:is([aria-expanded=true], [data-expanded], [data-state="expanded"]) ~ &` | | \_peerPlaceholderShown | `.peer:placeholder-shown ~ &` | | \_groupFocus | `.group:is(:focus, [data-focus]) &` | | \_groupHover | `.group:is(:hover, [data-hover]) &` | | \_groupActive | `.group:is(:active, [data-active]) &` | | \_groupFocusWithin | `.group:focus-within &` | | \_groupFocusVisible | `.group:is(:focus-visible, [data-focus-visible]) &` | | \_groupDisabled | `.group:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) &` | | \_groupChecked | `.group:is(:checked, [data-checked], [aria-checked=true], [data-state="checked"]) &` | | \_groupExpanded | `.group:is([aria-expanded=true], [data-expanded], [data-state="expanded"]) &` | | \_groupInvalid | `.group:is(:invalid, [data-invalid], [aria-invalid=true]) &` | | \_indeterminate | `&:is(:indeterminate, [data-indeterminate], [aria-checked=mixed], [data-state="indeterminate"])` | | \_required | `&:is(:required, [data-required], [aria-required=true])` | | \_valid | `&:is(:valid, [data-valid])` | | \_invalid | `&:is(:invalid, [data-invalid], [aria-invalid=true])` | | \_autofill | `&:autofill` | | \_inRange | `&:is(:in-range, [data-in-range])` | | \_outOfRange | `&:is(:out-of-range, [data-outside-range])` | | \_placeholder | `&::placeholder, &[data-placeholder]` | | \_placeholderShown | `&:is(:placeholder-shown, [data-placeholder-shown])` | | \_pressed | `&:is([aria-pressed=true], [data-pressed])` | | \_selected | `&:is([aria-selected=true], [data-selected])` | | \_grabbed | `&:is([aria-grabbed=true], [data-grabbed])` | | \_underValue | `&[data-state=under-value]` | | \_overValue | `&[data-state=over-value]` | | \_atValue | `&[data-state=at-value]` | | \_default | `&:default` | | \_optional | `&:optional` | | \_open | `&:is([open], [data-open], [data-state="open"], :popover-open)` | | \_closed | `&:is([closed], [data-closed], [data-state="closed"])` | | \_fullscreen | `&:is(:fullscreen, [data-fullscreen])` | | \_loading | `&:is([data-loading], [aria-busy=true])` | | \_hidden | `&:is([hidden], [data-hidden])` | | \_current | `&:is([aria-current=true], [data-current])` | | \_currentPage | `&[aria-current=page]` | | \_currentStep | `&[aria-current=step]` | | \_today | `&[data-today]` | | \_unavailable | `&[data-unavailable]` | | \_rangeStart | `&[data-range-start]` | | \_rangeEnd | `&[data-range-end]` | | \_now | `&[data-now]` | | \_topmost | `&[data-topmost]` | | \_motionReduce | `@media (prefers-reduced-motion: reduce)` | | \_motionSafe | `@media (prefers-reduced-motion: no-preference)` | | \_print | `@media print` | | \_landscape | `@media (orientation: landscape)` | | \_portrait | `@media (orientation: portrait)` | | \_dark | `.dark &` | | \_light | `.light &` | | \_osDark | `@media (prefers-color-scheme: dark)` | | \_osLight | `@media (prefers-color-scheme: light)` | | \_highContrast | `@media (forced-colors: active)` | | \_lessContrast | `@media (prefers-contrast: less)` | | \_moreContrast | `@media (prefers-contrast: more)` | | \_ltr | `:where([dir=ltr], :dir(ltr)) &` | | \_rtl | `:where([dir=rtl], :dir(rtl)) &` | | \_scrollbar | `&::-webkit-scrollbar` | | \_scrollbarThumb | `&::-webkit-scrollbar-thumb` | | \_scrollbarTrack | `&::-webkit-scrollbar-track` | | \_horizontal | `&[data-orientation=horizontal]` | | \_vertical | `&[data-orientation=vertical]` | | \_icon | `& :where(svg)` | | \_starting | `@starting-style` | | \_noscript | `@media (scripting: none)` | | \_invertedColors | `@media (inverted-colors: inverted)` | ## Custom conditions Bamboo lets you create your own conditions, so you're not limited to the ones in the default preset. Learn more about customizing conditions [here](/docs/customization/conditions). --- ## The extend keyword What is and how to to use the extend keyword The `extend` keyword allows you to extend the default Bamboo configuration. It is useful when you want to add your own customizations to Bamboo, without erasing the default `presets` values (`conditions`, `tokens`, `utilities`, etc). It will (deeply) merge your customizations with the default ones, instead of replacing them. The `extend` keyword allows you to extend the following parts of Bamboo: - [conditions](/docs/customization/conditions) - [theme](/docs/customization/theme) - [recipes](/docs/concepts/recipes) (included in theme) - [patterns](/docs/customization/patterns) - [utilities](/docs/customization/utilities) - [globalCss](/docs/concepts/writing-styles#global-styles) - [staticCss](/docs/guides/static) > These keys are all allowed in [presets](/docs/customization/presets). ## Example After running the `bamboo init` command you should see something similar to this: ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... // Useful for theme customization theme: { extend: {}, // 👈 it's already there! perfect, now you just need to add your customizations in this object }, // ... }) ``` Let's say you want to add a new color to the default theme. You can do it like this: ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ theme: { extend: { colors: { primary: { value: '#ff0000' }, }, }, }, }) ``` This will add a new color to the default theme, without erasing the other ones. Now, let's say we want to create new property `br` that applies a border radius to an element. ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ utilities: { extend: { br: { className: 'rounded', // css({ br: "sm" }) => rounded-sm values: 'radii', // connect values to the radii tokens transform(value) { return { borderRadius: value } }, }, }, }, }) ``` What if this utility was coming from a preset (`@acme/my-preset`) ? You can extend any specific part, as it will be deeply merged with the existing one: ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ presets: ['@acme/my-preset'] utilities: { extend: { br: { className: 'br' // css({ br: "sm" }) => br-sm } } } }) ``` ## Removing something from a preset Let's say you want to remove the `br` utility from the `@acme/my-preset` preset. You can do it like this: ```ts import { defineConfig } from '@bamboocss/dev' import myPreset from '@acme/my-preset' const { br, ...utilities } = myPreset.utilities export default defineConfig({ presets: ['@acme/my-preset'] utilities: { extend: { ...utilities, // 👈 we still want the other utilities from this preset // your customizations here } } }) ``` ## Removing something from the base presets Let's say you want to remove the `stack` pattern from the `@bamboocss/preset-base` preset (included by default). You can pick only the parts that you need with and spread the rest, like this: ```ts import bambooBasePreset from '@bamboocss/preset-base' // omitting stack here const { stack, ...bambooBasePresetPatterns } = bambooBasePreset.patterns export default defineConfig({ presets: ['@bamboocss/preset-bamboo'], // 👈 we still want the tokens, breakpoints and textStyles from this preset // ⚠️ we need to eject to prevent the `@bamboocss/preset-base` from being resolved // https://bamboocss.com/docs/customization/presets#which-bamboo-presets-will-be-included- eject: true, patterns: { extend: { ...bambooBasePresetPatterns, // your customizations here }, }, }) ``` ## Minimal setup If you want to use Bamboo with the bare minimum, without any of the defaults, you can read more about it [here](/docs/guides/minimal-setup) ## FAQ ### Why is my preset overriding the base one, even after adding it to the array? You might have forgotten to include the `extend` keyword in your config. Without `extend`, your preset will completely replace the base one, instead of merging with it. --- ## Global Styles How to work with resets, global styles, and global CSS variables in Bamboo. Bamboo groups global styles into reset and base layers so you can control defaults predictably and override them safely. ## Layers overview - **@layer reset**: Preflight/reset styles, enabled with `preflight`. - **@layer base**: Your additional global styles via `globalCss`. > See also: [Cascade layers](/docs/concepts/cascade-layers) ## Reset (preflight) Enable or scope the reset styles. ```ts filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: true, }) ``` Scope and level: ```ts filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ preflight: { scope: '.extension', level: 'element' }, }) ``` ## Exposed global CSS variables These variables are used by the reset and defaults. Set them in `globalCss`: - `--global-font-body` - `--global-font-mono` - `--global-color-border` - `--global-color-placeholder` - `--global-color-selection` - `--global-color-focus-ring` ## Setting global styles (base) Use `globalCss` to define additional global styles and set variables. ```ts filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... globalCss: { html: { '--global-font-body': 'Inter, sans-serif', '--global-font-mono': 'Mononoki Nerd Font, monospace', '--global-color-border': 'colors.gray.400', '--global-color-placeholder': 'rgba(0,0,0,0.5)', '--global-color-selection': 'rgba(0,115,255,0.3)', '--global-color-focus-ring': 'colors.blue.400', }, }, }) ``` ### Theming patterns You can set variables on `:root`, a `.dark` class, or via media queries. ```css :root { --global-color-border: oklch(0.8 0 0); } .dark { --global-color-border: oklch(0.72 0 0); } @media (prefers-color-scheme: dark) { :root { --global-color-border: oklch(0.72 0 0); } } ``` ## Custom global variables (`globalVars`) Define additional global CSS variables or `@property` entries. ```ts filename="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' export default defineConfig({ globalVars: { '--button-color': { syntax: '', inherits: false, initialValue: 'blue', }, }, }) ``` > Keys from `globalVars` are suggestable in style objects and generated near your tokens at `cssVarRoot`. ## Troubleshooting - **Global styles aren't applied:** Confirm `preflight` is enabled (if you expect reset), and ensure your selector (`html`, `:root`, `.dark`, etc.) matches the element where variables are set. - **Global styles are overridden by utilities or component styles:** Verify layer order and specificity. Ensure `@layer reset` and `@layer base` are emitted before utilities. If you customize insertion or injection order (SSR, framework plugins), preserve `@layer` order so globals are not overridden. --- ## Bamboo Integration Hooks Leveraging hooks in Bamboo to create custom functionality. Bamboo hooks can be used to add new functionality or modify existing behavior during certian parts of the compiler lifecycle. Hooks are mostly callbacks that can be added to the bamboo config via the `hooks` property, or installed via `plugins`. Here are some examples of what you can do with hooks: - modify the resolved config (`config:resolved`), like strip out tokens or keyframes. - modify presets after they are resolved (`preset:resolved`), like removing specific tokens or theme properties from a preset. - tweak the design token or classname engine (`tokens:created`, `utility:created`), like prefixing token names, or customizing the hashing function - transform a source file to a `tsx` friendly syntax before it's parsed (`parser:before`) so that Bamboo can automatically extract its styles usage - create your own styles parser (`parser:before`, `parser:after`) using the file's content so that Bamboo could be used with any templating language - alter the generated JS and DTS code (`codegen:prepare`) - modify the generated CSS (`cssgen:done`), allowing all kinds of customizations like removing the unused CSS variables, etc. - restrict `strictTokens` to a specific set of token categories, ex: only affect `colors` and `spacing` tokens and therefore allow any value for `fontSizes` and `lineHeights` ## Examples ### Prefixing token names This is especially useful when migrating from other css-in-js libraries, [like Stitches.](/docs/migration/stitches) ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... hooks: { 'tokens:created': ({ configure }) => { configure({ formatTokenName: (path) => '$' + path.join('-'), }) }, }, }) ``` ### Customizing the hash function When using the [`hash: true`](/docs/concepts/writing-styles) config property, you can customize the function used to hash the classnames. ```ts export default defineConfig({ // ... hash: true, hooks: { 'utility:created': ({ configure }) => { configure({ toHash: (paths, toHash) => { const stringConds = paths.join(':') const splitConds = stringConds.split('_') const hashConds = splitConds.map(toHash) return hashConds.join('_') }, }) }, }, }) ``` ### Modifying the config Here's an example of how to leveraging the provided `utils` functions in the `config:resolved` hook to remove the `stack` pattern from the resolved config. ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... hooks: { 'config:resolved': ({ config, utils }) => { return utils.omit(config, ['patterns.stack']) }, }, }) ``` ### Modifying presets You can use the `preset:resolved` hook to modify presets after they are resolved. This is useful for customizing or filtering out parts of a preset. ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... hooks: { 'preset:resolved': ({ utils, preset, name }) => { if (name === '@bamboocss/preset-bamboo') { return utils.omit(preset, ['theme.tokens.colors', 'theme.semanticTokens.colors']) } return preset }, }, }) ``` ### Configuring JSX extraction Use the `matchTag` / `matchTagProp` functions to customize the way Bamboo extracts your JSX. This can be especially useful when working with libraries that have properties that look like CSS properties but are not and should be ignored. Let's see a Radix UI example where the `Select.Content` component has a `position` property that should be ignored: ```js // Here, the `position` property will be extracted because `position` is a valid CSS property, but we don't want that ``` ```ts export default defineConfig({ // ... hooks: { 'parser:before': ({ configure }) => { configure({ // ignore the Select.Content entirely matchTag: (tag) => tag !== 'Select.Content', // ...or specifically ignore the `position` property matchTagProp: (tag, prop) => tag === 'Select.Content' && prop !== 'position', }) }, }, }) ``` ### Remove unused variables from final css Here's an example of how to transform the generated css in the `cssgen:done` hook. ```ts file="bamboo.config.ts" import { defineConfig } from '@bamboocss/dev' import { removeUnusedCssVars } from './remove-unused-css-vars' import { removeUnusedKeyframes } from './remove-unused-keyframes' export default defineConfig({ // ... hooks: { 'cssgen:done': ({ artifact, content }) => { if (artifact === 'styles.css') { return removeUnusedCssVars(removeUnusedKeyframes(content)) } }, }, }) ``` Get the snippets for the removal logic from our Github Sandbox in the [remove-unused-css-vars](https://github.com/bamboocss/bamboo/blob/main/sandbox/vite-ts/remove-unused-css-vars.ts) and [remove-unused-keyframes](https://github.com/bamboocss/bamboo/blob/main/sandbox/vite-ts/remove-unused-keyframes.ts) files. > Note: Using this means you can't use the JS function [`token.var`](/docs/guides/dynamic-styling#using-tokenvar) (or > [token(xxx)](/docs/guides/dynamic-styling#using-token) where `xxx` is the path to a > [semanticToken](/docs/theming/tokens#semantic-tokens)) from `styled-system/tokens` as the CSS variables will be > removed based on the usage found in the generated CSS ## Sharing hooks Hooks can be shared as a snippet or as a `plugin`. Plugins are currently simple objects that contain a `name` associated with a `hooks` object with the same structure as the `hooks` object in the config. > Plugins differ from `presets` as they can't be extended, but they will be called in sequence in the order they are > defined in the `plugins` array, with the user's config called last. ```ts import { defineConfig } from '@bamboocss/dev' export default defineConfig({ // ... plugins: [ { name: 'token-format', hooks: { 'tokens:created': ({ configure }) => { configure({ formatTokenName: (path) => '$' + path.join('-'), }) }, }, }, ], }) ``` ## Reference ```ts export interface BambooHooks { /** * Called when the config is resolved, after all the presets are loaded and merged. * This is the first hook called, you can use it to tweak the config before the context is created. */ 'config:resolved': (args: ConfigResolvedHookArgs) => MaybeAsyncReturn /** * Called when a preset is resolved, allowing you to modify it before it's merged into the config. */ 'preset:resolved': (args: PresetResolvedHookArgs) => MaybeAsyncReturn /** * Called when the token engine has been created */ 'tokens:created': (args: TokenCreatedHookArgs) => MaybeAsyncReturn /** * Called when the classname engine has been created */ 'utility:created': (args: UtilityCreatedHookArgs) => MaybeAsyncReturn /** * Called when the Bamboo context has been created and the API is ready to be used. */ 'context:created': (args: ContextCreatedHookArgs) => void /** * Called when the config file or one of its dependencies (imports) has changed. */ 'config:change': (args: ConfigChangeHookArgs) => MaybeAsyncReturn /** * Called after reading the file content but before parsing it. * You can use this hook to transform the file content to a tsx-friendly syntax so that Bamboo's parser can parse it. * You can also use this hook to parse the file's content on your side using a custom parser, in this case you don't have to return anything. */ 'parser:before': (args: ParserResultBeforeHookArgs) => string | void /** * Called after the file styles are extracted and processed into the resulting ParserResult object. * You can also use this hook to add your own extraction results from your custom parser to the ParserResult object. */ 'parser:after': (args: ParserResultAfterHookArgs) => void /** * Called right before writing the codegen files to disk. * You can use this hook to tweak the codegen files before they are written to disk. */ 'codegen:prepare': (args: CodegenPrepareHookArgs) => MaybeAsyncReturn /** * Called after the codegen is completed */ 'codegen:done': (args: CodegenDoneHookArgs) => MaybeAsyncReturn /** * Called right before adding the design-system CSS (global, static, preflight, tokens, keyframes) to the final CSS * Called right before writing/injecting the final CSS (styles.css) that contains the design-system CSS and the parser CSS * You can use it to tweak the CSS content before it's written to disk or injected through the postcss plugin. */ 'cssgen:done': (args: CssgenDoneHookArgs) => string | void } ``` --- ## JSX Style Context JSX Style Context provides an ergonomic way to style compound components with slot recipes. It uses a context-based approach to distribute recipe styles across multiple child components, making it easier to style headless UI libraries like Ark UI, and Radix UI. ## Atomic Slot Recipe - Create a slot recipe using the `sva` function - Pass the slot recipe to the `createStyleContext` function - Use the `withProvider` and `withContext` functions to create compound components ```tsx // components/ui/card.tsx import { sva } from 'styled-system/css' import { createStyleContext } from 'styled-system/jsx' const card = sva({ slots: ['root', 'label'], base: { root: {}, label: {}, }, variants: { size: { sm: { root: {} }, md: { root: {} }, }, }, defaultVariants: { size: 'sm', }, }) const { withProvider, withContext } = createStyleContext(card) const Root = withProvider('div', 'root') const Label = withContext('label', 'label') export const Card = { Root, Label, } ``` Then you can use the `Root` and `Label` components to create a card. ```tsx // app/page.tsx import { Card } from './components/ui/card' export default function App() { return ( Hello ) } ``` ## Config Slot Recipe The `createStyleContext` function can also be used with slot recipes defined in the `bamboo.config.ts` file. - Pass the config recipe to the `createStyleContext` function - Use the `withProvider` and `withContext` functions to create compound components ```tsx // components/ui/card.tsx import { card } from '../styled-system/recipes' import { createStyleContext } from 'styled-system/jsx' const { withProvider, withContext } = createStyleContext(card) const Root = withProvider('div', 'root') const Label = withContext('label', 'label') export const Card = { Root, Label, } ``` Then you can use the `Root` and `Label` components to create a card. ```tsx // app/page.tsx import { Card } from './components/ui/card' export default function App() { return ( Hello ) } ``` ## createStyleContext This function is a factory function that returns three functions: `withRootProvider`, `withProvider`, and `withContext`. ### withRootProvider Creates the root component that provides the style context. Use this when the root component **does not render an underlying DOM element**. ```tsx import { Dialog } from '@ark-ui/react' //... const DialogRoot = withRootProvider(Dialog.Root) ``` ### withProvider Creates a component that both provides context and applies the root slot styles. Use this when the root component **renders an underlying DOM element**. > **Note:** It requires the root `slot` parameter to be passed. ```tsx import { Avatar } from '@ark-ui/react' //... const AvatarRoot = withProvider(Avatar.Root, 'root') ``` ### withContext Creates a component that consumes the style context and applies slot styles. It does not accept variant props directly, but gets them from context. ```tsx import { Avatar } from '@ark-ui/react' //... const AvatarImage = withContext(Avatar.Image, 'image') const AvatarFallback = withContext(Avatar.Fallback, 'fallback') ``` ### unstyled prop Every component created with `createStyleContext` supports the `unstyled` prop to disable styling. It is useful when you want to opt-out of the recipe styles. - When applied the root component, will disable all styles - When applied to a child component, will disable the styles for that specific slot ```tsx // Removes all styles // Removes only the styles for the image slot ``` ## Guides ### Config Recipes The rules of config recipes still applies when using `createStyleContext`. Ensure the name of the final component matches the name of the recipe. > If you want to use a custom name, you can configure the recipe's `jsx` property in the `bamboo.config.ts` file. ```tsx // recipe name is "card" import { card } from '../styled-system/recipes' const { withRootProvider, withContext } = createStyleContext(card) const Root = withRootProvider('div') const Header = withContext('header', 'header') const Body = withContext('body', 'body') // The final component name must be "Card" export const Card = { Root, Header, Body, } ``` ### Default Props Use `defaultProps` option to provide default props to the component. ```tsx const { withContext } = createStyleContext(card) export const CardHeader = withContext('header', 'header', { defaultProps: { role: 'banner', }, }) ``` --- ## Merging Styles Learn how to merge multiple styles without conflicts. ## Merging `css` objects You can merge multiple style objects together using the `css` function. ```js import { css } from 'styled-system/css' const style1 = { bg: 'red', color: 'white', } const style2 = { bg: 'blue', } const className = css(style1, style2) // => 'bg_blue text_white' ``` In some cases though, the style object might not be colocated in the same file as the component. In this case, you can use the `css.raw` function to preserve the original style object. > All `.raw(...)` signatures are identity functions that return the same value as the input, but serve as a hint to the > compiler that the value is a style object. ```js // style.js import { css } from 'styled-system/css' export const style1 = css.raw({ bg: 'red', color: 'white', }) // component.js import { css } from 'styled-system/css' import { style1 } from './style.js' const style2 = css.raw({ bg: 'blue', }) const className = css(style1, style2) // => 'bg_blue text_white' ``` ## Spreading `css.raw` objects > **Added in v1.6.1** You can also spread `css.raw` objects within style declarations. This is particularly useful for reusing styles in nested selectors, conditions, and complex compositions: ### Child selectors ```js import { css } from 'styled-system/css' const baseStyles = css.raw({ margin: 0, padding: 0 }) const component = css({ '& p': { ...baseStyles, fontSize: '1rem' }, '& h1': { ...baseStyles, fontSize: '2rem' }, }) ``` ### Nested conditions ```js import { css } from 'styled-system/css' const interactive = css.raw({ cursor: 'pointer', transition: 'all 0.2s' }) const card = css({ _hover: { ...interactive, _dark: { ...interactive, color: 'white' }, }, }) ``` ## Merging `cva` + `css` styles The same technique can be used to merge an atomic `cva` recipe and a style object. ```js import { css, cx, cva } from 'styled-system/css' const overrideStyles = css.raw({ bg: 'red', color: 'white', }) const buttonStyles = cva({ base: { bg: 'blue', border: '1px solid black', }, variants: { size: { small: { fontSize: '12px' }, }, }, }) const className = css( // returns the resolved style object buttonStyles.raw({ size: 'small' }), // add the override styles overrideStyles, ) // => 'bg_red border_1px_solid_black color_white font-size_12px' ``` ## Merging `sva` + `css` styles The same technique can be used to merge an atomic `sva` recipe and a style object. ```js import { css, sva } from 'styled-system/css' const overrideStyles = css.raw({ bg: 'red', color: 'white' }) const buttonStyles = sva({ slots: ['root'] base: { root: { bg: 'blue', border: '1px solid black' } }, variants: { size: { root: { small: { fontSize: '12px' } } } } }) // returns the resolved style object for all slots const { root } = buttonStyles.raw({ size: 'small' }) const className = css( root, // add the override styles overrideStyles ) // => 'bg_red border_1px_solid_black color_white font-size_12px' ``` ## Merging config recipe and style object Due to the fact that the generated styles of a config recipe are saved in the `@layer recipe` cascade layer, they can be overridden with any atomic styles. Use the `cx` function to achieve that. > The `utilties` layer has more precedence than the `recipe` layer. ```js import { css, cx } from 'styled-system/css' import { button } from 'styled-system/recipes' const className = cx( // returns the resolved class name: `button button--size-small` button({ size: 'small' }), // add the override styles css({ bg: 'red' }), // => 'bg_red' ) // => 'button button--size-small bg_red' ``` ## Merging within JSX component Using these techniques, you can apply them to a component by exposing a `css` prop and merge with local styles. > **Note:** For this to work, Bamboo requires that you set `jsxFramework` config option to `react` ```jsx const cardStyles = css.raw({ bg: 'red', color: 'white', }) function Card({ title, description, css: cssProp }) { return ( // merge the `cardStyles` with the `cssProp` passed in

{title}

{description}

) } // usage function Demo() { return } ``` If you use any other prop name other than `css`, then you must use the `css.raw(...)` function to ensure Bamboo extracts the style object. ```jsx const cardStyles = css.raw({ bg: 'red', color: 'white', }) function Card({ title, description, style }) { return ( // merge the `cardStyles` with the `style` passed in

{title}

{description}

) } // usage function Demo() { return ( ) } ``` --- ## Patterns Patterns are layout primitives that can be used to create robust and responsive layouts with ease. Bamboo comes with predefined patterns like stack, hstack, vstack, wrap, etc. These patterns can be used as functions or JSX elements. Think of patterns as a set of predefined styles to reduce repetition and improve readability. You can override the properties as needed, just like in the `css` function. ## Creating Patterns To learn how to create patterns, check out the [customization](/docs/customization/patterns) section. ## Predefined Patterns ### Box The Box pattern does not contain any additional styles. With its function form it's the equivalent of the `css` function. It can be useful with its JSX form and is the equivalent of a `styled.div` component, serving mostly to get style props available in JSX. ```tsx import { Box } from '../styled-system/jsx' function App() { return (
Cool !
) } ``` ### Container The Container pattern is used to create a container with a max-width and center the content. By default, the container sets the following properties: - `maxWidth: 8xl` - `marginX: auto` - `position: relative` - `paddingX: { base: 4, md: 6, lg: 8 }` ```tsx import { container } from '../styled-system/patterns' function App() { return (
First
Second
Third
) } ```
```tsx import { Container } from '../styled-system/jsx' function App() { return (
First
Second
Third
) } ```
### Stack The Stack pattern is a layout primitive that can be used to create a vertical or horizontal stack of elements. The `stack` function accepts the following properties: - `direction`: An alias for the css `flex-direction` property. Default is `column`. - `gap`: The gap between the elements in the stack. - `align`: An alias for the css `align-items` property. - `justify`: An alias for the css `justify-content` property. ```tsx import { stack } from '../styled-system/patterns' function App() { return (
First
Second
Third
) } ```
```tsx import { Stack } from '../styled-system/jsx' function App() { return (
First
Second
Third
) } ```
#### HStack The HStack pattern is a wrapper around the `stack` pattern that sets the `direction` property to `horizontal`, and centers the elements vertically. ```tsx import { hstack } from '../styled-system/patterns' function App() { return (
First
Second
Third
) } ```
```tsx import { HStack } from '../styled-system/jsx' function App() { return (
First
Second
Third
) } ```
#### VStack The VStack pattern is a wrapper around the `stack` pattern that sets the `direction` property to `vertical`, and centers the elements horizontally. ```tsx import { vstack } from '../styled-system/patterns' function App() { return (
First
Second
Third
) } ```
```tsx import { VStack } from '../styled-system/jsx' function App() { return (
First
Second
Third
) } ```
### Wrap The Wrap pattern is used to add space between elements and wraps automatically if there isn't enough space. The `wrap` function accepts the following properties: - `gap`: The gap between the elements in the stack. - `columnGap`: The gap between the elements in the stack horizontally. - `rowGap`: The gap between the elements in the stack vertically. - `align`: An alias for the css `align-items` property. - `justify`: An alias for the css `justify-content` property. ```tsx import { wrap } from '../styled-system/patterns' function App() { return (
First
Second
Third
) } ```
```tsx import { Wrap } from '../styled-system/jsx' function App() { return (
First
Second
Third
) } ```
### Aspect Ratio The Aspect Ratio pattern is used to create a container with a fixed aspect ratio. It is used when displaying images, maps, videos and other media. > **Note:** In most cases, we recommend using the `aspectRatio` property instead of the pattern. The `aspectRatio` function accepts the following properties: - `ratio`: The aspect ratio of the container. Can be a number or a string. ```tsx import { aspectRatio } from '../styled-system/patterns' function App() { return (