# Panda CSS Guides > This document contains all guides documentation for Panda CSS ## Table of Contents - [Using Panda in a Component Library](#using-panda-in-a-component-library) - [Debugging](#debugging) - [Dynamic styling](#dynamic-styling) - [Custom Font](#custom-font) - [Minimal Setup](#minimal-setup) - [Multi-Theme Tokens](#multi-theme-tokens) - [Static CSS Generator](#static-css-generator) --- ## Using Panda in a Component Library How to set up Panda in a component library When creating a component library that uses Panda which can be used in a variety of different projects, you have four options: 1. Ship a Panda [preset](/docs/customization/presets) 2. Ship a static CSS file 3. Use Panda as external package, and ship the src files 4. Use Panda as external package, and ship the build info file > In the examples below, we use `tsup` as the build tool. You can use any other build tool. ## Recommendations - If your library code shouldn't be published on npm and App code uses Panda, use [ship build info](#ship-the-build-info-file) approach - If your app code doesn't use Panda, use the [static css](#ship-a-static-css-file) file approach - If your app code lives in a monorepo, use the [include src files](#include-the-src-files) approach - If your library code doesn't ship components but only ships tokens, patterns or recipes, use the [ship preset](#ship-a-panda-preset) approach > âš ī¸ If you use the `include src files` or `ship build info` approach, you might also need to ship a `preset` if your > library code has any custom tokens, patterns or recipes. ## Ship a Panda Preset This is the simplest approach. You can include the token, semantic tokens, text styles, etc. within a preset and consume them in your projects. **Library code** ```tsx filename="src/index.ts" import { definePreset } from '@pandacss/dev' export const acmePreset = definePreset({ theme: { extend: { tokens: { colors: { primary: { value: 'blue.500' } } } } } }) ``` Build the preset code ```bash pnpm tsup src/index.ts ``` **App code** ```tsx filename="panda.config.ts" import { acmePreset } from '@acme-org/panda-preset' import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... presets: ['@pandacss/dev/presets', acmePreset] }) ``` > Adding a preset will remove the default theme from Panda. To add it back, you need to include the > `@pandacss/dev/presets` preset. ## Ship a Static CSS File This approach involves extracting the static css of your library at build time. Then you can import the CSS file in your app code. **Library code** ```tsx filename="src/index.tsx" import { css } from '../styled-system/css' export function Button({ children }) { return ( ) } ``` Then you can build the library code and generate the static CSS file: ```bash # build the library code tsup src/index.tsx # generate the static CSS file panda cssgen --outfile dist/styles.css ``` Finally, don't forget to include the [cascade layers](/docs/concepts/cascade-layers) as well in your app code: **App code** ```tsx filename="src/App.tsx" import { Button } from '@acme-org/design-system' import './main.css' export function App() { return } ``` **main.css** ```css filename="src/main.css" @layer reset, base, tokens, recipes, utilities; @import url('@acme-org/design-system/dist/styles.css'); /* Your own styles here */ ``` This approach comes with a few downsides: - You can't customize the styles since the css is already generated - You might need add the [prefix](/docs/references/config#prefix) option to avoid className conflicts ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... prefix: 'acme' }) ``` - You might have duplicate CSS classes when using multiple atomic css libraries ## Use Panda as external package ### Summary - create a Panda [preset](/docs/customization/presets) so that you (and your users) can share the same design system tokens - create a workspace package for your outdir (`@acme-org/styled-system`) and use that package name as the `importMap` in your app code - have your component library (`@acme-org/components`) use the `@acme-org/styled-system` package as external --- Let's make a dedicated workspace package for your `outdir`: 1. Create a new directory `packages/styled-system` (or any other name) 2. Install `@pandacss/dev` as a dev dependency 3. Run the `panda init` command in there to generate a `panda.config.ts` file, don't forget to set the `jsxFramework` if needed 4. [optional] you might want to install and import your [preset](/docs/customization/presets) in this `panda.config.ts` file as well 5. Run the [`panda emit-pkg`](/docs/references/cli#emit-pkg) command to set the entrypoints in [`exports`](https://nodejs.org/api/packages.html#exports) This should look similar to this: ```json { "name": "@acme-org/styled-system", "version": "1.0.0", "exports": { "./css": { "types": "./css/index.d.ts", "require": "./css/index.mjs", "import": "./css/index.mjs" }, "./tokens": { "types": "./tokens/index.d.ts", "require": "./tokens/index.mjs", "import": "./tokens/index.mjs" }, "./types": { "types": "./types/index.d.ts", "require": "./types/index.mjs", "import": "./types/index.mjs" }, "./patterns": { "types": "./patterns/index.d.ts", "require": "./patterns/index.mjs", "import": "./patterns/index.mjs" }, "./recipes": { "types": "./recipes/index.d.ts", "require": "./recipes/index.mjs", "import": "./recipes/index.mjs" }, "./jsx": { "types": "./jsx/index.d.ts", "require": "./jsx/index.mjs", "import": "./jsx/index.mjs" }, "./styles.css": "./styles.css" }, "devDependencies": { "@pandacss/dev": "^1.4.2", "@types/react": "19.2.2", "react": "^19.2.0" }, "peerDependencies": { "react": ">=19" } } ``` > Notice that we've included the `react` and its corresponding `@types/react` in the `devDependencies` and > `peerDependencies`. This is to ensure the types are correctly set up in the `styled-system` package. Going forward, you'll now import the functions from the `@acme-org/styled-system` monorepo package. ```tsx import { css } from '@acme-org/styled-system/css' export function Button({ children }) { return ( ) } ``` **App code** Install the newly created `@acme-org/styled-system` package in your app code. ```bash pnpm add @acme-org/styled-system ``` Configure the `importMap` in your `panda.config.ts` to match the `name` field of your outdir `package.json`. This will inform Panda which imports belong to the `styled-system`. ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... importMap: '@acme-org/styled-system', outdir: 'styled-system' }) ``` Mark the `@acme-org/styled-system` as an external package in your library build tool. This ensures that the generated JS runtime code is imported only once, avoiding duplication. ```bash tsup src/index.tsx --external @acme-org/styled-system ``` ### Include the src files Include the `src` directory from the library code in the panda config. ```tsx {6} filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... include: ['../@acme-org/design-system/src/**/*.tsx', './src/**/*.{ts,tsx}'], importMap: '@acme-org/styled-system', outdir: 'styled-system' }) ``` ### Ship the build info file This approach is similar to the previous one, but instead of shipping the source code, you ship the Panda build info file. This will have **the exact same end-result** as adding the sources files in the `include`, but it will allow you not to ship the source code. The build info file is a JSON file that **only** contains the information about the static extraction result, you still need to ship your app build/dist by yourself. It can be used by Panda to generate CSS classes without the need for parsing the source code. Generate the build info file: ```bash panda ship --outfile dist/panda.buildinfo.json ``` **App code** Install the newly created `@acme-org/styled-system` package in your app code. ```bash pnpm add @acme-org/styled-system ``` Configure the `importMap` in your `panda.config.ts` to match the `name` field of your outdir `package.json`. This will inform Panda which imports belong to the `styled-system`. ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... importMap: '@acme-org/styled-system', outdir: 'styled-system' }) ``` Will allow imports like: ```tsx import { css } from '@acme-org/styled-system/css' import { button } from '@acme-org/styled-system/recipes' ``` Next, you need to include the build info file from the library code in the panda config. ```tsx {6} filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... include: ['./node_modules/@acme-org/design-system/dist/panda.buildinfo.json', './src/**/*.{ts,tsx}'], importMap: '@acme-org/styled-system', outdir: 'styled-system' }) ``` ## FAQ ### Why should my component library use an external package `styled-system`? By de-coupling the component library from the `styled-system`, your users can share the same runtime code between your library and their app code. ```tsx filename="component-lib/src/button.tsx" import { css } from '@acme-org/styled-system/css' export function Button({ children, css: cssProp }) { return ( ) } ``` ```tsx filename="app/src/App.tsx" import { Button } from '@acme-org/design-system' import { css } from '@acme-org/styled-system/css' export function App() { return } ``` Marking the `styled-system` as an external package in your build tool means that the generated JS runtime code (the `css` function is the example above) is imported only once, avoiding duplication. ### How do I use the `@acme-org/styled-system` package ? You can use your monorepo workspace package `@acme-org/styled-system` just like any other dependency in your app or component library code. ```bash pnpm add @acme-org/styled-system ``` Set the `importMap` in your `panda.config.ts` to that same package name. This will inform Panda which imports belong to the `styled-system`. ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... importMap: '@acme-org/styled-system' }) ``` Then you can import the functions from the `@acme-org/styled-system` monorepo package. ```tsx import { css } from '@acme-org/styled-system/css' export function Button({ children }) { return ( ) } ``` ### How to override tokens used by the `@acme-org/styled-system` package? You can override the tokens used by the `@acme-org/styled-system` package by extending the `theme` in your `panda.config.ts` file. ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ //... presets: ['@acme-org/preset'] theme: { extend: { tokens: { colors: { primary: { value: 'blue.500' } } } } } }) ``` ## Troubleshooting - When using `tsup` or any other build tool for your component library, if you run into a module resolution error that looks similar to `ERROR: Could not resolve "../styled-system/xxx"`. Consider setting the `outExtension`in the panda config to`js` - If you use Yarn PnP, you might need to set the `nodeLinker: node-modules` in the `.yarnrc.yml` file. --- ## Debugging How can I debug my styles or profile the extraction process? ## panda debug Panda's built-in debug command helps you see which files are processed, what styles are generated, and your final config. By default it will scan and output debug files for the entire project depending on your `include` and `exclude` options from your config file. {/* */} ```bash pnpm panda debug # You can also debug a specific file or folder # using the optional glob argument pnpm panda debug src/components/Button.tsx pnpm panda debug "./src/components/**" ``` ```bash npx panda debug # # You can also debug a specific file or folder # using the optional glob argument npx panda debug src/components/Button.tsx npx panda debug "./src/components/**" ``` ```bash yarn panda debug # # You can also debug a specific file or folder # using the optional glob argument yarn panda debug src/components/Button.tsx yarn panda debug "./src/components/**" ``` ```bash bun panda debug # # You can also debug a specific file or folder # using the optional glob argument bun panda debug src/components/Button.tsx bun panda debug "./src/components/**" ``` {/* */} This would generate a `debug` folder in your `config.outdir` folder with the following structure: The `config.json` file will contain the resolved config result, meaning the output after merging config presets in your own specific options. It can be useful to check if your config contains everything you expect for your app to be working, such as tokens or recipes. `*.ast.json` files will look like: ```json [ { "name": "css", "type": "object", "data": [ { "transitionProperty": "all", "opacity": "0.5", "border": "1px solid", "borderColor": "black", "color": "gray.600", "_hover": { "color": "gray.900" }, "rounded": "md", "p": "1.5", "_dark": { "borderColor": "rgba(255, 255, 255, 0.1)", "color": "gray.400", "_hover": { "color": "gray.50" } } } ], "kind": "CallExpression", "line": 13, "column": 9 } ] ``` And the `.css` file associated would just contain the styles generated from the extraction process on that file only. ## PANDA_DEBUG env variable You can prefix any of the Panda CLI command with the `PANDA_DEBUG` environment variable to show debug logs. ```bash PANDA_DEBUG=* pnpm panda ``` This can be useful to check if a specific file is being processed or not, or if a specific function/component has been extracted. ``` ❯ PANDA_DEBUG=* pnpm panda cssgen đŸŧ debug [config:path] /Users/astahmer/dev/open-source/panda-clone/website/panda.config.ts đŸŧ debug [ast:import] Found import { css } in /Users/astahmer/dev/open-source/panda-clone/website/theme.config.tsx đŸŧ debug [ast:Icon] { kind: 'component' } đŸŧ debug [ast:css] { kind: 'function' } đŸŧ debug [hrtime] Parsed /Users/astahmer/dev/open-source/panda-clone/website/theme.config.tsx (9.66ms) đŸŧ debug [ast:import] Found import { css } in /Users/astahmer/dev/open-source/panda-clone/website/src/DEFAULT_THEME.tsx đŸŧ debug [ast:DiscordIcon] { kind: 'component' } đŸŧ debug [ast:css] { kind: 'function' } đŸŧ debug [ast:Anchor] { kind: 'component' } đŸŧ debug [ast:GitHubIcon] { kind: 'component' } đŸŧ debug [ast:Flexsearch] { kind: 'component' } đŸŧ debug [ast:MatchSorterSearch] { kind: 'component' } đŸŧ debug [hrtime] Parsed /Users/astahmer/dev/open-source/panda-clone/website/src/DEFAULT_THEME.tsx (4.51ms) đŸŧ debug [ast:import] No import found in /Users/astahmer/dev/open-source/panda-clone/website/src/constants.tsx đŸŧ debug [hrtime] Parsed /Users/astahmer/dev/open-source/panda-clone/website/src/constants.tsx (4.23ms) đŸŧ debug [ast:import] Found import { css } in /Users/astahmer/dev/open-source/panda-clone/website/src/index.tsx đŸŧ debug [ast:css] { kind: 'function' } ``` ## Performance profiling If Panda is taking too long to process your files, you can use the `--cpu-prof` with the `panda`, `panda cssgen`, `panda codegen` and `panda debug` commands to generate a flamegraph of the whole process, which will allow you (or us as maintainers) to see which part of the process is taking the most time. This will generate a `panda-{command}-{timestamp}.cpuprofile` file in the current working directory, which can be opened in tools like [Speedscope](https://www.speedscope.app/) ```bash pnpm panda --cpu-prof ``` ## FAQ ### 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 `panda` command has been run (or is running with `--watch`). ### Some CSS is missing when using absolute imports This can happen when `tsconfig` (with `paths` or `baseUrl`) or with package.json [`#imports`](https://nodejs.org/api/packages.html#subpath-imports). Panda tries to automatically infer and read the custom paths defined in `tsconfig.json` file. However, there might be scenarios that won't work. To fix this add the `importMap` option to your `panda.config.js` file, setting it's value to match the way you import the `outdir` modules. ```app.tsx // app.tsx import { css } from "~/styled-system/css" // tsconfig.json paths // -> importMap: "~/styled-system" import { css } from "styled-system/css" // tsconfig.json baseUrl // -> importMap: "styled-system" import { css } from "@my-monorepo/ui-kit/css" // monorepo workspace package // -> importMap: "@my-monorepo/ui-kit" import { css } from "#styled-system/css" // package.json#imports // -> importMap: "#styled-system ``` ```js // panda.config.js export default defineConfig({ importMap: '~/styled-system' }) ``` This will ensure that the paths are resolved correctly, and HMR works as expected. --- ### How can I debug the styles? You can use the `panda 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/chakra-ui/panda/issues) or in the [discord](https://discord.gg/VQrkpsgSx7). If you can't find it, please create a minimal reproduction and submit [a new github issue](https://github.com/chakra-ui/panda/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. ### HMR does not work when I use `tsconfig` paths? Panda 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 `panda.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 // panda.config.js module.exports = { importMap: '@my-path' } ``` This will ensure that the paths are resolved correctly, and HMR works as expected. --- ## The postcss plugin sometimes seems slow or runs too frequently This is mostly specific to the host bundler (`vite`, `webpack` etc) you're using, it is up to them to decide when to run the postcss plugin again, and sometimes it can be more than needed for your usage. We do our best to cache the results of the postcss plugin by checking if the filesystem or your config have actually changed, but sometimes it might not be enough. In those rare cases, you might want to swap to using the [CLI](/docs/installation/cli) instead, as it will always be more performant than the postcss alternative since we directly watch for filesystem changes and only run the extract/codegen steps when needed. If you want to keep the convenience of having just one command to run, you can use something like `concurrently` for that: ```json file="package.json" { "scripts": { "dev": "concurrently \"next dev\" \"panda --watch\"" } } ``` --- ## Dynamic styling How to manage dynamic styling in Panda While Panda is mainly focused on the statically analyzable styles, you might need to handle dynamic styles in your project. > We recommend that you **avoid relying on runtime values for your styles** . Consider using recipes, css variables or > `data-*` attributes instead. Here are some ways you can handle dynamic styles in Panda: ## Runtime values Using a value that is not statically analyzable at build-time will not work in Panda due to the inability to determine the style values. ```tsx filename="App.tsx" import { useState } from 'react' import { css } from '../styled-system/css' const App = () => { const [color, setColor] = useState('red.300') return (
) } ``` The example above will not work because Panda can't determine the value of `color` at build-time. Here are some ways to fix this: ### Using Static CSS Panda supports a [`staticCss`](/docs/guides/static) option in the config you can use to pre-generate some styles ahead of time. ```tsx filename="panda.config.ts" import { defineConfig } from '@pandacss/dev' export default defineConfig({ staticCss: { css: [ { properties: { // ✅ Good: Pre-generate the styles for the color color: ['red.300'] } } ] } }) ``` ```tsx filename="Button.tsx" import { useState } from 'react' import { styled } from '../styled-system/jsx' export const Button = () => { const [color, setColor] = useState('red.300') // ✅ Good: This will work because `red.300` is pre-generated using `staticCss` config return } ``` ### Using `token()` The `token()` function is generated by Panda and contains an object of all tokens by dot-path, allowing you to query for token's raw value at runtime. ```tsx filename="App.tsx" import { useState } from 'react' import { css } from '../styled-system/css' import { token } from '../styled-system/tokens' const Component = props => { return (
Dynamic color with runtime value
) } // App.tsx const App = () => { const [runtimeColor, setRuntimeColor] = useState('pink.300') return } ``` ### Using `token.var()` You could also directly use the `token.var()` function to get a reference to the underlying CSS custom property for a given token: ```tsx filename="App.tsx" import { useState } from 'react' import { token } from '../styled-system/tokens' const Component = props => { return (
Dynamic color with runtime value
) } const App = () => { const [runtimeColor, setRuntimeColor] = useState('yellow.300') return } ``` ## JSX Style Props Panda supports forwarding JSX style properties to any element in your codebase. For example, let's say we create a Card component that accepts a `color` prop: ```tsx filename="Card.tsx" import { styled } from '../styled-system/jsx' const Card = props => { return } ``` Then you add more style props to the Card component in a different file: ```tsx filename="App.tsx" const App = () => { return (

Some content

) } ``` As long as all prop-value pairs are statically extractable, Panda will automatically generate the CSS, so avoid using runtime values: ```tsx filename="App.tsx" import { useState } from 'react' const App = () => { const [color, setColor] = useState('blue.300') // ❌ Avoid: Panda can't determine the value of color at build-time return (

Some content

) } ``` ## Property Renaming Due to the static nature of Panda, you can't rename properties at runtime. ```tsx filename="App.tsx" import { Circle, CircleProps } from '../styled-system/jsx' type Props = { circleSize?: CircleProps['size'] } const CustomCircle = (props: Props) => { const { circleSize = '3' } = props return ( ) } ``` In this case, you need to use the `size` prop. ### Alternative As of v0.8, we added a new `{fn}.raw()` method to css, patterns and recipes. This function is an identity function and only serves as a hint for the compiler to extract the css. It can be useful, for example, in Storybook args or custom react props. ```tsx filename="App.tsx" // mark the object as valid css for the extractor