# Panda CSS Complete Documentation
> Panda CSS is a CSS-in-JS framework with build-time optimizations for styling web applications
This document contains the complete Panda 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 Panda](#get-started-with-panda)
- [LLMs.txt](#llms.txt)
- [Why Panda](#why-panda)
### Installation
- [Using Angular](#using-angular)
- [Using Astro](#using-astro)
- [Panda CLI](#panda-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)
- [Panda Integration Hooks](#panda-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)
- [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 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)
### Migration
- [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 Panda](#configuring-panda)
---
# Overview
## Browser Support
Learn about the browser support for Panda
Panda CSS is built with modern CSS features and uses [PostCSS](https://postcss.org/) to add support for older browsers.
Panda 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: ['@pandacss/dev/postcss', 'autoprefixer', '@csstools/postcss-cascade-layers']
}
```
---
## Frequently Asked Questions
Frequently asked questions and how to resolve common issues
## How does Panda manage style conflicts ?
When you combine shorthand and longhand properties, Panda 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 Panda 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 Panda 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 Panda config, set the `outExtension` to `js`:
```ts
export default defineConfig({
// ...
outExtension: 'js'
})
```
---
## 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.
---
## HMR not triggered
If you are having issues with HMR not being triggered after a `panda.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 `panda.config.ts`:
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 `panda` command has been run (or is running with `--watch`).
---
## 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.
---
## 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 does Panda work?
When running `pnpm panda`, here's what's happening under the hood:
- **Load Panda context**:
- Find and evaluate app config, merge result with presets.
- Create panda 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/tsup. What should I do?
In such a case, check the [`outExtension`](/docs/references/config#outextension) in your `panda.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 `@pandacss/preset-panda` 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 Panda?
There is a detailed guide on how to do this [here](/docs/guides/component-library).
---
## Can I use dynamic styles with Panda?
Yes, you can use dynamic styles with Panda. More on that [here](/docs/guides/dynamic-styling#runtime-conditions).
---
## 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 panda 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 panda 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://panda-css.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 Panda'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 Panda
The universal design system solution for the web
Panda is a styling engine that generates styling primitives to author atomic CSS and recipes in a type-safe and readable
manner.
Panda 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; Panda is a CSS-in-JS engine that generates atomic CSS at build time (via CLI or PostCSS)
## Installation
### General Guides
- [Panda CLI](/docs/installation/cli): The simplest way to use Panda is with the Panda CLI tool.
- [Using PostCSS](/docs/installation/postcss): (**Recommended**) Installing Panda as a PostCSS plugin is the recommended
way to integrate it with your project.
### Framework Guides
Start using Panda 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 Panda.
## Playground
You can use the [online playground](https://play.panda-css.com) to get a taste of what Panda can do.
- See the live results of your JSX code
- Inspect what panda can extract using static analysis from your code
- Preview the statically generated `.css` files
## Acknowledgement
The development of Panda was only possible due to the inspiration and ideas from these amazing projects.
- [Chakra UI](https://chakra-ui.com/) - where it all started
- [Vanilla Extract](https://vanilla-extract.style/) - for inspiring the utilities API
- [Stitches](https://stitches.dev/) - for inspiring the recipes and variants API
- [Tailwind CSS](https://tailwindcss.com/) - for inspiring the JIT compiler and strategy
- [Class Variance Authority](https://cva.style/) - for inspiring the `cva` name
- [Styled System](https://styled-system.com/) - for the initial idea of Styled Props
- [Linaria](https://linaria.dev/) - for inspiring the initial atomic css strategy
- [Uno CSS](https://unocss.dev) - for inspiring the studio and astro integration
---
## LLMs.txt
Help AI tools understand Panda CSS with LLMs.txt support.
## What is LLMs.txt?
[LLMs.txt](https://llmstxt.org/) files are used to provide the Panda CSS documentation to large language models (LLMs).
This helps AI tools better understand our styling engine, its APIs, and usage patterns.
## Available Routes
These routes are available to help AI tools access our documentation:
- [/llms.txt](/llms.txt) - Contains a structured overview of all concepts and their documentation links
- [/llms-full.txt](/llms-full.txt) - Provides comprehensive documentation including implementation details and examples
## Access Individual Pages
You can also access the raw markdown content for any documentation page by adding `.mdx` to the end of the URL. For
example:
- [`/docs/overview/getting-started.mdx`](/docs/overview/getting-started.mdx) - Raw markdown for the getting started page
- [`/docs/concepts/recipes.mdx`](/docs/concepts/recipes.mdx) - Raw markdown for the recipes documentation
- [`/docs/theming/tokens.mdx`](/docs/theming/tokens.mdx) - Raw markdown for the tokens documentation
This is useful for AI tools that need to access specific documentation sections directly.
## Usage with AI Tools
### Cursor
Use the `@Docs` feature in Cursor to include the LLMs.txt files in your project. This helps Cursor provide more accurate
code suggestions and documentation for Panda CSS.
[Read more about @Docs in Cursor](https://docs.cursor.com/context/@-symbols/@-docs)
### Windsurf
Reference the LLMs.txt files using `@` or in your `.windsurfrules` files to enhance Windsurf's understanding of Panda
CSS.
[Read more about Windsurf Memories](https://docs.codeium.com/windsurf/memories#memories-and-rules)
### Other AI Tools
Any AI tool that supports LLMs.txt can use these routes to better understand Panda CSS. Simply point your tool to any of
the routes above to get comprehensive documentation about our styling engine.
---
## Why Panda
From the endless list of CSS-in-JS libraries, why should you choose Panda?
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
Panda 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:** Panda 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, Panda uses a set of PostCSS plugins to convert the parsed data to atomic css at
build time. **This makes Panda compatible with any framework that supports PostCSS.**
- **Codegen:** Panda 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:** Panda combines `csstype` and auto-generated typings to provide type-safety for css properties and
design tokens.
- **Performance:** Panda uses a unique approach to generate atomic CSS files that are optimized for performance and
readability.
- **Developer Experience:** Panda provides a great developer experience with a rich set of features like recipes,
patterns, design tokens, JSX style props, and more.
- **Modern CSS**: Panda uses modern CSS features like cascade layers, css variables, modern selectors like `:where` and
`:is` in generated styles.
## When to use Panda?
### Styling engine
If you're building a JavaScript application with a framework that supports PostCSS, Panda is a great choice for you.
```jsx
import { css } from '../styled-system/css'
import { circle, stack } from '../styled-system/patterns'
function App() {
return (
John Doe
john@doe.com
)
}
```
> If your framework doesn't support PostCSS, you can use the [Panda CLI](/docs/installation/cli)
### Token generator
Panda 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="panda.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 `panda 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 Panda?
Panda 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 Panda with Angular with our dedicated integration.
This guide shows you how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init
```
```bash
npm install -D @pandacss/dev
npx panda init
```
```bash
yarn add -D @pandacss/dev
yarn panda init
```
```bash
bun add -D @pandacss/dev
bun panda 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": {
"@pandacss/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": "panda codegen",
"ng": "ng",
"start": "ng serve",
"build": "ng build",
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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
`panda.config.ts` file.
```js {8, 17} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with Astro with our dedicated integration.
This guide shows you how to set up Panda CSS in an Astro project using our dedicated integration.
## Setup
### Install Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda init --postcss
```
{/* */}
### Update package.json scripts
Open your `package.json` file and update the `scripts` section as follows:
```diff {3}
{
"scripts": {
+ "prepare": "panda 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#panda-codegen) in the CLI section.
> This step ensures that the panda 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 panda config to your `panda.config.js` file, or wherever panda is configured in your project.
```js {6}
import { defineConfig } from '@pandacss/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: {
- '@pandacss/dev/postcss': {}
- }
+ plugins: [require('@pandacss/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 Panda
Use the generated style utilities in your code, and panda 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"]
}
```
---
## Panda CLI
An alternative way to use Panda is by running the Panda CLI tool.
This guide shows you how to use Panda as an alternative approach by running the Panda CLI tool.
### Install Panda
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init
```
```bash
npm install -D @pandacss/dev
npx panda init
```
```bash
yarn add -D @pandacss/dev
yarn panda init
```
```bash
bun add -D @pandacss/dev
bun panda init
```
{/* */}
### Configure the content
Add the paths to all of your JavaScript or TypeScript code where you intend to use panda.
```js {5}
import { defineConfig } from '@pandacss/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": "panda codegen",
}
}
```
The `prepare` script that will run codegen after dependency installation. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 Panda 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 Panda build process
Run the CLI tool to scan your JavaScript and TypeScript files for style properties and call expressions.
{/* */}
```bash
# Run it once
pnpm panda
# Run it in watch mode
pnpm panda --watch
```
```bash
# Run it once
npx panda
# Run it in watch mode
npx panda --watch
```
```bash
# Run it once
yarn panda
# Run it in watch mode
yarn panda --watch
```
```bash
# Run it once
bun panda
# Run it in watch mode
bun panda --watch
```
{/* */}
### Start using Panda
Use the generated style utilities in your code and panda 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 Panda with Ember with our dedicated integration.
This guide shows you how to set up Panda 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 Panda
Install panda and its peer dependencies, as well as `postcss-loader`. Run the init command to generate the
`panda.config.ts` and `postcss.config.js` file.
{/* */}
```bash
pnpm install -D @pandacss/dev postcss postcss-loader
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev postcss postcss-loader
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev postcss postcss-loader
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev postcss postcss-loader
bun panda 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 Panda PostCSS plugin picks up your app CSS files.
```js {4} filename="postcss.config.cjs"
module.exports = {
plugins: {
'@pandacss/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": "panda codegen",
// ...
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.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="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda CSS in your project.
```ts filename="app/components/hello-panda.ts"
import Component from '@glimmer/component'
import { css } from 'test-app/styled-system/css'
export default class HelloPanda extends Component {
style = css({ fontSize: '5xl', fontWeight: 'bold' })
}
```
```hbs filename="app/components/hello-panda.hbs"
{{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 Panda with Gatsby with our dedicated integration.
This guide shows you how to set up Panda 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 Panda CSS
Install Panda CSS and `gatsby-plugin-postcss` to your project. After that run the `panda init` command to setup Panda
CSS in your project.
```bash
npm install -D @pandacss/dev postcss gatsby-plugin-postcss
npx panda 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": "panda codegen",
"develop": "gatsby develop",
"start": "gatsby develop",
"build": "gatsby build",
"serve": "gatsby serve",
"clean": "gatsby clean",
"typecheck": "tsc --noEmit"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.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="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with Next.js with our dedicated integration.
Setting up Panda 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 Panda CSS](#install-panda-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 Panda CSS
Install Panda CSS dependency using your favorite package manager.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda init --postcss
```
{/* */}
`panda 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: {
'@pandacss/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": "panda 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#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
{/* */}
```ts {8} filename="panda.config.ts"
import { defineConfig } from "@pandacss/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", })
````
{/* */}
{/* */}
```js {8} filename="panda.config.ts"
import { defineConfig } from "@pandacss/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 Panda
We will update the contents of `src/app/page.tsx` with the following snippet that uses Panda CSS:
We will update the contents of `src/pages/index.tsx` with the following snippet that uses Panda 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 Panda with Nuxt with the vue integration.
Learn how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init
```
```bash
npm install -D @pandacss/dev
npx panda init
```
```bash
yarn add -D @pandacss/dev
yarn panda init
```
```bash
bun add -D @pandacss/dev
bun panda init
```
{/* */}
### Update package.json scripts
Open your `package.json` file and update the `scripts` section as follows:
```diff {3} filename="package.json"
{
"scripts": {
+ "prepare": "panda codegen",
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {8, 17} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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: {
'@pandacss/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 panda 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 Panda
Now you can start using Panda CSS in your project.
As an example here is a snippet of code for a `components/Demo.vue` file.
```xml filename="components/Demo.vue"
Hello πΌ!
```
---
## Using PostCSS
Installing Panda as a PostCSS plugin is the recommended way to integrate it with your project.
This guide shows you how to install Panda as a PostCSS plugin, which is the recommended way to integrate it with your
project.
### Install Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev postcss
pnpm panda init -p
```
```bash
npm install -D @pandacss/dev postcss
npx panda init -p
```
```bash
yarn add -D @pandacss/dev postcss
yarn panda init -p
```
```bash
bun add -D @pandacss/dev postcss
bun panda init -p
```
{/* */}
### Add Panda to your PostCSS config
Add panda to your `postcss.config.cjs` file, or wherever PostCSS is configured in your project.
```js
module.exports = {
plugins: {
'@pandacss/dev/postcss': {}
}
}
```
### Configure the content
Add your panda config to your `panda.config.js` file, or wherever panda is configured in your project.
```js {5}
import { defineConfig } from '@pandacss/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": "panda codegen",
}
}
```
The `prepare` script will run codegen after dependency installation. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 Panda
Use the generated style utilities in your code and panda 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 Panda with Preact with our dedicated integration.
This guide shows you how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda 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": "panda 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 Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {6} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with Qwik with our dedicated integration.
Learn how to set up Panda 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 Panda
Qwik provies an official script that installs panda and configures it for you.
{/* */}
```bash
npm run qwik add pandacss
```
```bash
pnpm qwik add pandacss
```
```bash
yarn qwik add pandacss
```
```bash
bun qwik add pandacss
```
{/* */}
## 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 Panda
Now you can start using Panda 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 Panda with React Router with our dedicated integration.
This guide will show you how to set up Panda CSS in a React Router project using PostCSS.
## Start a new project
### Create React Router 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:
```
? 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 Panda CSS.
### Install Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda 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 Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda output directory is regenerated after each dependency installation. So you can add
> the Panda 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
`panda.config.ts` file.
```ts {5, 8, 11} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 PandaCSS
Update the `vite.config.ts` file to use PandaCSS instead of TailwindCSS.
```ts {3, 10} filename="vite.config.ts"
import { reactRouter } from '@react-router/dev/vite'
import autoprefixer from 'autoprefixer'
import pandacss from '@pandacss/dev/postcss'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
css: {
postcss: {
plugins: [pandacss, 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 {11, 15} 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 Panda
Now you can start using Panda 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 Panda with Redwood.js with our dedicated integration.
This guide shows you how to set up Panda 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 Panda
Install panda and generate the `panda.config.ts` and `postcss.config.js` file.
```bash
cd web
yarn add -D @pandacss/dev postcss postcss-loader
yarn panda init --postcss
```
### Move to config folder
Redwood uses a `config` folder for all of the configuration files. Move the `panda.config.ts` and `postcss.config.js`
files to the `config` folder.
```bash
mv panda.config.ts postcss.config.js config/
```
### Update configs
Update the postcss config file to use the `panda.config.ts` file.
```diff filename="web/config/postcss.config.js"
+ const path = require('path')
module.exports = {
plugins: {
"@pandacss/dev/postcss": {
+ configPath: path.resolve(__dirname, 'panda.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": "panda codegen"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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
`panda.config.ts` file.
```js {5} filename="web/config/panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with Remix with our dedicated integration.
This guide will show you how to set up Panda 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 Panda CSS.
### Install Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda codegen",
"build": "remix build",
"dev": "remix dev",
"start": "remix-serve build",
"typecheck": "tsc"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda output directory is regenerated after each dependency installation. So you can add
> the Panda 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 `panda.config.ts`
file.
```js {5, 11} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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" {11,13}
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 Panda
Now you can start using Panda 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 `panda.config.ts` file, consider adding `watchPaths` in your remix
config file.
```js filename="remix.config.js"
export default {
// ...
watchPaths: ['panda.config.ts']
}
```
---
## Using Rsbuild
Easily use Panda with Rsbuild, React and Typescript with our dedicated integration.
This guide shows you how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda codegen",
"preview": "rsbuild preview"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {8} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with SolidJS with our dedicated integration.
This guide will show you how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda 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 Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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
`panda.config.ts` file.
```js {8, 17} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Panda with Storybook with our dedicated integration.
Learn how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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 {3} filename="postcss.config.js"
module.exports = {
- plugins: {
- '@pandacss/dev/postcss': {}
- }
+ plugins: [require('@pandacss/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": "panda codegen"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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
`panda.config.ts` file.
```js {9} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 '@pandacss/dev/postcss'`, update the
PostCSS config as follows:
```js filename="postcss.config.js"
module.exports = {
plugins: [require('@pandacss/dev/postcss')]
}
```
### HMR not triggered
If you are having issues with HMR not being triggered after a `panda.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 `panda.config.ts`:
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda find style usage](https://panda-css.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="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
recipes: '*'
}
})
```
---
## Using Svelte
Easily use Panda with Svelte with our dedicated integration.
This guide will show you how to set up Panda 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:
```
β 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 Panda
To install Panda and corresponding dependencies run the following commands:
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda 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 ."
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {8} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda alias update the `svelte.config.js` file as follows:
```js {3,11-13,21-23} 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:
```html {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 Panda
Now you can start using Panda CSS in your project. Here is the snippet of code that you can use in your
`src/routes/+page.svelte` file.
```jsx filename="src/routes/+page.svelte"
Hello πΌ!
```
## Troubleshooting
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 Panda with Vite, React and Typescript with our dedicated integration.
This guide will show you how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda 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 Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {8} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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 Vue
Easily use Panda with Vue with our dedicated integration.
Learn how to set up Panda 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 Panda
Install panda and create your `panda.config.ts` file.
{/* */}
```bash
pnpm install -D @pandacss/dev
pnpm panda init --postcss
```
```bash
npm install -D @pandacss/dev
npx panda init --postcss
```
```bash
yarn add -D @pandacss/dev
yarn panda init --postcss
```
```bash
bun add -D @pandacss/dev
bun panda 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": "panda codegen",
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"build-only": "vite build"
}
}
```
- `"prepare"` - script that will run Panda CSS CLI codegen before each build. Read more about
[codegen](/docs/references/cli#panda-codegen) in the CLI section.
> This step ensures that the panda 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 `panda.config.ts`
file.
```js {8, 17} filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 Panda
Now you can start using Panda 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"
Hello πΌ!
```
---
# 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.
Panda 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
Panda 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 Panda 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
Panda 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: ['@pandacss/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 `@pandacss/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 '@pandacss/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 Panda.
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.
Panda 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 Panda 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
Panda includes a set of common pseudo states that you can use to style your components:
- Pseudo Class: `_hover`, `_active`, `_focus`, `_focus-visible`, `_focus-within`, `_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 `@pandacss/preset-panda` 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 Panda:
| 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])` |
| \_active | `&:is(:active, [data-active])` |
| \_visited | `&:visited` |
| \_target | `&:target` |
| \_readOnly | `&:is(:read-only, [data-read-only])` |
| \_readWrite | `&:read-write` |
| \_empty | `&:is(:empty, [data-empty])` |
| \_checked | `&:is(:checked, [data-checked], [aria-checked=true])` |
| \_enabled | `&:enabled` |
| \_expanded | `&:is([aria-expanded=true], [data-expanded])` |
| \_highlighted | `&[data-highlighted]` |
| \_before | `&::before` |
| \_after | `&::after` |
| \_firstLetter | `&::first-letter` |
| \_firstLine | `&::first-line` |
| \_marker | `&::marker` |
| \_selection | `&::selection` |
| \_file | `&::file-selector-button` |
| \_backdrop | `&::backdrop` |
| \_first | `&:first-child` |
| \_last | `&:last-child` |
| \_only | `&:only-child` |
| \_even | `&:even` |
| \_odd | `&: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]) ~ &` |
| \_peerChecked | `.peer:is(:checked, [data-checked], [aria-checked=true]) ~ &` |
| \_peerInvalid | `.peer:is(:invalid, [data-invalid], [aria-invalid=true]) ~ &` |
| \_peerExpanded | `.peer:is([aria-expanded=true], [data-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]) &` |
| \_groupChecked | `.group:is(:checked, [data-checked], [aria-checked=true]) &` |
| \_groupExpanded | `.group:is([aria-expanded=true], [data-expanded]) &` |
| \_groupInvalid | `.group:is(:invalid, [data-invalid]) &` |
| \_indeterminate | `&:is(:indeterminate, [data-indeterminate], [aria-checked=mixed])` |
| \_required | `&:is(:required, [data-required], [aria-required=true])` |
| \_valid | `&:is(:valid, [data-valid])` |
| \_invalid | `&:is(:invalid, [data-invalid])` |
| \_autofill | `&:autofill` |
| \_inRange | `&:in-range` |
| \_outOfRange | `&:out-of-range` |
| \_placeholder | `&:is(:placeholder, [data-placeholder])` |
| \_placeholderShown | `&:is(:placeholder-shown, [data-placeholder-shown])` |
| \_pressed | `&:is([aria-pressed=true], [data-pressed])` |
| \_selected | `&:is([aria-selected=true], [data-selected])` |
| \_default | `&:default` |
| \_optional | `&:optional` |
| \_open | `&[open]` |
| \_fullscreen | `&:fullscreen` |
| \_loading | `&:is([data-loading], [aria-busy=true])` |
| \_currentPage | `&[aria-current=page]` |
| \_currentStep | `&[aria-current=step]` |
| \_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, .dark &` |
| \_light | `&.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 | `[dir=ltr] &` |
| \_rtl | `[dir=rtl] &` |
| \_scrollbar | `&::-webkit-scrollbar` |
| \_scrollbarThumb | `&::-webkit-scrollbar-thumb` |
| \_scrollbarTrack | `&::-webkit-scrollbar-track` |
| \_horizontal | `&[data-orientation=horizontal]` |
| \_vertical | `&[data-orientation=vertical]` |
## Custom conditions
Panda 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 Panda configuration. It is useful when you want to add your own
customizations to Panda, 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 Panda:
- [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 `panda init` command you should see something similar to this:
```ts
import { defineConfig } from '@pandacss/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 '@pandacss/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 '@pandacss/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 '@pandacss/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 '@pandacss/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 `@pandacss/preset-base` preset (included by default).
You can pick only the parts that you need with and spread the rest, like this:
```ts
import pandaBasePreset from '@pandacss/preset-base'
// omitting stack here
const { stack, ...pandaBasePresetPatterns } = pandaBasePreset.patterns
export default defineConfig({
presets: ['@pandacss/preset-panda'], // π we still want the tokens, breakpoints and textStyles from this preset
// β οΈ we need to eject to prevent the `@pandacss/preset-base` from being resolved
// https://panda-css.com/docs/customization/presets#which-panda-presets-will-be-included-
eject: true,
patterns: {
extend: {
...pandaBasePresetPatterns
// your customizations here
}
}
})
```
## Minimal setup
If you want to use Panda 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.
---
## Panda Integration Hooks
Leveraging hooks in Panda to create custom functionality.
Panda 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 panda 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 Panda can
automatically extract its styles usage
- create your own styles parser (`parser:before`, `parser:after`) using the file's content so that Panda 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 '@pandacss/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 '@pandacss/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 '@pandacss/dev'
export default defineConfig({
// ...
hooks: {
'preset:resolved': ({ utils, preset, name }) => {
if (name === '@pandacss/preset-panda') {
return utils.omit(preset, ['theme.tokens.colors', 'theme.semanticTokens.colors'])
}
return preset
}
}
})
```
### Configuring JSX extraction
Use the `matchTag` / `matchTagProp` functions to customize the way Panda 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="panda.config.ts"
import { defineConfig } from '@pandacss/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/chakra-ui/panda/blob/main/sandbox/vite-ts/remove-unused-css-vars.ts) and
[remove-unused-keyframes](https://github.com/chakra-ui/panda/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 '@pandacss/dev'
export default defineConfig({
// ...
plugins: [
{
name: 'token-format',
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: path => '$' + path.join('-')
})
}
}
}
]
})
```
## Reference
```ts
export interface PandaHooks {
/**
* 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 Panda 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 Panda'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 `panda.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 `panda.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'
```
## 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, Panda 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
)
}
```
### cq (Container Query)
To make it easier to use container queries, we've added a new `cq` pattern to `@pandacss/preset-base`. It is used to
apply styles based on the width of the container.
The `cq` function accepts the following properties:
- `name`: The name of the container query, Maps to the
[`containerName` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/container-name).
- `type`: The type of the container query. Maps to the
[`containerType` CSS property](https://developer.mozilla.org/en-US/docs/Web/CSS/container-type). Defaults to
`inline-size`.
```ts
import { cq } from 'styled-system/patterns'
function Demo() {
return (
)
}
```
You can also named container queries:
```tsx
// 1 - Define container conditions
export default defineConfig({
// ...
theme: {
containerNames: ['sidebar', 'content'],
containerSizes: {
xs: '40em',
sm: '60em',
md: '80em'
}
}
})
```
```tsx
// 2 - Automatically generate container query pattern
import { cq } from 'styled-system/patterns'
function Demo() {
return (
)
}
```
Read more about container queries [here](/docs/concepts/conditional-styles#container-queries).
## Usage with JSX
To use the pattern in JSX, you need to set the `jsxFramework` property in the config. When this is set, Panda will emit
files for JSX elements based on the framework.
Every pattern can be used as a JSX element and imported from the `/jsx` entrypoint. By default, the pattern name is the
function name in PascalCase. You can override both the component name (with the `jsx` config property) and the element
rendered (with the `jsxElement` config property).
Learn more about pattern customization [here](/docs/customization/patterns).
```tsx
import { VStack, Center } from '../styled-system/jsx'
function App() {
return (
First
Second
Third
4
)
}
```
### Advanced JSX Tracking
We recommend that you use the pattern functions in most cases, in design systems there might be a need to compose
existing components to create new components.
To track the usage of the patterns in these cases, you'll need to add the `jsx` hint for the pattern config
```js {12} filename="button.pattern.ts"
import { definePattern } from '@pandacss/dev'
const scrollable = definePattern({
// ...
// Add the jsx hint to track the usage of the pattern in JSX, you can also use a regex to match multiple components
jsx: ['Scrollable', 'PageScrollable']
})
```
Then you can create a new component that uses the `PageScrollable` component and Panda will track the usage of the
`scrollable` pattern as well.
```tsx
const PageScrollable = (props: ButtonProps) => {
const { children, size } = props
return (
{children}
)
}
```
---
## Recipes
Panda provides a way to write CSS-in-JS with better performance, developer experience, and composability.
Recipes are a way to create multi-variant styles with a type-safe runtime API.
A recipe consists of four properties:
- `base`: The base styles for the component
- `variants`: The different visual styles for the component
- `compoundVariants`: The different combinations of variants for the component
- `defaultVariants`: The default variant values for the component
> **Credit:** This API was inspired by [Stitches](https://stitches.dev/),
> [Vanilla Extract](https://vanilla-extract.style/), and [Class Variance Authority](https://cva.style/).
[Comparison table between the different types of recipes here: "Should I use atomic or config recipes ?"](/docs/concepts/recipes#should-i-use-atomic-or-config-recipes-)
## Atomic Recipe (or cva)
Atomic recipes are a way to create multi-variant atomic styles with a type-safe runtime API.
They are defined using the `cva` function which was inspired by [Class Variance Authority](https://cva.style/). The
`cva` function which takes an object as its argument.
> **Note:** `cva` is not the same as [Class Variance Authority](https://cva.style/). The `cva` from Panda is a
> purpose-built function for creating atomic recipes that are connected to your design tokens and utilities.
### Defining the recipe
```jsx
import { cva } from '../styled-system/css'
const button = cva({
base: {
display: 'flex'
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' }
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' }
}
}
})
```
### Using the recipe
The returned value from the `cva` function is a function that can be used to apply the recipe to a component. Here's an
example of how to use the `button` recipe:
```jsx
import { button } from './button'
const Button = () => {
return
}
```
When a recipe is created, Panda will extract and generate CSS for every variant and compoundVariant `css` ahead of time,
as atomic classes.
```css
@layer utilities {
.d_flex {
display: flex;
}
.bg_red_200 {
background-color: #fed7d7;
}
.color_white {
color: #fff;
}
.border_width_1px {
border-width: 1px;
}
/* ... */
}
```
### Setting the default variants
The `defaultVariants` property is used to set the default variant values for the recipe. This is useful when you want to
apply a variant by default. Here's an example of how to use `defaultVariants`:
```jsx
import { cva } from '../styled-system/css'
const button = cva({
base: {
display: 'flex'
},
variants: {
visual: {
solid: { bg: 'red.200', color: 'white' },
outline: { borderWidth: '1px', borderColor: 'red.200' }
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '24px' }
}
},
defaultVariants: {
visual: 'solid',
size: 'lg'
}
})
```
### Compound Variants
Compound variants are a way to combine multiple variants together to create more complex sets of styles. They are
defined using the `compoundVariants` property , which takes an array of objects as its argument. Each object in the
array represents a set of conditions that must be met in order for the corresponding styles to be applied.
Here's an example of how to use `compoundVariants` in Panda:
```js
import { cva } from '../styled-system/css'
const button = cva({
base: {
padding: '8px 16px',
borderRadius: '4px',
fontSize: '16px',
fontWeight: 'bold'
},
variants: {
size: {
small: {
fontSize: '14px',
padding: '4px 8px'
},
medium: {
fontSize: '16px',
padding: '8px 16px'
},
large: {
fontSize: '18px',
padding: '12px 24px'
}
},
color: {
primary: {
backgroundColor: 'blue',
color: 'white'
},
secondary: {
backgroundColor: 'gray',
color: 'black'
}
},
disabled: {
true: {
opacity: 0.5,
cursor: 'not-allowed'
}
}
},
// compound variants
compoundVariants: [
// apply when both small size and primary color are selected
{
size: 'small',
color: 'primary',
css: {
border: '2px solid blue'
}
},
// apply when both large size and secondary color are selected and the button is disabled
{
size: 'large',
color: 'secondary',
disabled: true,
css: {
backgroundColor: 'lightgray',
color: 'darkgray',
border: 'none'
}
},
// apply when both small or medium size, and secondary color variants are applied
{
size: ['small', 'medium'],
color: 'secondary',
css: {
fontWeight: 'extrabold'
}
}
]
})
```
Here's an example usage of the `button` recipe:
```jsx
import { button } from './button'
const Button = () => {
// will apply size: small, color: primary, css: { border: '2px solid blue' }
return
}
```
Overall, using compound variants allows you to create more complex sets of styles that can be applied to your components
based on multiple conditions.
By combining simple variants together in this way, you can create a wide range of visual styles without cluttering up
your code with lots of conditional logic.
### TypeScript Guide
Panda provides a `RecipeVariantProps` type utility that can be used to infer the variant properties of a recipe.
This is useful when you want to use the recipe in JSX and want to get type safety for the variants.
```tsx
import { styled } from '../styled-system/jsx'
import { cva, type RecipeVariantProps } from '../styled-system/css'
const buttonStyle = cva({
base: {
color: 'red',
textAlign: 'center'
},
variants: {
size: {
small: {
fontSize: '1rem'
},
large: {
fontSize: '2rem'
}
}
}
})
export type ButtonVariants = RecipeVariantProps // { size?: 'small' | 'large' }
export const Button = styled('button', buttonStyle)
```
### Usage in JSX
You can create a JSX component from any existing atomic recipe by using the `styled` function from the `/jsx`
entrypoint.
The `styled` function takes the element type as its first argument, and the recipe as its second argument.
> Make sure to add the `jsxFramework` option to your `panda.config` file, and run `panda codegen` to generate the JSX
> entrypoint.
```js
import { cva } from '../styled-system/css'
import { styled } from '../styled-system/jsx'
const buttonStyle = cva({
base: {
color: 'red',
textAlign: 'center'
},
variants: {
size: {
small: {
fontSize: '1rem'
},
large: {
fontSize: '2rem'
}
}
}
})
const Button = styled('button', buttonStyle)
```
Then you can use the component in JSX
```jsx
```
## Config Recipe
Config recipes are extracted and generated just in time, this means regardless of the number of recipes in the config,
only the recipes and variants you use will exist in the generated CSS.
The config recipe takes the following additional properties:
- `className`: The name of the recipe. Used in the generated class name
- `jsx`: An array of JSX components that use the recipe. Defaults to the uppercase version of the recipe name
- `description`: An optional description of the recipe (used in the js-doc comments)
> As of v0.9, the `name` property is removed in favor of `className`
### Defining the recipe
To define a config recipe, import the `defineRecipe` helper function
```jsx filename="button.recipe.ts"
import { defineRecipe } from '@pandacss/dev'
export const buttonRecipe = defineRecipe({
className: 'button',
description: 'The styles for the Button component',
base: {
display: 'flex'
},
variants: {
visual: {
funky: { bg: 'red.200', color: 'white' },
edgy: { border: '1px solid {colors.red.500}' }
},
size: {
sm: { padding: '4', fontSize: '12px' },
lg: { padding: '8', fontSize: '40px' }
},
shape: {
square: { borderRadius: '0' },
circle: { borderRadius: 'full' }
}
},
defaultVariants: {
visual: 'funky',
size: 'sm',
shape: 'circle'
}
})
```
### Adding recipe to config
To add the recipe to the config, youβd need to add it to the `theme.recipes` object.
```jsx filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
import { buttonRecipe } from './button.recipe'
export default defineConfig({
//...
jsxFramework: 'react',
theme: {
extend: {
recipes: {
button: buttonRecipe
}
}
}
})
```
### Generate JS code
This generates a recipes folder the specified `outdir` which is `styled-system` by default. If Panda doesnβt
automatically generate your CSS file, you can run the `panda codegen` command.
You only need to import the recipes into the component files where you need to use them.
### Using the recipe
To use the recipe, you can import the recipe from the `/recipes` entrypoint and use it in your component. Panda
tracks the usage of the recipe and only generates CSS of the variants used in your application.
```js
import { button } from '../styled-system/recipes'
function App() {
return (
)
}
```
The generated css is registered under the `recipe` [cascade layer](/docs/concepts/cascade-layers.mdx) with the class
name that matches the recipe-variant name pattern `--`.
> **Technical Notes π:** Only the recipe and variants used in your application are generated. Not more!
```css
@layer recipes {
@layer base {
.button {
font-size: var(--font-sizes-lg);
}
}
.button--visual-funky {
background-color: var(--colors-red-200);
color: var(--colors-white);
}
.button--size-lg {
padding: var(--space-8);
font-size: var(--font-sizes-40px);
}
}
```
### Responsive and Conditional variants
Recipes created in the config have a **special** feature; they can be applied based on a specific breakpoints or
conditions.
Here's how to tweak the size variant of the button recipe based on breakpoints.
```jsx
import { button } from '../styled-system/recipes'
function App() {
return (
)
}
```
> In most cases, we don't recommend applying conditional variants inline. Ideally, you might want to render different
> views for your responsive breakpoints.
### TypeScript Guide
Every recipe ships a type interface for its accepted variants. You can import them from the `styled-system/recipes`
entrypoint.
For the button recipe, we can import the `ButtonVariants` type like so:
```ts
import React from 'react'
import type { ButtonVariants } from '../styled-system/recipes'
type ButtonProps = ButtonVariants & {
children: React.ReactNode
}
```
### Usage in JSX
Layer recipes can be consumed directly in your custom JSX components. Panda will automatically track the usage of the
recipe if the component name matches the recipe name.
For example, if your recipe is called `button` and you create a `Button` component from it, Panda will automatically
track the usage of the variant properties.
```tsx
import React from 'react'
import { button, type ButtonVariants } from '../styled-system/recipes'
type ButtonProps = ButtonVariants & {
children: React.ReactNode
}
const Button = (props: ButtonProps) => {
const { children, size } = props
return (
)
}
const App = () => {
return (
)
}
```
### Advanced JSX Tracking
We recommend that you use the recipe functions in most cases, in design systems there might be a need to compose
existing components (like Button) to create new components.
To track the usage of the recipes in these cases, you'll need to add the `jsx` hint for the recipe config
```js {12} filename="button.recipe.ts"
import { defineRecipe } from '@pandacss/dev'
const button = defineRecipe({
base: {
color: 'red',
fontSize: '1.5rem'
},
variants: {
// ...
},
// Add the jsx hint to track the usage of the recipe in JSX, you can use regex to match multiple components
jsx: ['Button', 'PageButton']
})
```
Then you can create a new component that uses the `Button` component and Panda will track the usage of the `button`
recipe as well.
```tsx
const PageButton = (props: ButtonProps) => {
const { children, size } = props
return (
)
}
```
#### Extending a preset recipe
If you're using a recipe from a preset, you can still extend it in your config.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
//...
jsxFramework: 'react',
theme: {
extend: {
recipes: {
button: {
className: 'something-else', // π override the className
base: {
color: 'red', // π replace some part of the recipe
fontSize: '1.5rem' // or add new styles
},
variants: {
// ... // π add or extend new variants
},
jsx: ['Button', 'PageButton'] // π extend the jsx tracking hint
}
}
}
}
})
```
Learn more about the [extend](/docs/concepts/extend.md) keyword.
## Methods and Properties
Both atomic and config recipe ships a helper methods and properties that can be used to get information about the
recipe.
- `variantKeys`: An array of the recipe variant keys
- `variantMap`: An object of the recipe variant keys and their values
- `splitVariantProps`: A function that takes an object as its argument and returns an array containing the recipe
variant props and the rest of the props
```js
import { cva } from '../styled-system/css'
const buttonRecipe = cva({
base: {
color: 'red',
fontSize: '1.5rem'
},
variants: {
size: {
sm: {
fontSize: '1rem'
},
md: {
fontSize: '2rem'
}
}
}
})
buttonRecipe.variantKeys
// => ['size']
buttonRecipe.variantMap
// => { size: ['sm', 'md'] }
buttonRecipe.splitVariantProps({ size: 'sm', onClick() {} })
// => [{ size: 'sm'}, { onClick() {} }]
```
These methods and properties are useful when creating custom components or writing Storybook stories for your recipes.
Here's a Storybook example.
```tsx filename="button.stories.tsx"
import { Button, buttonRecipe } from './components/button'
export default {
title: 'Button',
component: Button,
argTypes: {
size: {
control: {
type: 'select',
options: buttonRecipe.variantMap.size
}
}
}
}
export const Demo = {
render: args =>
}
```
## Best Practices
- Leverage css variables in the base styles as much as possible. Makes it easier to theme the component with JS
- Don't mix styles by writing complex selectors. Separate concerns and group them in logical variants
- Use the `compoundVariants` property to create more complex sets of styles
## Limitations
- Recipes created from `cva` cannot have responsive or conditional values. Only layer recipes can have responsive or
conditional values.
- Due to static nature of Panda, it's not possible to track the usage of the recipes in all cases. Here are some of use
cases that Panda won't be able to track the usage of the recipe variants:
**When you change the name of the variant prop in the JSX component**
In below example, the `size` prop is renamed to `buttonSize`
```tsx
const Button = ({ buttonSize, children }) => {
return (
)
}
```
**When you use the recipe in a custom component that is not named as per the recipe name, Panda won't be able to track
the usage of the recipe variants.**
In below example, the component name `Button` is renamed to `Random` and we are using `button` recipe.
```tsx
const Random = ({ size, children }) => {
return (
)
}
```
- When using `compoundVariants` in the recipe, you're not able to use responsive values in the variants.
```tsx
const button = defineRecipe({
base: {
color: 'red',
fontSize: '1.5rem'
},
variants: {
size: {
sm: {
fontSize: '1rem'
},
md: {
fontSize: '2rem'
}
}
},
// this will disable responsive values for the variants
compoundVariants: [
{
size: 'sm',
visual: 'funky',
css: {
color: 'blue'
}
},
{
size: 'md',
visual: 'funky',
css: {
color: 'green'
}
}
]
})
```
## Static CSS
Panda provides a way to generate `static CSS` for your recipes. This is useful when you want to generate CSS for a
recipe without using the recipe in your code or if you use dynamic styling that Panda can't keep track of.
More information about static CSS can be found [here](/docs/guides/static.md#generating-recipes).
## 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-or-cva) (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 panda 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.
| | Config recipe | Atomic recipe (cva) |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Can both use any theme tokens, utilities or conditions | β yes | β yes |
| Are generated just in time (JIT) based on usage | β yes, only the recipe variants found in your code will be generated | β no, all variants found in your `cva` recipes will always be generated |
| Can be shared in a preset | β yes, you can include it in your `preset.theme.recipes` | β no |
| Can be applied responsively | β yes, `button({ size: { base: 'sm', md: 'lg' } })` | β no, only the styles in the recipe can be responsive |
| Can be colocated in your markup code | β no, they must be defined or imported in your `panda.config` | β yes, you can place it anywhere in your app |
| Generate atomic classes | β no, a specific className will be generated using your `recipe.className` | β yes |
| Can be composed/merged at runtime | β no, a specific className will be generated using your `recipe.className`, [you need to use `cx` to add each recipe classes](https://panda-css.com/docs/concepts/merging-styles#merging-config-recipe-and-style-object) | β [yes, you can use the `.raw` function (ex: `button.raw({ size: "md" })`) to get the atomic style object and merge them all in a `css(xxx, yyy, zzz)` call](/docs/concepts/merging-styles#merging-cva--css-styles) |
---
## Responsive Design
How to write mobile responsive designs in your CSS in Panda
Responsive design is a fundamental aspect of modern web development, allowing websites and applications to adapt
seamlessly to different screen sizes and devices.
Panda provides a comprehensive set of responsive utilities and features to facilitate the creation of responsive
layouts. It lets you do this through conditional styles for different breakpoints.
Let's say you want to change the font weight of a text on large screens, you can do it like this:
```jsx
Text
```
> Panda uses a mobile-first breakpoint system and leverages min-width media queries `@media(min-width)` when you write
> responsive styles.
Panda provides five breakpoints by default:
```ts
const breakpoints = {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px'
}
```
## Overview
### Property based modifier
Panda allows you apply the responsive condition directly to a style property, resulting in a more concise syntax:
```diff
Text
```
### The Array syntax
Panda also accepts arrays as values for responsive styles. Pass the corresponding value for each breakpoint in the
array. Using our previous code as an example:
```jsx
Text
```
> We're leaving the corresponding values of the unused breakpoints `md` and `lg` as undefined.
### Targeting a breakpoint range
By default, styles assigned to a specific breakpoint will be effective at that breakpoint and will persist as applied
styles at larger breakpoints.
If you wish to apply a utility exclusively when a particular range of breakpoints is active, Panda offers properties
that restrict the style to that specific range. To construct the property, combine the minimum and maximum breakpoints
using the "To" notation in camelCase format.
Let's say we want to apply styles between the `md` and `xl` breakpoints, we use the `mdToXl` property:
```jsx
Text
```
> This text will only be bold in `md`, `lg` and `xl` breakpoints.
### Targeting a single breakpoint
To target a single breakpoint, you can easily achieve this by simply adding the suffix "Only" to the breakpoint name in
camelCase format.
Let's say we want to apply styles only in the `lg` breakpoint, we use the `lgOnly` property:
```jsx
Text
```
### Customizing Breakpoints
When encountering certain scenarios, it may become necessary to establish custom breakpoints tailored to your
application's needs. It is advisable to utilize commonly used aliases such as `sm`, `md`, `lg`, and `xl` for this
purpose.
In order to define custom breakpoints, you can easily accomplish this by passing them as an object within your Panda
config.
> Note: Make sure that the CSS units of your breakpoints are consistent. Use either all pixels (`px`) or all `em`, but
> do not mix them.
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
theme: {
extend: {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px'
}
}
}
})
```
### Hiding elements by breakpoint
If you need to limit the visibility of an element to any breakpoint, Panda provides
[display utilities](/docs/utilities/display) to help you achieve this.
---
## Slot Recipes
Learn how to style multiple parts components with slot recipes.
When using `cva` or `defineRecipe` might be enough for simple cases, slot recipes are a better fit for more complex
cases.
A slot recipe consists of these properties:
- `slots`: An array of component parts to style
- `base`: The base styles per slot
- `variants`: The different visual styles for each slot
- `defaultVariants`: The default variant for the component
- `compoundVariants`: The compound variant combination and style overrides for each slot.
> **Credit:** This API was inspired by multipart components in
> [Chakra UI](https://chakra-ui.com/docs/styled-system/component-style) and slot variants in
> [Tailwind Variants](https://tailwind-variants.org)
[See the comparison table between atomic recipes (`cva`) and `config recipes` here.](/docs/concepts/recipes#should-i-use-atomic-or-config-recipes-)
The same comparison applies to `sva` and `slot recipes`.
## Atomic Slot Recipe (or sva)
The `sva` function is a shorthand for creating a slot recipe with atomic variants. It takes the same arguments as `cva`
but returns a slot recipe instead.
### Defining the Recipe
```jsx filename="checkbox.recipe.ts"
import { sva } from '../styled-system/css'
const checkbox = sva({
slots: ['root', 'control', 'label'],
base: {
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
},
variants: {
size: {
sm: {
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
},
md: {
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
}
}
},
defaultVariants: {
size: 'sm'
}
})
```
### Using the recipe
The returned value from `sva` is a function that can be used to apply the recipe for each component part. Here's an
example of how to use the `checkbox` recipe:
```jsx filename="Checkbox.tsx"
import { css } from '../styled-system/css'
import { checkbox } from './checkbox.recipe'
const Checkbox = () => {
const classes = checkbox({ size: 'sm' })
return (
)
}
```
When a slot recipe is created, Panda will pre-generate the css of all the possible combinations of variants and compound
variants as atomic classes.
```css
@layer utilities {
.border_width_1px {
border-width: 1px;
}
.rounded_sm {
border-radius: var(--radii-sm);
}
.margin_start_2 {
margin-inline-start: var(--spacing-2);
}
.w_8 {
width: var(--sizing-8);
}
.h_8 {
height: var(--sizing-8);
}
.font_size_sm {
font-size: var(--fontSizes-sm);
}
.w_10 {
width: var(--sizing-10);
}
.h_10 {
height: var(--sizing-10);
}
.font_size_md {
font-size: var(--fontSizes-md);
}
/* ... */
}
```
### Compound Variants
Compound variants are a way to apply style overrides to a slot based on the combination of variants.
Let's say you want to apply a different border color to the checkbox control based on its `size` and the `isChecked`
variant, here's how to do it:
```jsx filename="checkbox.recipe.ts" {14-22}
import { sva } from '../styled-system/css'
const checkbox = sva({
slots: ['root', 'control', 'label'],
base: {...},
variants: {
size: {
sm: {...},
md: {...}
},
isChecked: {
true: { control: {}, label: {} }
}
},
compoundVariants: [
{
size: 'sm',
isChecked: true,
css: {
control: { borderColor: 'green.500' }
}
}
],
defaultVariants: {...}
})
```
### Targeting slots
You can set an optional `className` property in the `sva` config which can be used to target slots in the DOM.
> Each slot will contain a `${className}__${slotName}` class in addition to the atomic styles.
Let's say you want to apply a different border color to the button text directly from the `root` slot. Here's how you
would do it:
```tsx
import { sva } from '../styled-system/css'
const button = sva({
className: 'btn',
slots: ['root', 'text'],
base: {
root: {
bg: 'blue.500',
_hover: {
// v--- π― this will target the `text` slot
'& .btn__text': {
color: 'white'
}
}
}
}
})
```
> Note: This doesn't work when you have the `hash: true` option in your panda config. We recommend using `data-x`
> selectors to target slots.
### TypeScript Guide
Panda provides a `RecipeVariantProps` type utility that can be used to infer the variant properties of a slot recipe.
This is useful when you want to use the recipe in JSX and want to get type safety for the variants.
```tsx
import { sva, type RecipeVariantProps } from '../styled-system/css'
const checkbox = sva({...})
export type CheckboxVariants = RecipeVariantProps
// => { size?: 'sm' | 'md', isChecked?: boolean }
```
### Usage in JSX
Unlike the atomic recipe or `cva`, slot recipes are not meant to be used directly in the `styled` factory since it
returns an object of classes instead of a single class.
```jsx
import { css } from '../styled-system/css'
import { styled } from '../styled-system/jsx'
import { checkbox, type CheckboxVariants } from './checkbox.recipe'
// β Won't work
const Checkbox = styled('label', checkbox)
// β Works
const Checkbox = (props: CheckboxVariants) => {
const classes = checkbox(props)
return (
)
}
```
### Styling JSX Compound Components
Compound components are a great way to create reusable components for better composition. Slot recipes play nicely with
this pattern and requires a context provider for the component.
> **Note:** This is an advanced topic and you don't need to understand it to use slot recipes. If you use React, be
> aware that context require adding 'use client' to the top of the file.
Let's say you want to design a Checkbox component that can be used like this:
```jsx
Checkbox Label
```
First, create a shared context for ths styles
```jsx filename="style-context.tsx"
'use client'
import { createContext, forwardRef, useContext } from 'react'
export const createStyleContext = recipe => {
const StyleContext = createContext(null)
const withProvider = (Component, part) => {
const Comp = forwardRef((props, ref) => {
const [variantProps, rest] = recipe.splitVariantProps(props)
const styles = recipe(variantProps)
return (
)
})
Comp.displayName = Component.displayName || Component.name
return Comp
}
const withContext = (Component, part) => {
if (!part) return Component
const Comp = forwardRef((props, ref) => {
const styles = useContext(StyleContext)
return
})
Comp.displayName = Component.displayName || Component.name
return Comp
}
return { withProvider, withContext }
}
```
> Note: For the TypeScript version of this file, refer to
> [create-style-context.tsx](https://github.com/cschroeter/park-ui/blob/main/website/src/lib/create-style-context.tsx)
> in Park UI
Then, use the context to create compound components connected to the recipe
```jsx filename="Checkbox.tsx"
import { createStyleContext } from './style-context'
import { checkbox } from './checkbox.recipe'
const { withProvider, withContext } = createStyleContext(checkbox)
// ππ» points to the root slot
const Root = withProvider('label', 'root')
// ππ» points to the control slot
const Control = withContext('div', 'control')
// ππ» points to the label slot
const Label = withContext('span', 'label')
const Checkbox = { Root, Control, Label }
```
## Config Slot Recipe
Config slot recipes are very similar atomic recipes except that they use well-defined classNames and store the styles in
the `recipes` cascade layer.
The config slot recipe takes the following additional properties:
- `className`: The name of the recipe. Used in the generated class name
- `jsx`: An array of JSX components that use the recipe. Defaults to the uppercase version of the recipe name
- `description`: An optional description of the recipe (used in the js-doc comments)
### Defining the recipe
To define a config slot recipe, import the `defineSlotRecipe` function
```jsx filename="checkbox.recipe.ts"
import { defineSlotRecipe } from '@pandacss/dev'
export const checkboxRecipe = defineSlotRecipe({
className: 'checkbox',
description: 'The styles for the Checkbox component',
slots: ['root', 'control', 'label'],
base: {
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
},
variants: {
size: {
sm: {
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
},
md: {
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
}
}
},
defaultVariants: {
size: 'sm'
}
})
```
### Adding recipe to config
To add the recipe to the config, youβd need to add it to the `slotRecipes` property of the `theme`
```jsx filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
import { checkboxRecipe } from './checkbox.recipe'
export default defineConfig({
//...
jsxFramework: 'react',
theme: {
extend: {
slotRecipes: {
checkbox: checkboxRecipe
}
}
}
})
```
### Generate JS code
This generates a recipes folder the specified `outdir` which is `styled-system` by default. If Panda doesnβt
automatically generate your CSS file, you can run the `panda codegen` command.
You only need to import the recipes into the component files where you need to use them.
### Using the recipe
To use the recipe, you can import the recipe from the `/recipes` entrypoint and use it in your component. Panda
tracks the usage of the recipe and only generates CSS of the variants used in your application.
```js
import { css } from '../styled-system/css'
import { checkbox } from '../styled-system/recipes'
const Checkbox = () => {
const classes = checkbox({ size: 'sm' })
return (
)
}
```
The generated css is registered under the `recipe` [cascade layer](/docs/concepts/cascade-layers.mdx) with the class
name that matches the recipe-slot-variant name pattern `__--`.
```css
@layer recipes {
@layer base {
.checkbox__root {
display: flex;
align-items: center;
gap: var(--space-2);
}
.checkbox__control {
border-width: var(--border-widths-1px);
border-radius: var(--radii-sm);
}
.checkbox__label {
margin-start: var(--space-2);
}
}
.checkbox__control--size-sm {
width: var(--space-8);
height: var(--space-8);
}
.checkbox__label--size-sm {
font-size: var(--font-sizes-sm);
}
.checkbox__control--size-md {
width: var(--space-10);
height: var(--space-10);
}
.checkbox__label--size-md {
font-size: var(--font-sizes-md);
}
}
```
### TypeScript Guide
Every slot recipe ships a type interface for its accepted variants. You can import them from the `styled-system/recipes`
entrypoint.
For the checkbox recipe, we can import the `CheckboxVariants` type like so:
```ts
import React from 'react'
import type { CheckboxVariants } from '../styled-system/recipes'
type CheckboxProps = CheckboxVariants & {
children: React.ReactNode
value?: string
onChange?: (value: string) => void
}
```
### `defineParts`
It can be useful when you want to have the equivalent of a slot recipe without needing to split the class names bindings
and instead just having a className that handles children on 1 DOM element.
It pairs well with [ZagJs](https://zagjs.com/) and [Ark-UI](https://ark-ui.com/)
Let's refactor the previous example to use parts instead of slots:
```ts
import { defineParts, definetRecipe } from '@pandacss/dev'
const parts = defineParts({
root: { selector: '& [data-part="root"]' },
control: { selector: '& [data-part="control"]' },
label: { selector: '& [data-part="label"]' }
})
export const checkboxRecipe = defineRecipe({
className: 'checkbox',
description: 'A checkbox style',
base: parts({
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
}),
variants: {
size: {
sm: parts({
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
}),
md: parts({
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
})
}
},
defaultVariants: {
size: 'sm'
}
})
```
---
## Style props
Build UIs quickly by passing css properties as "props" to your components.
While you can get very far by using the `className` prop and function from Panda, style props provide a more ergonomic
way of expressing styles.
Panda will extract the style props through static analysis and generate the CSS at build time.
> If you use Chakra UI, Styled System, or Theme UI, you'll feel right at home right away π
```jsx
import { css } from '../styled-system/css'
import { styled } from '../styled-system/jsx'
// The className approach
const Button = ({ children }) => (
)
// The style props approach
const Button = ({ children }) => (
{children}
)
```
## Configure JSX
Using JSX style props is turned off by default in Panda, but you can opt-in to this feature by using the `jsxFramework`
property in the panda config.
> β οΈ Panda will not extract style props from JSX elements if you don't set the `jsxFramework` property. This is to avoid
> unnecessary work for projects that don't use JSX.
### Choose Framework
JSX is a JavaScript syntax extension that allows you to write HTML-like code directly within your JavaScript code and is
supported by most popular frameworks. Panda supports JSX style props in React, Preact, Vue 3, Qwik and Solid.js.
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
jsxFramework: 'react'
})
```
### Generate JSX runtime
Next, you need to run `panda codegen` to generate the JSX runtime for your framework.
{/* */}
```bash
pnpm panda codegen --clean
```
```bash
npm panda codegen --clean
```
```bash
yarn panda codegen --clean
```
```bash
bun panda codegen --clean
```
{/* */}
That's it! You can now use JSX style props in your components.
## Using Style Props
### JSX Element
Style props are just CSS properties that you can pass to your components as props. With the JSX runtime, you can use
`styled.` syntax to create supercharged JSX elements that support style props.
```jsx
import { styled } from '../styled-system/jsx'
const Button = ({ children }) => (
{children}
)
```
### 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 (
)
}
// ...
const App = () => {
return (
// In this case, you should keep the `size` naming
)
}
```
The same principles apply to all style props, recipe variants, and pattern props.
If you still need to rename properties at runtime, you can use `config.staticCss` as an escape-hatch to pre-generate
the CSS anyway for the properties you need.
### Recipe
You can use recipe variants as JSX props to quickly change the styles of your components, as long as
[you're tracking those components in your recipe config](/docs/concepts/recipes#advanced-jsx-tracking).
```tsx
import { styled } from '../styled-system/jsx'
import { button, type ButtonVariantProps } from '../styled-system/recipes'
const Button = (props: ButtonVariantProps) =>
const App = () =>
```
## Factory Function
You can also use the `styled` function to create a styled component from any component or JSX intrinsic element (like
"a", "button").
```jsx
import { styled } from '../styled-system/jsx'
import { Button } from 'component-library'
const StyledButton = styled(Button)
const App = () => (
Button
)
```
> You can configure the `styled` function name using the [`config.jsxFactory`](/docs/references/config#jsxfactory)
> option.
### Factory Recipe
You can define a recipe for your component using the `styled` function. This is useful when you want to create a
component that has a specific set of style props.
```jsx
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
base: {
py: '2',
px: '4',
rounded: 'md'
},
variants: {
variant: {
primary: {
bg: 'blue.500',
color: 'white'
},
secondary: {
bg: 'gray.500',
color: 'white'
}
}
}
})
const App = () => (
)
```
### Factory Options
There's a few options you can pass to the `styled` function to customize the behavior of the generated component.
```ts
interface FactoryOptions {
dataAttr?: boolean
defaultProps?: TProps
shouldForwardProp?(prop: string, variantKeys: string[]): boolean
}
```
#### `dataAttr`
Setting `dataAttr` to true will add a `data-recipe="{recipeName}"` attribute to the element with the recipe name. This
is useful for testing and debugging.
```jsx
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button, { dataAttr: true })
const App = () =>
// =>
```
#### `defaultProps`
allows you to skip writing wrapper components just to set a few props. It also allows you to locall override the default
variants or base styles of a recipe.
```jsx
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button, {
defaultProps: {
variant: 'secondary',
px: '10px'
}
})
const App = () =>
// =>
```
#### `shouldForwardProp`
Used to customize which props are forwarded to the underlying element. By default, all props except recipe variants and
style props are forwarded.
For example, you could use it to integrate with [Framer Motion](https://www.framer.com/motion/).
```jsx
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
import { motion, isValidMotionProp } from 'framer-motion'
const StyledMotion = styled(
motion.div,
{},
{
shouldForwardProp: (prop, variantKeys) =>
isValidMotionProp(prop) || (!variantKeys.includes(prop) && !isCssProperty(prop))
}
)
```
### Unstyled prop
All styled components accept an `unstyled` prop that allows you to disable the recipe styles. This is useful when you
want to use a component's structure but apply completely custom styling.
```jsx
import { styled } from '../styled-system/jsx'
import { button } from '../styled-system/recipes'
const Button = styled('button', button)
const App = () => (
<>
{/* With recipe styles */}
{/* Without recipe styles, but inline styles still work */}
>
)
```
### Reducing the allowed style props
You can reduce the allowed JSX properties on the factory using
[`config.jsxStyleProps`](/docs/references/config#jsxstyleprops):
- When set to 'all', all style props are allowed.
- When set to 'minimal', only the `css` prop is allowed.
- When set to 'none', no style props are allowed and therefore the `jsxFactory` will not be usable as a component:
- `` and `styled("div")` aren't valid
- but the recipe usage is still valid `styled("div", { base: { color: "red.300" }, variants: { ...} })`
> Removing style props (from `all` to either `minimal` or `none`) will reduce the size of the generated code due to not
> having to check which props are style props at runtime.
## JSX Patterns
Patterns are common layout patterns like `stack`, `grid`, `circle` that can be used to speed up your css. Think of them
as a way to avoid repetitive layout styles.
All the patterns provided by Panda are available as JSX components.
> Learn more about the [patterns](/docs/customization/patterns) we provide.
```jsx
import { Stack, Circle } from '../styled-system/jsx'
const App = () => (
4
)
```
## Making your own styled components
To make a custom JSX component that accepts style props, Use the `splitCssProps` function to split style props from
other component props.
> For this to work correctly, set the `jsxFramework` to the framework you're using in your panda config.
```tsx
import { splitCssProps } from '../styled-system/jsx'
import type { HTMLStyledProps } from '../styled-system/types'
export function Component(props: HTMLStyledProps<'div'>) {
const [cssProps, restProps] = splitCssProps(props)
const { css: cssProp, ...styleProps } = cssProps
const className = css({ display: 'flex', height: '20', width: '20' }, styleProps, cssProp)
return
}
// Usage
function App() {
return Click me
}
```
## TypeScript
Panda provides type definitions for all the style props that are supported by the JSX runtime.
You can use these types to get type safety in your components.
### Style Object
Use the `JsxStyleProps` to get the types of the style object that is compatible with JSX elements.
```tsx
import { styled } from '../styled-system/jsx'
import type { JsxStyleProps } from '../styled-system/types'
interface ButtonProps {
color?: JsxStyleProps['color']
}
const Button = (props: ButtonProps) => {
return
}
```
### Style Props
Use the `HTMLStyledProps` type to get the types of an element in addition to the style props.
```tsx {2}
import { styled } from '../styled-system/jsx'
import type { HTMLStyledProps } from '../styled-system/jsx'
type ButtonProps = HTMLStyledProps<'button'>
const Button = (props: ButtonProps) => {
return
}
```
### Variant Props
Use the `StyledVariantProps` type to extract the variants from a styled component.
```tsx {2}
import { styled } from '../styled-system/jsx'
import type { StyledVariantProps } from '../styled-system/jsx'
const Button = styled('button', {
base: { color: 'black' },
variants: {
state: {
error: { color: 'red' },
success: { color: 'green' }
}
}
})
type ButtonVariantProps = StyledVariantProps
// ^ { state?: 'error' | 'success' | undefined }
```
### Patterns
Every pattern provided by Panda has a corresponding type that you can use to get type safety in your components.
```tsx {2}
import { Stack } from '../styled-system/jsx'
import type { StackProps } from '../styled-system/jsx'
```
---
## Styled System
What is the styled-system folder and how does it work?
While Panda generates your CSS at **build-time** using static extraction, we still need a lightweight runtime to
transform the CSS-in-JS syntax (either [`object`](/docs/concepts/writing-styles#atomic-styles) or
[`template-literal`](/docs/concepts/template-literals)) to class names strings. This is where the `styled-system` folder
comes in.
When running the `panda` or `panda codegen` commands, the [`config.outdir`](/docs/references/config#outdir) will be used
as output path to generate the `styled-system` in.
This is the core of what the `styled-system` does:
```ts
css({ color: 'blue.300' }) // => "text_blue_300"
```
Since Panda doesn't rely on any bundler's (`vite`, `webpack`, etc) plugin, there is no code transformation happening to
convert the CSS-in-JS syntax to class names at compile-time. This is why we need a lightweight runtime to do that.
The same principles applies to `patterns`, `recipes` and even `jsx` components, as they all use the `css` function under
the hood.
If you look inside your `styled-system` folder, you should see the main entrypoints for the runtime:
Feel free to explore the files inside the `styled-system` folder to get a better understanding of how it works in
details!
> Note: The `styled-system` folder is not meant to be edited manually. It is generated by Panda and should be treated as
> a build artifact. This also means you don't need to commit it to your repository.
## How does it work?
When running the `panda` command or with the postcss plugin, here's what's happening under the hood:
1. **Load Panda context**:
- Find and evaluate app config, merge result with presets.
- Create panda context: prepare code generator from config, parse user's file as AST.
2. **Generating artifacts**:
- Write lightweight JS runtime and types to output directory
3. **Extracting used styles in app code**:
- Run parser on each user's file: identify and extract styles, compute CSS, write to styles.css.
That `2. Generating artifacts` step is where the `styled-system` folder is generated, using the resolved config that
contains all your tokens, patterns, recipes, utilities etc. We generate a tailored runtime for your app, so that it only
contains enough code (and types!) to support the styles you're using.
## Pre-rendering
If you use some way to pre-render your components to static HTML, for example using Astro or RSC, the `styled-system`
functions like `css` and others will be removed at build-time and replaced by the generated class names, so that you
don't have to ship the runtime to your users.
---
## Template Literals
Panda allows you to write styles using template literals.
Writing styles using template literals provides a similar experience to
[styled-components](https://styled-components.com/) and [emotion](https://emotion.sh/), except that Panda generates
atomic class names instead of a single unique class name.
> Emitting atomic class names allows Panda to generate smaller CSS bundles.
Panda provides two functions to write template literal styles: `css` and `styled`.
## Getting started
To use template literals, you need to set the `syntax` option in your `panda.config.ts` file to `templateLiteral`:
```ts
// panda.config.ts
export default defineConfig({
// ...
syntax: 'template-literal', // required
jsxFramework: 'react' // optional
})
```
Then run the codegen command to generate the functions:
```sh
panda codegen --clean
```
## The `css` function
This the basic way of writing template styles. It converts the template literal into a set of atomic class name which
you can pass to the `className` prop of an element.
```js
import { css } from '../styled-system/css'
const className = css`
font-size: 16px;
font-weight: bold;
`
function Heading() {
return
This is a title
}
// =>
```
Here's what the emitted atomic CSS looks like:
```css
.font-size_16px {
font-size: 16px;
}
.font-weight_bold {
font-weight: bold;
}
```
## The `styled` tag
The `styled` tag allows you to create a component with encapsulated styles. It's similar to the `styled-components` or
`emotion` library.
```js
import { styled } from '../styled-system/jsx'
// Create a styled component
const Heading = styled.h1`
font-size: 16px;
font-weight: bold;
`
function Demo() {
// Use the styled component
return This is a title
}
// =>
This is a title
```
Here's what the emitted atomic CSS looks like:
```css
.font-size_16px {
font-size: 16px;
}
.font-weight_bold {
font-weight: bold;
}
```
## Nested styles
You can nest selectors, pseudo-elements and pseudo-selectors.
```js
const Button = styled.button`
color: black;
&:hover {
color: blue;
}
`
```
Using css nesting syntax, pseudo-elements, pseudo-selectors and combinators are also supported:
```js
const Demo = styled.div`
color: black;
&::after {
content: 'πΌ';
}
& + & {
background: yellow;
}
&.bordered {
border: 1px solid black;
}
.parent & {
color: red;
}
`
```
Nested media and container queries are also supported:
```js
const Demo = styled.div`
color: black;
@media (min-width: 200px) {
color: blue;
}
@container (min-width: 200px) {
color: red;
}
`
```
## Hashing class names
In some cases, it might be useful to shorten the class names by hashing them. Set the `hash: true` option in your
`panda.config.ts` file to enable this. This will generate shorter class names but will make it harder to debug.
To achieve this, set the `hash` option in your `panda.config.ts` file to `true`:
```ts
// panda.config.ts
export default defineConfig({
// ...
hash: true // optional
})
```
> Run the `codegen` command to regenerate the functions with hashing enabled.
When hashing is enabled, the class names will go from this:
```css
.font-size_16px {
font-size: 16px;
}
.font-weight_bold {
font-weight: bold;
}
```
To a unique six character hash regardless of the length of the selector or the number of declarations:
```css
.adfg5r {
font-size: 16px;
}
.bsdf35 {
font-weight: bold;
}
```
## Using tokens
Use the `token()` function or `{}` syntax in your template literals to reference design tokens in your styles. Panda
will automatically generate the corresponding CSS variables.
```js
import { css } from '../styled-system/css'
const className = css`
font-size: {fontSizes.md};
font-weight: token(fontWeights.bold, 700);
`
```
## Caveats
The object literal syntax is the recommended way of writing styles. But, if you stick with the template literal syntax,
there are some caveats to be aware of:
- Patterns and recipes are not generated
- Dynamic interpolation or component targeting is not supported
- Lack of autocompletion for tokens within the template literal Our
[Eslint plugin](https://github.com/chakra-ui/eslint-plugin-panda/blob/main/docs/rules/no-invalid-token-paths.md) can
help you overcome this by detecting invalid tokens
- JSX Style props are not supported
---
## Virtual Color
Panda allows you to create a virtual color or color placeholder in your project.
The `colorPalette` property is how you create virtual colors.
```js
import { css } from '../styled-system/css'
const className = css({
colorPalette: 'blue',
bg: 'colorPalette.100',
_hover: {
bg: 'colorPalette.200'
}
})
```
This will translate to the `blue.100` background color and `blue.200` background color on hover.
Virtual colors are useful when creating easily customizable components.
## Using with recipes
You can also use virtual colors with recipes.
```js
import { css, cva, cx } from '../styled-system/css'
const button = cva({
base: {
padding: 4
// you can also specify a default colorPalette in the `base` recipe key
// colorPalette: 'blue',
// ^^^^^^^^^^^^^^^^^^^^
},
variants: {
variant: {
primary: { color: 'colorPalette.500' }
}
},
defaultVariants: { variant: 'primary' }
})
```
## Using with different color modes
You can also use virtual colors with different conditions, such as color modes.
```js
import { css, cva, cx } from '../styled-system/css'
const someButton = cva({
base: { padding: 4 },
variants: {
variant: {
primary: {
bg: { base: 'colorPalette.500', _dark: 'colorPalette.200' },
color: { base: 'white', _dark: 'gray.900' }
}
}
},
defaultVariants: { variant: 'primary' }
})
export const App = () => {
return (
<>
>
)
}
```
## Semantic Virtual Colors
Semantic virtual colors gives you an ability to create a virtual color organized by category, variant and state.
Hierarchically organized virtual colors are useful when creating easily customizable components.
```js
const theme = {
extend: {
semanticTokens: {
colors: {
button: {
dark: {
value: 'navy'
},
light: {
DEFAULT: {
value: 'skyblue'
},
accent: {
DEFAULT: {
value: 'cyan'
},
secondary: {
value: 'blue'
}
}
}
}
}
}
}
}
```
You can now use the root `button` color palette and its values directly:
```tsx
import { css } from '../styled-system/css'
export const App = () => {
return (
)
}
```
Or you can use any deeply nested property (e.g. `button.light.accent`) as a root color palette:
```tsx
import { css } from '../styled-system/css'
export const App = () => {
return (
)
}
```
## Pregenerated Virtual Colors
Use the `staticCss` option in the config to pre-generate values for the `colorPalette` property.
This is useful when you want to use a color palette that can be changed at runtime (e.g. in Storybook knobs).
> Learn more about [static css generation](/docs/guides/static).
```tsx
export default defineConfig({
staticCss: {
css: [
{
properties: { colorPalette: ['red', 'blue'] }
}
]
}
})
```
Then in your code, you can design components that use the `colorPalette` property:
```tsx
import { css } from '../styled-system/css'
function ButtonShowcase() {
const [colorPalette, setColorPalette] = useState('red')
return (
)
}
```
---
## Writing Styles
Panda generates the utilities you need to style your components with confidence.
Using the object syntax is a fundamental approach to writing styles in Panda. It not only provides a type-safe style
authoring experience, but also improves readability and ensures a consistent experience with style overrides.
## Atomic Styles
When you write styles in Panda, it generates a modern atomic stylesheet that is automatically scoped to the
`@layer utilities` cascade layer.
The atomic stylesheets approach offers several advantages, such as improved code maintainability and reusability, as
well as a smaller overall CSS footprint.
Panda exposes a `css` function that can be used to author styles. It accepts a style object and returns a className
string.
```jsx
import { css } from '../styled-system/css'
const styles = css({
backgroundColor: 'gainsboro',
borderRadius: '9999px',
fontSize: '13px',
padding: '10px 15px'
})
// Generated className:
// --> bg_gainsboro rounded_9999px fs_13px p_10px_15px
Hello World
```
The styles generated at build time end up like this:
```css
@layer utilities {
.bg_gainsboro {
background-color: gainsboro;
}
.rounded_9999px {
border-radius: 9999px;
}
.fs_13px {
font-size: 13px;
}
.p_10px_15px {
padding: 10px 15px;
}
}
```
### Shorthand Properties
Panda provides shorthands for common css properties to help improve the speed of development and reduce the visual
density of your style declarations.
Properties like `borderRadius`, `backgroundColor`, and `padding` can be swapped to their shorthand equivalent `rounded`,
`bg`, and `p`.
```jsx
import { css } from '../styled-system/css'
// BEFORE - Good
const styles = css({
backgroundColor: 'gainsboro',
borderRadius: '9999px',
fontSize: '13px',
padding: '10px 15px'
})
// AFTER - Better
const styles = css({
bg: 'gainsboro',
rounded: '9999px',
fontSize: '13px',
p: '10px 15px'
})
```
> Shorthands are documented alongside their respective properties in the [utilities](/docs/utilities/background)
> section.
### Type safety
Panda is built with TypeScript and provides type safety for all style properties and shorthands. Most of the style
properties are connected to either the native CSS properties or their respective token value defined as defined in the
`theme` object.
```ts
import { css } from '../styled-system/css'
// ‡ you'll get autocomplete for colors
const styles = css({ bg: '|' })
```
> You can also enable the `strictTokens: true` setting in the Panda configuration. This allows only token values and
> prevents the use of custom or raw CSS values.
- `config.strictTokens` will only affect properties that have config tokens, such as `color`, `bg`, `borderColor`, etc.
- `config.strictPropertyValues` will throw for properties that do not have config tokens, such as `display`, `content`,
`willChange`, etc. when the value is not a predefined CSS value.
> In both cases, you can use the `[xxx]` escape-hatch syntax to use custom or raw CSS values without TypeScript errors.
#### strictTokens
With `config.strictTokens` enabled, you can only use token values in your styles. This prevents the use of custom or raw
CSS values.
```ts filename="panda.config.ts"
import { css } from '../styled-system/css'
css({ bg: 'red' }) // β Error: "red" is not a valid token value
css({ fontSize: '123px' }) // β Error: "123px" is not a valid token value
css({ bg: 'red.400' }) // β Valid
css({ fontSize: '[123px]' }) // β Valid, since `[123px]` is using the escape-hatch syntax
css({ content: 'abc' }) // β Valid, since `content` isn't bound to a config token
```
For one-off styles, you can always use the escape-hatch syntax `[xxx]` to use custom or raw CSS values without
TypeScript errors.
```ts filename="panda.config.ts"
import { css } from '../styled-system/css'
css({ bg: '[red]' }) // β Valid, since `[red]` is using the escape-hatch syntax
css({ fontSize: '[123px]' }) // β Valid, since `[123px]` is using the escape-hatch syntax
```
#### strictPropertyValues
With `config.strictPropertyValues` enabled, you can only use valid CSS values for properties that do have a predefined
list of values in your styles. This prevents the use of custom or raw CSS values.
```ts filename="panda.config.ts"
css({ display: 'flex' }) // β Valid
css({ display: 'block' }) // β Valid
css({ display: 'abc' }) // β will throw since 'abc' is not part of predefined values of 'display'
css({ pos: 'absolute123' }) // β will throw since 'absolute123' is not part of predefined values of 'position'
css({ display: '[var(--btn-display)]' }) // β Valid, since `[var(--btn-display)]` is using the escape-hatch syntax
css({ content: '""' }) // β Valid, since `content` does not have a predefined list of values
css({ flex: '0 1' }) // β Valid, since `flex` does not have a predefined list of values
```
The `config.strictPropertyValues` option will only be applied to this exhaustive list of properties:
```ts
type StrictableProps =
| 'alignContent'
| 'alignItems'
| 'alignSelf'
| 'all'
| 'animationComposition'
| 'animationDirection'
| 'animationFillMode'
| 'appearance'
| 'backfaceVisibility'
| 'backgroundAttachment'
| 'backgroundClip'
| 'borderCollapse'
| 'border'
| 'borderBlock'
| 'borderBlockEnd'
| 'borderBlockStart'
| 'borderBottom'
| 'borderInline'
| 'borderInlineEnd'
| 'borderInlineStart'
| 'borderLeft'
| 'borderRight'
| 'borderTop'
| 'borderBlockEndStyle'
| 'borderBlockStartStyle'
| 'borderBlockStyle'
| 'borderBottomStyle'
| 'borderInlineEndStyle'
| 'borderInlineStartStyle'
| 'borderInlineStyle'
| 'borderLeftStyle'
| 'borderRightStyle'
| 'borderTopStyle'
| 'boxDecorationBreak'
| 'boxSizing'
| 'breakAfter'
| 'breakBefore'
| 'breakInside'
| 'captionSide'
| 'clear'
| 'columnFill'
| 'columnRuleStyle'
| 'contentVisibility'
| 'direction'
| 'display'
| 'emptyCells'
| 'flexDirection'
| 'flexWrap'
| 'float'
| 'fontKerning'
| 'forcedColorAdjust'
| 'isolation'
| 'lineBreak'
| 'mixBlendMode'
| 'objectFit'
| 'outlineStyle'
| 'overflow'
| 'overflowX'
| 'overflowY'
| 'overflowBlock'
| 'overflowInline'
| 'overflowWrap'
| 'pointerEvents'
| 'position'
| 'resize'
| 'scrollBehavior'
| 'touchAction'
| 'transformBox'
| 'transformStyle'
| 'userSelect'
| 'visibility'
| 'wordBreak'
| 'writingMode'
```
## Nested Styles
Panda provides different ways of nesting style declarations. You can use the native css nesting syntax, or the built-in
pseudo props like `_hover` and `_focus`. Pseudo props are covered more in-depth in the next section.
### Native CSS Nesting
Panda supports the native css nesting syntax. You can use the `&` selector to create nested styles.
> **Important:** It is required to use the "&" character when nesting styles.
```jsx
```
You can also target children and siblings using the `&` syntax.
```jsx
```
We recommend not using descendant selectors as they can lead to specificity issues when managing style overrides.
Colocating styles directly on the element is the preferred way of writing styles in Panda.
### Using Pseudo Props
Panda provides a set of pseudo props that can be used to create nested styles. The pseudo props are prefixed with an
underscore `_` to avoid conflicts with the native pseudo selectors.
For example, to create a hover style, you can use the `_hover` pseudo prop.
```jsx
```
> See the [pseudo props](/docs/concepts/conditional-styles#reference) section for a list of all available pseudo props.
## Global styles
Global styles are useful for applying additional global resets or font faces. Use the `globalCss` property in the
`panda.config.ts` file to define global styles.
Global styles are inserted at the top of the stylesheet and are scoped to the `@layer base` cascade layer.
```js filename="panda.config.ts"
import { defineConfig, defineGlobalStyles } from '@pandacss/dev'
const globalCss = defineGlobalStyles({
'html, body': {
color: 'gray.900',
lineHeight: '1.5'
}
})
export default defineConfig({
// ...
globalCss
})
```
The styles generated at build time will look like this:
```css
@layer base {
html,
body {
color: var(--colors-gray-900);
line-height: 1.5;
}
}
```
### Setting global font
Set the `--global-font-body` and `--global-font-mono` CSS variables to set the body and monospace font-families.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
globalCss: {
html: {
'--global-font-body': 'Inter, sans-serif',
'--global-font-mono': 'Mononoki Nerd Font, monospace'
}
}
})
```
### Setting the global placeholder color
Set the `--global-color-placeholder` CSS variable to set the placeholder color for all input elements.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
globalCss: {
html: {
'--global-color-placeholder': 'red'
}
}
})
```
### Setting the global border color
Set the `--global-color-border` CSS variable to set the border color for all elements.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
globalCss: {
html: {
'--global-color-border': 'colors.gray.400'
}
}
})
```
## Style Composition
### Merging styles
Passing multiple styles to the `css` function will deeply merge the styles, allowing you to override styles in a
predictable way.
```jsx
import { css } from '../styled-system/css'
const result = css({ mx: '3', paddingTop: '4' }, { mx: '10', pt: '6' })
// ^? result = "mx_10 pt_6"
```
To design a component that supports style overrides, you can provide the `css` prop as a style object, and it'll be
merged correctly.
```tsx filename="src/components/Button.tsx"
import { css } from '../styled-system/css'
export const Button = ({ css: cssProp = {}, children }) => {
const className = css({ display: 'flex', alignItems: 'center', color: 'black' }, cssProp)
return
}
```
Then you can use the `Button` component like this:
```tsx filename="src/app/page.tsx"
import { Button } from './Button'
export default function Page() {
return (
)
}
```
---
You can use this approach as well with the `{cvaFn}.raw`, `{svaFn.raw}` and `{patternFn}.raw` functions, allowing style
objects to be merged as expected in any situation.
**Pattern Example:**
```tsx filename="src/components/Button.tsx"
import { hstack } from '../styled-system/patterns'
import { css } from '../styled-system/css'
export const Button = ({ css: cssProp = {}, children }) => {
// using the flex pattern
const hstackProps = hstack.raw({
border: '1px solid',
_hover: { color: 'blue.400' }
})
// merging the styles
const className = css(hstackProps, cssProp)
return
}
```
**CVA Example:**
```tsx filename="src/components/Button.tsx"
import { css, cva } from '../styled-system/css'
const buttonRecipe = cva({
base: { display: 'flex', fontSize: 'lg' },
variants: {
variant: {
primary: { color: 'white', backgroundColor: 'blue.500' }
}
}
})
export const Button = ({ css: cssProp = {}, children }) => {
const className = css(
// using the button recipe
buttonRecipe.raw({ variant: 'primary' }),
// adding style overrides (internal)
{ _hover: { color: 'blue.400' } },
// adding style overrides (external)
cssProp
)
return
}
```
**SVA Example:**
```tsx filename="src/components/Button.tsx"
import { css, sva } from '../styled-system/css'
const checkbox = sva({
slots: ['root', 'control', 'label'],
base: {
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
},
variants: {
size: {
sm: {
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
},
md: {
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
}
}
},
defaultVariants: {
size: 'sm'
}
})
export const Checkbox = ({ rootProps, controlProps, labelProps }) => {
// using the checkbox recipe
const slotStyles = checkbox.raw({ size: 'md' })
return (
)
}
// Usage
const App = () => {
return (
)
}
```
### Classname concatenation
Panda provides a simple `cx` function to join classnames. It accepts a list of classnames and returns a string.
```jsx
import { css, cx } from '../styled-system/css'
const styles = css({
borderWidth: '1px',
borderRadius: '8px',
paddingX: '12px',
paddingY: '24px'
})
const Card = ({ className, ...props }) => {
const rootClassName = cx('group', styles, className)
return
}
```
### Hashing
When debugging or previewing DOM elements in the browser, the length of the generated atomic `className` can get quite
long, and a bit annoying. If you prefer to have terser classnames, use the `hash` option to enable className and css
variable name hashing.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
hash: true
})
```
> You might need to generate a new code artifact by running `panda codegen --clean`
When you write a style like this:
```jsx
import { css } from '../styled-system/css'
const styles = css({
display: 'flex',
flexDirection: 'row',
_hover: {
bg: 'red.50'
}
})
```
The hash generated css will look like:
```css
.fPSBzf {
display: flex;
}
.ksWBqx {
flex-direction: row;
}
.btpEVp:is(:hover, [data-hover]) {
background: var(--bINrJX);
}
```
> We recommend that you use this in production builds only, as it can make debugging a bit harder.
## Important styles
Applying important styles works just like CSS
```js
css({
color: 'red !important'
})
```
You can also apply important using just the exclamation syntax `!`
```js
css({
color: 'red!'
})
```
## TypeScript
Use the `SystemStyleObject` type if you want to type your styles.
```ts {2}
import { css } from '../styled-system/css'
import type { SystemStyleObject } from '../styled-system/types'
const styles: SystemStyleObject = {
color: 'red'
}
```
## Property conflicts
When you combine shorthand and longhand properties, Panda 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;
}
}
```
## Global vars
You can use the `globalVars` property to define global
[CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) or custom CSS
[`@property`](https://developer.mozilla.org/en-US/docs/Web/CSS/@property) definitions.
Panda will automatically generate the corresponding CSS variables and suggest them in your style objects.
> They will be generated in the [`cssVarRoot`](/docs/references/config#cssvarroot) near your tokens.
This can be especially useful when using a 3rd party library that provides custom CSS variables, like a popper library
that exposes a `--popper-reference-width`.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
globalVars: {
'--popper-reference-width': '4px',
// you can also generate a CSS @property
'--button-color': {
syntax: '',
inherits: false,
initialValue: 'blue'
}
}
})
```
> Note: Keys defined in `globalVars` will be available as a value for _every_ utilities, as they're not bound to token
> categories.
```ts
import { css } from '../styled-system/css'
const className = css({
'--button-color': 'colors.red.300',
// ^^^^^^^^^^^^ will be suggested
backgroundColor: 'var(--button-color)'
// ^^^^^^^^^^^^^^^^^^ will be suggested
})
```
---
# Theming
## Animation Styles
Define reusable animation css properties.
Animation styles focus solely on animations, allowing you to orchestrate animation properties.
## Defining Animation Styles
Animation styles are defined in the `animationStyles` property of the theme.
Here's an example of an animation style:
```js filename="animation-styles.ts"
import { defineAnimationStyles } from '@pandacss/dev'
export const animationStyles = defineAnimationStyles({
'slide-fade-in': {
value: {
transformOrigin: 'var(--transform-origin)',
animationDuration: 'fast',
'&[data-placement^=top]': {
animationName: 'slide-from-top, fade-in'
},
'&[data-placement^=bottom]': {
animationName: 'slide-from-bottom, fade-in'
},
'&[data-placement^=left]': {
animationName: 'slide-from-left, fade-in'
},
'&[data-placement^=right]': {
animationName: 'slide-from-right, fade-in'
}
}
}
})
```
> **Good to know:** The `value` property maps to style objects that will be applied to the element.
## Update the Config
To use the animation styles, we need to update the `config` object in the `panda.config.ts` file.
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
import { animationStyles } from './animation-styles'
export default defineConfig({
theme: {
extend: {
animationStyles
}
}
})
```
This should automatically update the generated theme with the specified `animationStyles`. If this doesn't happen, you
can run the `panda codegen` command.
## Using Animation Styles
Now we can use the `animationStyle` property in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return (
This is an element with slide-fade-in animation style.
)
}
```
Take advantage of it in your conditions:
```ts
export const popoverSlotRecipe = defineSlotRecipe({
slots: anatomy.keys(),
base: {
content: {
_open: {
animationStyle: 'scale-fade-in'
},
_closed: {
animationStyle: 'scale-fade-out'
}
}
}
})
```
## Best Practices
### Avoid Overuse
To ensure the performance and readability of your design system, avoid overusing animations. Use them sparingly to
enhance user experience without overwhelming the user.
### Consistent Naming Conventions
We recommend using consistent naming conventions for animation styles. Here are common ideas on how to name animation
styles:
- Based on the type of animation (`slide`, `fade`, `bounce`)
- Based on the direction or trigger (`slide-from-top`, `fade-in`, `bounce-on-click`)
- Descriptive or functional names that explain the style's intended use (`modal-open`, `button-hover`, `alert-show`)
By following these guidelines, you can create a clear and maintainable animation system in your design.
---
## Layer Styles
Define reusable container styles properties.
Layer styles provide a way to create consistent and visually appealing elements.
- Color or text color
- Background color
- Border width and border color
- Box shadow
- Opacity
## Defining layer styles
Layer styles are defined in the `layerStyles` property of the theme.
Here's an example of a layer style:
```js filename="layer-styles.ts"
import { defineLayerStyles } from '@pandacss/dev'
const layerStyles = defineLayerStyles({
container: {
description: 'container styles',
value: {
background: 'gray.50',
border: '2px solid',
borderColor: 'gray.500'
}
}
})
```
> **Good to know:** The `value` property maps to style objects that will be applied to the element.
## Update the config
To use the layer styles, we need to update the `config` object in the `panda.config.ts` file.
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
import { layerStyles } from './layer-styles'
export default defineConfig({
theme: {
extend: {
layerStyles
}
}
})
```
This should automatically update the generated theme the specified `layerStyles`. If this doesn't happen, you can run
the `panda codegen` command.
## Using layer styles
Now we can use `layerStyle` property in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return
This is inside a container style
}
```
---
## Text Styles
Define reusable typography css properties.
Text styles allows you to define textual css properties. The common properties are:
- The font family, weight, size
- Line height
- Letter spacing
- Text Decoration (strikethrough and underline)
- Text Transform (uppercase, lowercase, and capitalization)
## Defining text styles
Text styles are defined in the `textStyles` property of the theme.
Here's an example of a text style:
```js filename="text-styles.ts"
import { defineTextStyles } from '@pandacss/dev'
export const textStyles = defineTextStyles({
body: {
description: 'The body text style - used in paragraphs',
value: {
fontFamily: 'Inter',
fontWeight: '500',
fontSize: '16px',
lineHeight: '24px',
letterSpacing: '0',
textDecoration: 'None',
textTransform: 'None'
}
}
})
```
> **Good to know:** The `value` property maps to style objects that will be applied to the text.
## Update the config
To use the text styles, we need to update the `config` object in the `panda.config.ts` file.
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
import { textStyles } from './text-styles'
export default defineConfig({
theme: {
extend: {
textStyles
}
}
})
```
This should automatically update the generated theme the specified `textStyles`. If this doesn't happen, you can run the
`panda codegen` command.
## Using text styles
Now we can use `textStyle` property in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return
This is a paragraph from Panda with the body text style.
}
```
## Best Practices
### Avoid layout properties
To ensure the consistency of your design system, avoid applying layout properties (like margin, padding, etc.) or color
properties (background, colors, etc.) to the text styles.
### Naming conventions
We recommend using the same text style names used by designers on your team. Here are common ideas on how to name text
styles:
- Sized-based naming system (`xs`, `sm`, `md`, `lg`, `xl`)
- Semantic naming system that corresponds to respective html tags in production (`caption`, `paragraph`, `h1`, `h2`)
- Descriptive or functional naming system that explains the style's intended use (`alert`, `modal-header`,
`button-label`)
---
## Tokens
Design tokens are the platform-agnostic way to manage design decisions in your application or website.
Design tokens provide a platform-agnostic way to manage design decisions through key-value pairs that describe
fundamental visual styles.
> Design tokens in Panda are largely influenced by the [W3C Token Format](https://tr.designtokens.org/format/).
A design token consists of the following properties:
- `value`: The value of the token. This can be any valid CSS value.
- `description`: An optional description of what the token can be used for.
## Core Tokens
Tokens are defined in the `panda.config` file under the `theme` key
```js filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
// ππ» Define your tokens here
extend: {
tokens: {
colors: {
primary: { value: '#0FEE0F' },
secondary: { value: '#EE0F0F' }
},
fonts: {
body: { value: 'system-ui, sans-serif' }
}
}
}
}
})
```
> β οΈ Token values need to be nested in an object with a `value` key. This is to allow for additional properties like
> `description` and more in the future.
After defining tokens, you can use them in authoring components and styles.
```jsx
import { css } from '../styled-system/css'
function App() {
return (
Hello World
)
}
```
You can also add an optional description to your tokens. This will be used in the autogenerate token documentation.
```js {8}
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
colors: {
danger: {
value: '#EE0F0F',
description: 'Color for errors'
}
}
}
}
})
```
## Semantic Tokens
Semantic tokens are tokens that are designed to be used in a specific context. In most cases, the value of a semantic
token references to an existing token.
> To reference a value in a semantic token, use the `{}` syntax.
For example, assuming we've defined the following tokens:
- `red` and `green` are raw tokens that define the color red and green.
- `danger` and `success` are semantic tokens that reference the `red` and `green` tokens.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
colors: {
red: { value: '#EE0F0F' },
green: { value: '#0FEE0F' }
}
},
semanticTokens: {
colors: {
danger: { value: '{colors.red}' },
success: { value: '{colors.green}' }
}
}
}
})
```
> β οΈ Semantic Token values need to be nested in an object with a `value` key. This is to allow for additional properties
> like `description` and more in the future.
Semantic tokens can also be changed based on the [conditions](/docs/concepts/conditional-styles) like light and dark
modes.
For example, if you want a color to change automatically based on light or dark mode.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
theme: {
semanticTokens: {
colors: {
danger: {
value: { base: '{colors.red}', _dark: '{colors.darkred}' }
},
success: {
value: { base: '{colors.green}', _dark: '{colors.darkgreen}' }
}
}
}
}
})
```
> NOTE π¨: The conditions used in semantic tokens must be an at-rule or parent selector
> [condition](/docs/concepts/conditional-styles#reference).
## Token Nesting
Tokens can be nested to create a hierarchy of tokens. This is useful when you want to group tokens together.
> Tip: You can use the `DEFAULT` key to define the default value of a nested token.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
theme: {
semanticTokens: {
colors: {
bg: {
DEFAULT: { value: '{colors.gray.100}' },
muted: { value: '{colors.gray.100}' }
}
}
}
}
})
```
This allows the use of the `bg` token in the following ways:
```jsx
import { css } from '../styled-system/css'
function App() {
return (
Hello World
)
}
```
## Token Types
Panda supports the following token types:
### Colors
Colors have meaning and support the purpose of the content, communicating things like hierarchy of information, and
states. It is mostly defined as a string value or reference to other tokens.
```jsx
const theme = {
tokens: {
colors: {
red: { 100: { value: '#fff1f0' } }
}
}
}
```
### Gradients
Gradient tokens represent a smooth transition between two or more colors. Its value can be defined as a string or a
composite value.
```ts
type Gradient =
| string
| {
type: 'linear' | 'radial'
placement: string | number
stops:
| Array<{
color: string
position: number
}>
| Array
}
```
```jsx
const theme = {
tokens: {
gradients: {
// string value
simple: { value: 'linear-gradient(to right, red, blue)' },
// composite value
primary: {
value: {
type: 'linear',
placement: 'to right',
stops: ['red', 'blue']
}
}
}
}
}
```
### Sizes
Size tokens represent the width and height of an element. Its value is defined as a string.
```jsx
const theme = {
tokens: {
sizes: {
sm: { value: '12px' }
}
}
}
```
> Size tokens are typically used in `width`, `height`, `min-width`, `max-width`, `min-height`, `max-height` properties.
### Spacings
Spacing tokens represent the margin and padding of an element. Its value is defined as a string.
```jsx
const theme = {
tokens: {
spacing: {
sm: { value: '12px' }
}
}
}
```
> Spacing tokens are typically used in `margin`, `padding`, `gap`, and `{top|right|bottom|left}` properties.
### Fonts
Font tokens represent the font family of a text element. Its value is defined as a string or an array of strings.
```jsx
const theme = {
tokens: {
fonts: {
body: { value: 'Inter, sans-serif' },
heading: { value: ['Roboto Mono', 'sans-serif'] }
}
}
}
```
> Font tokens are typically used in `font-family` property.
### Font Sizes
Font size tokens represent the size of a text element. Its value is defined as a string.
```jsx
const theme = {
tokens: {
fontSizes: {
sm: { value: '12px' }
}
}
}
```
> Font size tokens are typically used in `font-size` property.
### Font Weights
Font weight tokens represent the weight of a text element. Its value is defined as a string.
```jsx
const theme = {
tokens: {
fontWeights: {
bold: { value: '700' }
}
}
}
```
> Font weight tokens are typically used in `font-weight` property.
### Letter Spacings
Letter spacing tokens represent the spacing between letters in a text element. Its value is defined as a string.
```jsx
const theme = {
tokens: {
letterSpacings: {
wide: { value: '0.1em' }
}
}
}
```
> Letter spacing tokens are typically used in `letter-spacing` property.
### Line Heights
Line height tokens represent the height of a line of text. Its value is defined as a string.
```jsx
const theme = {
tokens: {
lineHeights: {
normal: { value: '1.5' }
}
}
}
```
> Line height tokens are typically used in `line-height` property.
### Radii
Radii tokens represent the radius of a border. Its value is defined as a string.
```jsx
const theme = {
tokens: {
radii: {
sm: { value: '4px' }
}
}
}
```
> Radii tokens are typically used in `border-radius` property.
### Borders
A border is a line surrounding a UI element. You can define them as string values or as a composite value
```jsx
const theme = {
tokens: {
borders: {
// string value
subtle: { value: '1px solid red' },
// string value with reference to color token
danger: { value: '1px solid {colors.red.400}' },
// composite value
accent: { value: { width: '1px', color: 'red', style: 'solid' } }
}
}
}
```
> Border tokens are typically used in `border`, `border-top`, `border-right`, `border-bottom`, `border-left`, `outline`
> properties.
### Border Widths
Border width tokens represent the width of a border. Its value is defined as a string.
```jsx
const theme = {
tokens: {
borderWidths: {
thin: { value: '1px' },
thick: { value: '2px' },
medium: { value: '1.5px' }
}
}
}
```
### Shadows
Shadow tokens represent the shadow of an element. Its value is defined as single or multiple values containing a string
or a composite value.
```ts
type CompositeShadow = {
offsetX: number
offsetY: number
blur: number
spread: number
color: string
inset?: boolean
}
type Shadow = string | CompositeShadow | string[] | CompositeShadow[]
```
```jsx
const theme = {
tokens: {
shadows: {
// string value
subtle: { value: '0 1px 2px 0 rgba(0, 0, 0, 0.05)' },
// composite value
accent: {
value: {
offsetX: 0,
offsetY: 4,
blur: 4,
spread: 0,
color: 'rgba(0, 0, 0, 0.1)'
}
},
// multiple string values
realistic: {
value: ['0 1px 2px 0 rgba(0, 0, 0, 0.05)', '0 1px 4px 0 rgba(0, 0, 0, 0.1)']
}
}
}
}
```
> Shadow tokens are typically used in `box-shadow` property.
### Easings
Easing tokens represent the easing function of an animation or transition. Its value is defined as a string or an array
of values representing the cubic bezier.
```jsx
const theme = {
tokens: {
easings: {
// string value
easeIn: { value: 'cubic-bezier(0.4, 0, 0.2, 1)' },
// array value
easeOut: { value: [0.4, 0, 0.2, 1] }
}
}
}
```
> Ease tokens are typically used in `transition-timing-function` property.
### Opacity
Opacity tokens help you set the opacity of an element.
```js
const theme = {
tokens: {
opacity: {
50: { value: 0.5 }
}
}
}
```
> Opacity tokens are typically used in `opacity` property.
### Z-Index
This token type represents the depth of an element's position on the z-axis.
```jsx
const theme = {
tokens: {
zIndex: {
modal: { value: 1000 }
}
}
}
```
> Z-index tokens are typically used in `z-index` property.
### Assets
Asset tokens represent a url or svg string. Its value is defined as a string or a composite value.
```ts
type CompositeAsset = { type: 'url' | 'svg'; value: string }
type Asset = string | CompositeAsset
```
```js
const theme = {
tokens: {
assets: {
logo: {
value: { type: 'url', value: '/static/logo.png' }
},
checkmark: {
value: { type: 'svg', value: '' }
}
}
}
}
```
> Asset tokens are typically used in `background-image` property.
### Durations
Duration tokens represent the length of time in milliseconds an animation or animation cycle takes to complete. Its
value is defined as a string.
```jsx
const theme = {
tokens: {
durations: {
fast: { value: '100ms' }
}
}
}
```
> Duration tokens are typically used in `transition-duration` and `animation-duration` properties.
### Animations
Animation tokens represent a keyframe animation. Its value is defined as a string value.
```jsx
const theme = {
tokens: {
animations: {
spin: {
value: 'spin 1s linear infinite'
}
}
}
}
```
> Animation tokens are typically used in `animation` property.
### Aspect Ratios
Aspect ratio tokens represent the aspect ratio of an element. Its value is defined as a string.
```js
const theme = {
tokens: {
aspectRatios: {
'1:1': { value: '1 / 1' },
'16:9': { value: '16 / 9' }
}
}
}
```
### Cursor
Cursor tokens define the style of the mouse pointer when it hovers over a specific element or area. These tokens
represent the visual behavior of interactions, indicating actions such as clickable areas, draggable elements, or
loading states. Their value is defined as a string.
```js
const theme = {
tokens: {
cursor: {
click: { value: 'pointer' },
disabled: { value: 'not-allowed' },
// custom value
custom: { value: 'url(cursor.svg), auto' }
}
}
}
```
## Token Helpers
To help defining tokens in a type-safe way, you can use the tokens
[Config Functions](/docs/customization/config-functions#token-creators).
## CSS variables
The generated CSS variables will be scoped using the `cssVarRoot` selector defined in the config.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
cssVarRoot: ':where(:root, :host)'
// ...
})
```
This will generate a CSS file similar to the following:
```css
:where(:root, :host) {
--colors-primary: #0fee0f;
--colors-secondary: #ee0f0f;
/* ... */
}
```
You can also define type-safe CSS variables using [globalVars](/docs/concepts/writing-styles#property-conflicts).
---
## Using Tokens
There are various ways to consume Panda tokens depending on your need at that point in time.
Learn the various ways to consume Panda tokens in your project.
## Style Properties
The recommended way to consume your tokens is in the `css` function or style props.
```jsx
import { css } from '../styled-system/css'
const App = () => (
)
```
## Composite values
Some CSS properties like `border`, `box-shadow` allow you to specify multiple properties in its value. Panda allows you
to reference tokens in these composite values by using either the `token()` string function (similar to the JS
equivalent) or the token reference syntax `{path.to.token}` (similar to the semantic tokens equivalent).
The `token()` function is useful when you need to provide a fallback value. The token reference syntax is useful when
you don't need a fallback value or prefer using a more concise syntax.
{/* */}
```js
import { css } from '../styled-system/css'
const className = css({ border: '1px solid token(colors.red.400)' })
```
You can also provide a fallback value.
```js
import { css } from '../styled-system/css'
const className = css({ border: '1px solid token(colors.red.400, red)' })
```
```js
import { css } from '../styled-system/css'
const className = css({ border: '1px solid {colors.red.400}' })
```
{/* */}
You can also use it in media queries or any other CSS at-rule.
{/* */}
```js
import { css } from '../styled-system/css'
const className = css({
'@media screen and (min-width: token(sizes.4xl))': {
color: 'green.400'
}
})
```
```js
import { css } from '../styled-system/css'
const className = css({
'@media screen and (min-width: {sizes.4xl})': {
color: 'green.400'
}
})
```
{/* */}
## Vanilla JS
Use the generated `token` function to query design tokens in your project. This is useful if you need direct access to
your design tokens in the `style` attribute or when using CSS-in-JS libraries like `styled-components` or
`@emotion/styled`
> This approach is useful for incrementally adopting Panda in existing projects or
> [dynamic styling](/docs/guides/dynamic-styling#using-token)
### Style Attribute
```tsx filename="src/App.tsx"
import { token } from '../styled-system/tokens'
function App() {
return (
)
}
```
Each of your design tokens will be available in the generated `/tokens` folder. It looks like this:
```js filename="styled-system/tokens.ts"
const tokens = {
// ...
'colors.blue.200': {
value: '#bfdbfe',
variable: 'var(--colors-blue-200)'
}
// ...
}
```
- The `token()` function returns the raw value of the token.
- The `token.var()` function returns the CSS custom property used to reference the token.
Both functions are typesafe and expect a known dot-separated token path, they also accept a fallback value as a second
argument.
Using the example above, `token('colors.blue.200')` would return `#bfdbfe` and `token.var('colors.blue.200')` would
return `var(--colors-blue-200)`.
### Styled Components
```tsx
import styled from 'styled-components'
const Button = styled.button`
background: ${token('colors.blue.200')};
`
```
### Emotion
```tsx
import styled from '@emotion/styled'
const Button = styled.button`
background: ${token('colors.blue.200')};
`
```
---
# Utilities
## Background
Panda provides the following utilities or style properties for styling background colors, gradients, and images.
Use these utilities to style background colors, gradients, and images.
## Background Colors
```jsx
// with alpha
```
| Prop | CSS Property | Token Category |
| ---------------------------- | ------------------ | -------------- |
| `bg`, `background` | `background` | `colors` |
| `bgColor`, `backgroundColor` | `background-color` | `colors` |
| `bgGradient` | `background-image` | `gradients` |
## Background Gradients
Properties to create a background gradient based on color stops.
```jsx
```
Background and text gradients can be connected to design tokens. Here's how to define a gradient token in your theme.
```ts
const theme = {
tokens: {
gradients: {
// string value
simple: { value: 'linear-gradient(to right, red, blue)' },
// composite value
primary: {
value: {
type: 'linear',
placement: 'to right',
stops: ['red', 'blue']
}
}
}
}
}
```
These tokens can be used in the `bgGradient` or `textGradient` properties.
```jsx
```
| Prop | CSS Property | Token Category |
| -------------- | ------------------ | -------------- |
| `bgGradient` | `background-image` | `gradients` |
| `textGradient` | `background-image` | `gradients` |
| `gradientFrom` | `--gradient-from` | `colors` |
| `gradientTo` | `--gradient-to` | `colors` |
| `gradientVia` | `--gradient-via` | `colors` |
## Background Position
Properties for controlling the src and position of a background image.
```jsx
```
| Prop | CSS Property | Token Category |
| -------------------------------------- | ------------------- | -------------- |
| `bgPosition`, `backgroundPosition` | `background-image` | none |
| `bgPositionX`, `backgroundPositionX` | `background-image` | none |
| `bgPositionY`, `backgroundPositionY` | `background-image` | none |
| `bgAttachment` ,`backgroundAttachment` | `background-size` | none |
| `bgClip`, `backgroundClip` | `background-size` | none |
| `bgOrigin`, `backgroundOrigin` | `background-size` | none |
| `bgImage`, `backgroundImage` | `background-size` | assets |
| `bgRepeat`, `backgroundRepeat` | `background-repeat` | none |
| `bgBlendMode`, `backgroundBlendMode` | `background-size` | none |
| `bgSize`, `backgroundSize` | `background-size` | none |
---
## Border
Panda's border utilities.
Panda provides CSS properties for styling borders.
## Compound Properties
The border compound property maps to the `borders` token category.
| Prop | CSS Property | Token Category |
| ----------------------------------- | ------------------- | -------------- |
| `border` | `border` | `borders` |
| `borderX` , `borderInline` | `borderInline` | `borders` |
| `borderY` , `borderBlock` | `borderBlock` | `borders` |
| `borderStart` , `borderInlineStart` | `borderInlineStart` | `borders` |
| `borderEnd` , `borderInlineEnd` | `borderInlineEnd` | `borders` |
## Border Radius
### All sides
```jsx
// shorthand
```
### Specific sides
Use the `border{Left|Right|Top|Bottom}Radius` properties, or the shorthand equivalent to apply border radius on a
specific side of an element.
```jsx
// shorthand
// shorthand
```
### Specific corners
Use the `border{Top|Bottom}{Left|Right}Radius` properties, or the shorthand equivalent to round a specific corner.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| ---------------------------------------- | ----------------------------------- | -------------- |
| `rounded`,`borderRadius` | `border-radius` | `radii` |
| `roundedTopLeft`,`borderTopLeftRadius` | `border-top-left-radius` | `radii` |
| `roundedTopRight`,`borderTopRight` | `border-top-right-radius` | `radii` |
| `roundedBottomRight`,`borderBottomRight` | `border-bottom-right-radius` | `radii` |
| `roundedBottomLeft`,`borderBottomLeft` | `border-bottom-left-radius` | `radii` |
| `roundedTop`,`borderTopRadius` | `border-top-{left+right}-radius` | `radii` |
| `roundedRight`,`borderRightRadius` | `border-{top+bottom}-right-radius` | `radii` |
| `roundedBottom`,`borderBottomRadius` | `border-bottom-{left+right}-radius` | `radii` |
| `roundedLeft`,`borderLeftRadius` | `border-{top+bottom}-left-radius` | `radii` |
### Logical Properties
Panda also provides the logical properties for border radius, which map to corresponding physical properties based on
the document's writing mode.
> For example, `borderStartRadius` will map to `border-left-radius` in LTR mode, and `border-right-radius` in RTL mode.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| -------------------------------------------- | --------------------------------- | -------------- |
| `roundedStartStart`,`borderStartStartRadius` | `border-start-start-radius` | `radii` |
| `roundedStartEnd`,`borderStartEndRadius` | `border-start-end-radius` | `radii` |
| `roundedStart`,`borderStartRadius` | `border-{start+end}-start-radius` | `radii` |
| `roundedEndStart`,`borderEndStartRadius` | `border-end-start-radius` | `radii` |
| `roundedEndEnd`,`borderEndEndRadius` | `border-end-end-radius` | `radii` |
| `roundedEnd` ,`borderEndRadius` | `border-{start+end}-end-radius` | `radii` |
## Border Width
### All sides
```jsx
```
### Specific sides
Use the `border{Left|Right|Top|Bottom}Width` properties, to apply border width on a specific side of an element.
```jsx
```
| Prop | CSS Property |
| ------------------------------------ | --------------------------- |
| `borderWidth` | `border-width` |
| `borderTopWidth` | `border-top-width` |
| `borderLeftWidth` | `border-left-width` |
| `borderRightWidth` | `border-right-width` |
| `borderBottomWidth` | `border-bottom-width` |
| `borderXWidth` , `borderInlineWidth` | `border-{left+right}-width` |
| `borderYWidth` , `borderBlockWidth` | `border-{top+bottom}-width` |
### Logical Properties
Panda also provides the logical properties for border width, which map to corresponding physical properties based on the
document's writing mode.
> For example, `borderStartWidth` will map to `border-left-width` in LTR mode, and `border-right-width` in RTL mode.
```jsx
```
| Prop | CSS Property |
| --------------------------------------------- | -------------------------- |
| `borderStartWidth` , `borderInlineStartWidth` | `border-{start+end}-width` |
| `borderEndWidth` , `borderInlineEndWidth` | `border-{start+end}-width` |
## Border Color
The border color utilities are used to set the border color of an element. It references the `colors` token category.
### All sides
```jsx
```
### Specific sides
Use the `border{Left|Right|Top|Bottom}Color` properties to apply border color on a specific side of an element.
```jsx
```
| Prop | CSS Property | Token Category |
| ------------------- | --------------------- | -------------- |
| `borderColor` | `border-color` | `colors` |
| `borderTopColor` | `border-top-color` | `colors` |
| `borderLeftColor` | `border-left-color` | `colors` |
| `borderRightColor` | `border-right-color` | `colors` |
| `borderBottomColor` | `border-bottom-color` | `colors` |
### Logical Properties
Panda also provides the logical properties for border color, which map to corresponding physical properties based on the
document's writing mode.
> For example, `borderInlineStartColor` will map to `border-left-color` in LTR mode, and `border-right-color` in RTL
> mode.
```jsx
```
| Prop | CSS Property | Token Category |
| --------------------------------------------- | -------------------------- | -------------- |
| `borderStartColor` , `borderInlineStartColor` | `border-{start+end}-color` | `colors` |
| `borderEndColor` , `borderInlineEndColor` | `border-{start+end}-color` | `colors` |
| `borderXColor`, `borderInlineColor` | `border-inline-color` | `colors` |
| `borderYColor`, `borderBlockColor` | `border-block-color` | `colors` |
---
## Display
Panda provides style properties for styling display of an element
Panda provides utilities and style properties for styling display of an element.
## Display Property
```jsx
```
## Hiding Elements
Panda provides shortcut properties for hiding elements from and below a specific breakpoint.
### Hide From
```jsx
```
### Hide Below
```jsx
```
| Prop | CSS Property | Token Category |
| ----------- | ------------ | -------------- |
| `hideFrom` | `display` | `breakpoints` |
| `hideBelow` | `display` | `breakpoints` |
---
## Divide
Panda provides style properties for for dividing elements
Panda provides utilities and style properties for dividing elements.
## Divide X
```jsx
```
## Divide Y
```jsx
```
## Divide Color
```jsx
```
## Divide Style
```jsx
```
---
## Effects
Panda provides utilities or style properties for applying various visual effects to elements.
Panda offers a range of utilities and style properties for applying visual effects to elements. These effects include
opacity, shadows, blending modes, filters, and more.
## Opacity
```jsx
```
| Prop | CSS Property | Token Category |
| --------- | ------------ | -------------- |
| `opacity` | `opacity` | `opacity` |
## Box Shadow
Apply box shadows to elements.
```jsx
```
| Prop | CSS Property | Token Category |
| ------------- | ---------------- | -------------- |
| `boxShadow` | `box-shadow` | `shadows` |
| `shadow` | `box-shadow` | `shadows` |
| `shadowColor` | `--shadow-color` | `colors` |
## Mix Blend Mode
Control the blending mode of an element.
```jsx
```
| Prop | CSS Property | Token Category |
| -------------- | ---------------- | -------------- |
| `mixBlendMode` | `mix-blend-mode` | none |
## Filter
Apply various filters to elements.
```jsx
```
| Prop | CSS Property | Token Category |
| ------------ | --------------- | -------------- |
| `filter` | `filter` | none |
| `blur` | `--blur` | `blurs` |
| `brightness` | `--brightness` | none |
| `contrast` | `--contrast` | none |
| `grayscale` | `--grayscale` | none |
| `hueRotate` | `--hue-rotate` | none |
| `invert` | `--invert` | none |
| `saturate` | `--saturate` | none |
| `sepia` | `--sepia` | none |
| `dropShadow` | `--drop-shadow` | `dropShadows` |
## Backdrop Filter
Apply filters to the backdrop of an element.
```jsx
```
| Prop | CSS Property | Token Category |
| -------------------- | ----------------------- | -------------- |
| `backdropFilter` | `backdrop-filter` | none |
| `backdropBlur` | `--backdrop-blur` | `blurs` |
| `backdropBrightness` | `--backdrop-brightness` | none |
| `backdropContrast` | `--backdrop-contrast` | none |
| `backdropGrayscale` | `--backdrop-grayscale` | none |
| `backdropHueRotate` | `--backdrop-hue-rotate` | none |
| `backdropInvert` | `--backdrop-invert` | none |
| `backdropOpacity` | `--backdrop-opacity` | none |
| `backdropSaturate` | `--backdrop-saturate` | none |
| `backdropSepia` | `--backdrop-sepia` | none |
---
## Flex and Grid
Panda provides a set of utilities and style properties for flexible box layout (Flex) and grid layout (Grid). These utilities are designed to make it easy to create responsive and dynamic layouts in your application.
Panda provides a set of utilities and style properties for flexible box layout (Flex) and grid layout (Grid). These
utilities are designed to make it easy to create responsive and dynamic layouts in your application.
## Flex
Flex utilities are designed to control the layout and behavior of flex containers and items.
### Flex Basis
The `flexBasis` utility sets the initial main size of a flex item, distributing the available space along the main axis.
It supports `spacing` tokens and fractional literal values like β1/2β, β2/3", etc.
```jsx
```
### Flex
The `flex` utility defines the flexibility of a flex container or item. Supported values:
| Value | |
| --------- | ---------- |
| `1` | `1 1 0%` |
| `auto` | `1 1 auto` |
| `initial` | `0 1 auto` |
| `none` | `none` |
### Flex Direction
The `flexDirection` utility sets the direction of the main axis in a flex container. It's shorthand is `flexDir`.
```jsx
```
## Grid
Grid utilities offer control over various grid layout properties, providing a powerful system for creating layouts with
rows and columns.
### Grid Template Columns
The `gridTemplateColumns` utility defines the columns of a grid container.
```jsx
```
### Grid Template Rows
The `gridTemplateRows` utility defines the rows of a grid container.
```jsx
```
---
## Focus Ring
Style focus states with accessibility-first focus ring utilities.
Focus rings are essential for accessibility, helping users identify which element currently has keyboard focus. Panda
provides comprehensive focus ring utilities that work with both regular focus and focus-visible states.
## Focus Ring Variants
The `focusRing` utility applies focus styles using the `&:is(:focus, [data-focus])` selector and supports four variants:
```jsx
// Outside focus ring (default 2px offset)
// Inside focus ring (no offset, with border)
// Mixed focus ring (semi-transparent with border)
// No focus ring
```
## Focus Visible Ring
The `focusVisibleRing` utility only applies focus styles during keyboard navigation using the
`&:is(:focus-visible, [data-focus-visible])` selector:
```jsx
```
### Focus Ring vs. Focus Visible Ring
The Focus Visible Ring functions similarly to the Focus Ring, but with a key difference: it only applies focus indicator
styles when an element receives keyboard focus.
This ensures that the focus ring is visible only when navigating via keyboard, improving accessibility without affecting
mouse interactions.
## Customization
You can customize focus ring appearance with additional utilities:
```jsx
```
| Prop | CSS Property | Token Category | Description |
| ------------------ | ---------------- | -------------- | ------------------------ |
| `focusRing` | Multiple | Enum | Focus ring variant |
| `focusVisibleRing` | Multiple | Enum | Keyboard-only focus ring |
| `focusRingColor` | `outline-color` | `colors` | Focus ring color |
| `focusRingWidth` | `outline-width` | `borderWidths` | Focus ring thickness |
| `focusRingStyle` | `outline-style` | `borderStyles` | Focus ring style |
| `focusRingOffset` | `outline-offset` | `spacing` | Distance from element |
### Ring Color
To change the focus ring color for a specific component, use the `focusRingColor` prop:
```jsx
```
## Global Ring Color
You can set a global focus ring color by defining the CSS custom property:
```ts
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
globalCss: {
html: {
'--global-color-focus-ring': '#3b82f6'
}
}
})
```
### Ring Width
To change the focus ring width for a specific component, use the `focusRingWidth` prop:
```jsx
```
### Ring Style
To change the focus ring style for a specific component, use the `focusRingStyle` prop:
```jsx
```
This color will be used as the default for all focus rings unless overridden by the `focusRingColor` prop.
## Examples
### Basic Focus Ring
```jsx
import { css } from '../styled-system/css'
function Button({ children }) {
return (
)
}
```
### Keyboard-Only Focus Ring
```jsx
import { css } from '../styled-system/css'
function Input({ ...props }) {
return (
)
}
```
### Custom Focus Ring
```jsx
import { css } from '../styled-system/css'
function CustomButton({ children }) {
return (
)
}
```
---
## Gradients
Create smooth color transitions with linear, radial, and conic gradient utilities.
Create smooth color transitions with linear, radial, and conic gradient utilities.
| Property | Shorthand | CSS Property | Description |
| -------------------- | ------------ | ------------------ | ------------------------------ |
| `backgroundLinear` | `bgLinear` | `background-image` | Apply linear gradient effects |
| `backgroundRadial` | `bgRadial` | `background-image` | Apply radial gradient effects |
| `backgroundConic` | `bgConic` | `background-image` | Apply conic gradient effects |
| `backgroundGradient` | `bgGradient` | `background-image` | Apply linear gradient (alias) |
| `textGradient` | - | `background-image` | Apply gradient to text |
| `gradientFrom` | - | `--gradient-from` | Define starting gradient color |
| `gradientTo` | - | `--gradient-to` | Define ending gradient color |
| `gradientVia` | - | `--gradient-via` | Define middle gradient color |
## Examples
### Linear gradients
Use the `bgLinear` utility to create a linear gradient with a direction.
```tsx
css({ bgLinear: 'to-r', gradientFrom: 'cyan.500', gradientTo: 'blue.500' })
css({ bgLinear: 'to-t', gradientFrom: 'sky.500', gradientTo: 'indigo.500' })
css({
bgLinear: 'to-bl',
gradientFrom: 'violet.500',
gradientTo: 'fuchsia.500'
})
css({ bgLinear: '65deg', gradientFrom: 'purple.500', gradientTo: 'pink.500' })
```
### Radial gradients
Build circular color transitions that radiate outward from a center point:
```tsx
css({
bgRadial: 'in srgb',
gradientFrom: 'pink.400',
gradientFromPosition: '40%',
gradientTo: 'fuchsia.700'
})
css({
bgRadial: 'at 50% 75%',
gradientFrom: 'sky.200',
gradientVia: 'blue.400',
gradientTo: 'indigo.900',
gradientToPosition: '90%'
})
css({
bgRadial: 'at 25% 25%',
gradientFrom: 'white',
gradientTo: 'zinc.900',
gradientToPosition: '75%'
})
```
### Conic gradients
Create sweeping color transitions that rotate around a central point:
```jsx
css({
boxSize: '24',
rounded: 'full',
bgConic: 'in srgb',
gradientFrom: 'blue.600',
gradientTo: 'sky.400',
gradientToPosition: '50%'
})
css({
boxSize: '24',
rounded: 'full',
bgConic: 'from 180deg',
gradientFrom: 'blue.600',
gradientVia: 'blue.50',
gradientTo: 'blue.600'
})
css({
boxSize: '24',
rounded: 'full',
bgConic: 'in oklch decreasing hue',
gradientFrom: 'violet.700',
gradientVia: 'lime.300',
gradientTo: 'violet.700'
})
```
### Controlling color stops
Define which colors appear in your gradient using `gradientFrom`, `gradientVia`, and `gradientTo`:
```jsx
css({
bgLinear: 'to-r',
gradientFrom: 'indigo.500',
gradientVia: 'purple.500',
gradientTo: 'pink.500'
})
```
### Positioning color stops
Control exactly where each color appears along the gradient using position utilities:
```jsx
css({
bgLinear: 'to-r',
gradientFrom: 'indigo.500',
gradientFromPosition: '10%',
gradientVia: 'sky.500',
gradientViaPosition: '30%',
gradientTo: 'emerald.500',
gradientToPosition: '90%'
})
```
### Text gradients
Apply colorful gradient effects to typography using `textGradient`:
```jsx
css({
textGradient: 'to-r',
gradientFrom: 'purple.400',
gradientTo: 'pink.400',
fontSize: '4xl',
fontWeight: 'bold'
})
```
### Custom gradient values
Use bracket notation to create gradients with arbitrary values:
```jsx
css({
bgLinear: '25deg',
gradientFrom: 'red.50%',
gradientVia: 'yellow.60%',
gradientTo: 'lime.90%',
gradientToPosition: 'teal.100%'
})
```
### Responsive gradients
Apply different gradient styles at different breakpoints using responsive objects:
```jsx
css({
gradientFrom: { base: 'purple.400', md: 'yellow.500' }
})
```
---
## Helpers
Panda CSS offers utility classes to enhance accessibility and aid in debugging.
Panda CSS offers utility classes to enhance accessibility and aid in debugging.
## Screen Reader-Only Content
The srOnly utility class hides content visually while keeping it accessible to screen readers. It is particularly useful
when you want to provide information to screen readers without displaying it on the screen.
```jsx
Accessible only to screen readers
```
## Debug
The debug utility class applies styles to aid in debugging by adding outlines to elements. This can be helpful during
development to visually inspect the layout and structure of your components.
```jsx
Debugging outline applied
```
---
## Interactivity
Panda CSS provides a variety of utility classes to enhance interactivity and user experience on your web applications.
Panda CSS provides a variety of utility classes to enhance interactivity and user experience on your web applications.
These utilities cover aspects such as accent color, caret color, scrolling behavior, scrollbar customization, scroll
margins and paddings, scroll snapping, touch actions, and user selection.
## Accent Color
The `accentColor` utility class sets the accent color of an element. It supports `colors` tokens.
```jsx
Accent color applied
```
## Caret Color
The `caretColor` utility class sets the color of the text cursor (caret) in an input or textarea. It supports `colors`
tokens.
```jsx
```
## Scrollbar
The `scrollbar` utility allows customization of scrollbar appearance. It supports `visible` and `hidden` values which
respectively show or hide the scrollbar.
```jsx
Scrollbar hidden
```
## Scroll Margin
Scroll margin utilities set margins around scroll containers.
```jsx
```
### Scroll Snap Type
Supported values
| Value | |
| ------ | ------------------------------------ |
| `none` | `none` |
| `x` | `x var(--scroll-snap-strictness)` |
| `y` | `y var(--scroll-snap-strictness)` |
| `both` | `both var(--scroll-snap-strictness)` |
---
## Layout
Panda provides style properties for styling layout of an element
Panda provides style properties for styling layout of an element.
## Aspect Ratio
Use the `aspectRatio` utilities to set the desired aspect ratio of an element.
Values can reference the `aspectRatios` token category.
```jsx
```
> This uses the native CSS property `aspect-ratio` which is might not supported in all browsers. Consider using the
> [`AspectRatio` pattern](/docs/concepts/patterns#aspect-ratio) instead
## Position
Use the `position` utilities to set the position of an element.
```jsx
// shorthand
```
## Top / Right / Bottom / Left
Use the `top`, `right`, `bottom` and `left` utilities to set the position of an element.
Values can reference the `spacing` token category.
```jsx
```
| Prop | CSS Property | Token Category |
| -------- | ------------ | -------------- |
| `top` | `top` | `spacing` |
| `right` | `right` | `spacing` |
| `bottom` | `bottom` | `spacing` |
| `left` | `left` | `spacing` |
### Logical Properties
Use the `inset{Start|End}` utilities to set the position of an element based on the writing mode.
> For example, `insetStart` will set the `left` property in `ltr` mode and `right` in `rtl` mode.
```jsx
```
| Prop | CSS Property | Token Category |
| ----------------------------------------- | -------------------- | -------------- |
| `start`, `insetStart`, `insetInlineStart` | `inset-inline-start` | `spacing` |
| `end` , `insetEnd`, `insetInlineEnd` | `inset-inline-end` | `spacing` |
| `insetX`, `insetInline` | `inset-inline` | `spacing` |
| `insetY`, `insetBlock` | `inset-inline` | `spacing` |
## Container Query
You can define container names and sizes in your theme configuration and use them in your styles.
[Read more.](/docs/concepts/conditional-styles#container-queries)
| Prop | CSS Property | Token Category |
| --------------- | --------------- | ---------------- |
| `containerName` | `containerName` | `containerNames` |
---
## List
Panda provides utilities for customizing list styles.
Panda provides utilities for customizing list styles.
## List Style Image
Use a custom image as the list marker. It supports the `assets` token category.
```js filename="panda.config.ts"
const theme = {
tokens: {
assets: {
star: {
value: { type: 'svg', value: '' }
}
}
}
}
```
```jsx
```
---
## Outline
Panda provides utilities for customizing outlines.
Panda provides utilities for customizing outlines.
## Compound Property
Set the width, color, and style of the outline.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| ------------------ | ------------ | -------------- |
| `ring` , `outline` | `outline` | `borders` |
## Outline Width
Change the width of the outline.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| ---------------------------- | --------------- | -------------- |
| `ringWidth` , `outlineWidth` | `outline-width` | `borderWidths` |
## Outline Color
Change the color of the outline.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| -------------- | --------------- | -------------- |
| `outlineColor` | `outline-color` | `colors` |
## Outline Offset
Adjust the space between the outline and the element.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| --------------- | ---------------- | -------------- |
| `outlineOffset` | `outline-offset` | `spacing` |
---
## Sizing
Style properties for controlling the size of an element.
Style properties for controlling the size of an element.
## Width
Use the `width` or `w` property to set the width of an element.
```jsx
// shorthand
```
### Fractional width
Use can set fractional widths using the `width` or `w` property.
Values can be within the following ranges:
- Thirds: `1/3` to `2/3`
- Fourths: `1/4` to `3/4`
- Fifths: `1/5` to `4/5`
- Sixths: `1/6` to `5/6`
- Twelfths: `1/12` to `11/12`
```jsx
// shorthand
// shorthand
```
### Max width
Use the `maxWidth` or `maxW` property to set the maximum width of an element.
```jsx
// shorthand
```
### Min width
Use the `minWidth` or `minW` property to set the minimum width of an element.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| ------------------ | ------------ | -------------- |
| `w`, `width` | `width` | `sizes` |
| `maxW`, `maxWidth` | `max-width` | `sizes` |
| `minW`, `minWidth` | `min-width` | `sizes` |
## Height
Use the `height` or `h` property to set the height of an element.
```jsx
// shorthand
```
### Fractional height
Use can set fractional heights using the `height` or `h` property.
Values can be within the following ranges:
- Thirds: `1/3` to `2/3`
- Fourths: `1/4` to `3/4`
- Fifths: `1/5` to `4/5`
- Sixths: `1/6` to `5/6`
```jsx
// shorthand
```
### Relative heights
You can use the modern relative height values `dvh`, `svh`, `lvh`.
```jsx
// shorthand
```
### Max height
Use the `maxHeight` or `maxH` property to set the maximum height of an element.
```jsx
// shorthand
```
### Min height
Use the `minHeight` or `minH` property to set the minimum height of an element.
```jsx
// shorthand
```
| Prop | CSS Property | Token Category |
| ------------------- | ------------ | -------------- |
| `h`, `height` | `height` | `sizes` |
| `maxH`, `maxHeight` | `max-height` | `sizes` |
| `minH`, `minHeight` | `min-height` | `sizes` |
### Size
Use the `boxSize` property to set the width and height of an element.
```jsx
```
| Prop | CSS Property | Token Category |
| --------- | --------------- | -------------- |
| `boxSize` | `width, height` | `sizes` |
---
## Spacing
Style properties for controlling the padding of an element.
## Padding
### All sides
Use the `padding` property to apply padding on all sides of an element
```jsx
// shorthand
```
### Specific sides
Use the `padding{Left|Right|Top|Bottom}` to apply padding on one side of an element
```jsx
// shorthand
// shorthand
```
### Horizontal and Vertical padding
Use the `padding{X|Y}` properties to apply padding on the horizontal and vertical axis of an element
```jsx
// shorthand
// shorthand
```
| Prop | CSS Property | Token Category |
| --------------------- | ---------------- | -------------- |
| `p`,`padding` | `padding` | `spacing` |
| `pl`, `paddingLeft` | `padding-left` | `spacing` |
| `pr`, `paddingRight` | `padding-right` | `spacing` |
| `pt`, `paddingTop` | `padding-top` | `spacing` |
| `pb`, `paddingBottom` | `padding-bottom` | `spacing` |
| `px`, `paddingX` | `padding-inline` | `spacing` |
| `py`, `paddingY` | `padding-block` | `spacing` |
### Logical properties
Use the `padding{Start|End}` properties to apply padding on the logical axis of an element based on the text direction.
```jsx
// shorthand
// shorthand
```
| Prop | CSS Property | Token Category |
| -------------------- | ---------------------- | -------------- |
| `ps`, `paddingStart` | `padding-inline-start` | `spacing` |
| `pe`, `paddingEnd` | `padding-inline-end` | `spacing` |
## Margin
### All sides
Use the `margin` property to apply margin on all sides of an element
```jsx
// shorthand
```
### Specific sides
Use the `margin{Left|Right|Top|Bottom}` to apply margin on one side of an element
```jsx
// shorthand
// shorthand
```
### Horizontal and Vertical margin
Use the `margin{X|Y}` properties to apply margin on the horizontal and vertical axis of an element
```jsx
// shorthand
// shorthand
```
| Prop | CSS Property | Token Category |
| -------------------- | --------------- | -------------- |
| `m`,`margin` | `margin` | `spacing` |
| `ml`, `marginLeft` | `margin-left` | `spacing` |
| `mr`, `marginRight` | `margin-right` | `spacing` |
| `mt`, `marginTop` | `margin-top` | `spacing` |
| `mb`, `marginBottom` | `margin-bottom` | `spacing` |
| `mx`, `marginX` | `margin-left` | `spacing` |
| `my`, `marginY` | `margin-top` | `spacing` |
### Logical properties
Use the `margin{Start|End}` properties to apply margin on the logical axis of an element based on the text direction.
```jsx
// shorthand
// shorthand
```
| Prop | CSS Property | Token Category |
| ------------------- | --------------------- | -------------- |
| `ms`, `marginStart` | `margin-inline-start` | `spacing` |
| `me`, `marginEnd` | `margin-inline-end` | `spacing` |
---
## SVG
Panda provides utilities for styling SVG elements.
Panda provides utilities for styling SVG elements.
## Fill
Change the fill color of an SVG element.
```jsx
```
| Prop | CSS Property | Token Category |
| ------ | ------------ | -------------- |
| `fill` | `fill` | `colors` |
## Stroke
Change the stroke color of an SVG element.
```jsx
```
| Prop | CSS Property | Token Category |
| -------- | ------------ | -------------- |
| `stroke` | `stroke` | colors |
## Stroke Width
Change the stroke width of an SVG element.
```jsx
```
| Prop | CSS Property | Token Category |
| ------------- | -------------- | -------------- |
| `strokeWidth` | `stroke-width` | borderWidths |
---
## Tables
Panda provides utilities for styling tables.
Panda provides utilities for styling tables.
## Border Spacing
Control the border-spacing property of a table.
```jsx
```
| Prop | CSS Property | Token Category |
| --------------- | ---------------- | -------------- |
| `borderSpacing` | `border-spacing` | `spacing` |
## Border Spacing X
Control the horizontal border-spacing property of a table.
```jsx
```
| Prop | CSS Property | Token Category |
| ---------------- | ---------------- | -------------- |
| `borderSpacingX` | `border-spacing` | `spacing` |
## Border Spacing Y
Control the vertical border-spacing property of a table.
```jsx
```
| Prop | CSS Property | Token Category |
| ---------------- | ---------------- | -------------- |
| `borderSpacingY` | `border-spacing` | `spacing` |
---
## Transforms
Panda provides utilities for transforming elements.
Panda provides utilities for transforming elements.
## Scale
Control the scale property. Supported value is `auto`
```jsx
// => 'var(--scale-x) var(--scale-y)'
```
### Scale X
Control the scaleX property.
```jsx
// => --scale-x: 1.3;
```
### Scale Y
Control the scaleY property.
```jsx
// => --scale-y: 0.4;
```
## Translate
Control the translate property. Supported value is `auto`
```jsx
// => 'var(--translate-x) var(--translate-y)'
```
### Translate X
Control the translateX property.
```jsx
// => --translate-x: 50%;
// shorthand
```
### Translate Y
Control the translateY property.
```jsx
// => --translate-y: -40%;
// shorthand
```
---
## Transitions
Panda provides utilities for defining and customizing transitions.
Panda provides utilities for defining and customizing transitions.
## Transition
A shorthand utility for defining common transition sets.
Values are `all`, `common`, `colors`, `opacity`, `shadow`, `transform`.
```jsx
```
| Prop | CSS Property | Token Category |
| -------------------------- | ---------------------------- | -------------- |
| `transitionTimingFunction` | `transition-timing-function ` | `easings` |
| `transitionDelay` | `transition-delay ` | `durations` |
| `transitionDuration` | `transition-duration ` | `durations` |
## Animation
Control the animation property. It supports the `animations` token category.
```jsx
```
| Prop | CSS Property | Token Category |
| ---------------- | ----------------- | -------------- |
| `animation` | `animation-name ` | animations |
| `animationName` | `animation-name ` | animationName |
| `animationDelay` | `animation-delay ` | durations |
---
## Typography
Panda's typography utilities.
Panda provides utilities and style properties for styling text.
## Font Properties
```jsx
```
| Prop | CSS Property | Token Category |
| --------------------- | ----------------------- | ---------------- |
| `fontFamily` | `font-family` | `fonts` |
| `fontSize` | `font-size` | `fontSizes` |
| `fontWeight` | `font-weight` | `fontWeights` |
| `letterSpacing` | `letter-spacing` | `letterSpacings` |
| `lineHeight` | `line-height` | `lineHeights` |
| `textDecorationColor` | `text-decoration-color` | `colors` |
| `textEmphasisColor` | `text-emphasis-color` | `colors` |
| `textIndent` | `text-indent` | `spacing` |
| `textShadow` | `text-shadow` | `shadows` |
## Line Clamp (Truncation)
How to truncate multi-line text
```jsx
```
| Prop | Config |
| ----------- | ------------ |
| `textStyle` | `textStyles` |
---
# Customization
## Conditions
Learn how to customize conditions in your Panda config
Conditions allow you to apply different styles and behaviors based on specific conditions or states. They provide a way
to target specific elements or apply styles in response to certain events or conditions.
## Creating a condition
To create a condition, you can use the conditions property in the config. Let's say we want to create a `groupHover`
pseudo condition that applies styles to an element when a parent container with the `group` role is hovered.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
groupHover: '[role=group]:where(:hover, [data-hover]) &'
}
}
})
```
> β οΈ The `&` character is mandatory, it is a placeholder for the current selector. It will be replaced with the actual
> selector when the condition is used. It has to be used either at the beginning or at the end of the condition.
Then you can run the following command to generate the conditions JS code:
{/* */}
```bash
pnpm panda codegen
```
```bash
npm panda codegen
```
```bash
yarn panda codegen
```
```bash
bun panda codegen
```
{/* */}
Now, we can use the `groupHover` condition in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return (
)
}
```
## Customizing Built-in Conditions
You can extend the [default conditions](/docs/concepts/conditional-styles#reference) by using the `conditions.extend`
property in the config.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
// Extend the default `dark` condition
dark: '.dark &, [data-theme="dark"] &'
}
}
})
```
Then you can run the following command to update the conditions JS code:
{/* */}
```bash
pnpm panda codegen
```
```bash
npm panda codegen
```
```bash
yarn panda codegen
```
```bash
bun panda codegen
```
{/* */}
## Using tokens
You can also use tokens in your conditions, and they will be resolved to their actual values:
```tsx
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
mq: '@media (min-width: token(sizes.4xl))',
size2: '&[data-size=token(spacing.2)]'
}
}
})
```
## Mixed conditions
You can also use mixed conditions (nested at-rules/selectors) under a single condition name:
```tsx
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
conditions: {
extend: {
supportHover: ['@media (hover: hover) and (pointer: fine)', '&:hover']
}
}
})
```
```ts
import { css } from '../styled-system/css'
css({
_supportHover: {
color: 'red'
}
})
```
will generate the following CSS:
```css
@media (hover: hover) and (pointer: fine) {
&:hover {
color: red;
}
}
```
## Container queries
Read more about how to define type-safe container queries [here](/docs/concepts/conditional-styles#container-queries)
## Minimal setup
If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it
[here](/docs/guides/minimal-setup)
---
## Config Functions
Functions to expose types for your config.
Config functions help define and provide type information for your configuration. These utilities enhance code
readability, enforce consistency, and ensure robust type checking.
## Config Creators
To help defining config in a type-safe way, you can use the following helpers:
### `defineConfig`
Function for [config](/docs/references/config) definitions.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {},
include: ['src/**/*.{js,jsx,ts,tsx}']
})
```
### `defineRecipe`
Function for [recipe](/docs/concepts/recipes#config-recipe) definitions.
```ts
import { defineRecipe } from '@pandacss/dev'
export const buttonRecipe = defineRecipe({
className: 'button',
description: 'The styles for the Button component',
base: {
display: 'flex'
},
variants: {
visual: {
funky: { bg: 'red.200', color: 'white' },
edgy: { border: '1px solid {colors.red.500}' }
}
},
defaultVariants: {
visual: 'funky',
size: 'sm'
}
})
```
### `defineSlotRecipe`
Function for [slot recipe](/docs/concepts/slot-recipes#config-slot-recipe) definitions.
```ts
import { defineSlotRecipe } from '@pandacss/dev'
export const checkboxRecipe = defineSlotRecipe({
className: 'checkbox',
description: 'The styles for the Checkbox component',
slots: ['root', 'control', 'label'],
base: {
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
},
variants: {
size: {
sm: {
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
},
md: {
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
}
}
},
defaultVariants: {
size: 'sm'
}
})
```
### `defineParts`
It can be useful when you want to have the equivalent of a slot recipe without needing to split the class names bindings
and instead just having a className that handles children on 1 DOM element.
It pairs well with [ZagJs](https://zagjs.com/) and [Ark-UI](https://ark-ui.com/)
Let's refactor the previous example to use parts instead of slots:
```ts
import { defineParts, definetRecipe } from '@pandacss/dev'
const parts = defineParts({
root: { selector: '& [data-part="root"]' },
control: { selector: '& [data-part="control"]' },
label: { selector: '& [data-part="label"]' }
})
export const checkboxRecipe = defineRecipe({
className: 'checkbox',
description: 'A checkbox style',
base: parts({
root: { display: 'flex', alignItems: 'center', gap: '2' },
control: { borderWidth: '1px', borderRadius: 'sm' },
label: { marginStart: '2' }
}),
variants: {
size: {
sm: parts({
control: { width: '8', height: '8' },
label: { fontSize: 'sm' }
}),
md: parts({
control: { width: '10', height: '10' },
label: { fontSize: 'md' }
})
}
},
defaultVariants: {
size: 'sm'
}
})
```
### `definePattern`
Function for [pattern](/docs/customization/patterns) definitions.
```ts
import { definePattern } from '@pandacss/dev'
const visuallyHidden = definePattern({
transform(props) {
return {
srOnly: true,
...props
}
}
})
```
### `definePreset`
Function for [preset](/docs/customization/presets#creating-a-preset) definitions.
```ts
import { definePreset } from '@pandacss/dev'
export const pandaPreset = definePreset({
theme: {
extend: {
tokens: {
colors: { primary: { value: 'blue.500' } }
}
}
}
})
```
### `definePlugin`
Function for [plugin](/docs/references/config#plugins) definitions.
```ts
import { definePlugin } from '@pandacss/dev'
export const plugin = definePlugin({
name: 'token-format',
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: path => '$' + path.join('-')
})
}
}
})
```
### `defineKeyframes`
Function for [keyframes](/docs/customization/theme#keyframes) definitions.
```ts
import { defineKeyframes } from '@pandacss/dev'
export const keyframes = defineKeyframes({
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' }
}
})
```
### `defineGlobalStyles`
Function for [global styles](/docs/concepts/writing-styles#global-styles) definitions.
```ts
import { defineGlobalStyles } from '@pandacss/dev'
const globalCss = defineGlobalStyles({
'html, body': {
color: 'gray.900',
lineHeight: '1.5'
}
})
```
### `defineUtility`
Function for [utility](/docs/customization/utilities) definitions.
```ts
import { defineUtility } from '@pandacss/dev'
export const br = defineUtility({
className: 'rounded',
values: 'radii',
transform(value) {
return { borderRadius: value }
}
})
```
### `defineTextStyles`
Function for [text styles](/docs/theming/text-styles) definitions.
```ts
import { defineTextStyles } from '@pandacss/dev'
export const textStyles = defineTextStyles({
body: {
description: 'The body text style - used in paragraphs',
value: {
fontFamily: 'Inter',
fontWeight: '500',
fontSize: '16px',
lineHeight: '24',
letterSpacing: '0',
textDecoration: 'None',
textTransform: 'None'
}
}
})
```
### `defineLayerStyles`
Function for [layer styles](/docs/theming/layer-styles) definitions.
```ts
import { defineLayerStyles } from '@pandacss/dev'
const layerStyles = defineLayerStyles({
container: {
description: 'container styles',
value: {
background: 'gray.50',
border: '2px solid',
borderColor: 'gray.500'
}
}
})
```
### `defineStyles`
Function for style definitions.
This comes in handy when you want to define reusable styles in the config.
E.g. a set of styles to be used in multiple variants within a [recipe](/docs/concepts/recipes#config-recipe).
```ts {3, 14, 18} filename="recipes/button.ts"
import { defineRecipe, defineStyles } from '@pandacss/dev'
const buttonVisualStyles = defineStyles({
borderRadius: 'lg',
boxShadow: 'sm'
})
export const buttonRecipe = defineRecipe({
// ...
variants: {
visual: {
funky: {
bg: 'red.200',
color: 'white',
...buttonVisualStyles
},
edgy: {
border: '1px solid {colors.red.500}',
...buttonVisualStyles
}
}
}
})
```
## Token Creators
To help defining tokens in a type-safe way, you can use the following helpers:
### `defineTokens`
```ts
import { defineTokens } from '@pandacss/dev'
const theme = {
tokens: defineTokens({
colors: {
primary: { value: '#ff0000' }
}
})
}
```
You can also use this function to define tokens in a separate file:
```ts filename="tokens/colors.ts"
import { defineTokens } from '@pandacss/dev'
export const colors = defineTokens.colors({
primary: { value: '#ff0000' }
})
```
### `defineSemanticTokens`
```ts
import { defineSemanticTokens } from '@pandacss/dev'
const theme = {
semanticTokens: defineSemanticTokens({
colors: {
primary: {
value: { _light: '{colors.blue.400}', _dark: '{colors.blue.200}' }
}
}
})
}
```
You can also use this function to define tokens in a separate file:
```ts filename="tokens/colors.semantic.ts"
import { defineSemanticTokens } from '@pandacss/dev'
export const colors = defineSemanticTokens.colors({
primary: {
value: { _light: '{colors.blue.400}', _dark: '{colors.blue.200}' }
}
})
```
---
## Deprecations
Deprecating tokens, utilities, patterns and config recipes.
Deprecations are mostly relevant for large teams that want to deprecate certain utilities, patterns, recipes, or tokens
before removing them from the codebase.
## Deprecating a Utility
To deprecate a utility, set the `deprecated` property to `true` in the `utility` object.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
utilities: {
ta: {
deprecated: true,
transform(value) {
return { textAlign: value }
}
}
}
})
```
## Deprecating a Token
To deprecate a token, set the `deprecated` property to `true` in the `token` object.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
spacing: {
lg: { value: '8px', deprecated: true }
}
}
}
})
```
## Deprecating a Pattern
To deprecate a pattern, set the `deprecated` property to true in the `pattern` definition.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
patterns: {
customStack: {
deprecated: true
}
}
})
```
## Deprecating a Recipe
To deprecate a recipe, set the `deprecated` property to true in the `recipe` definition.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
recipes: {
btn: {
deprecated: true
}
}
}
})
```
## Custom Deprecation Messages
You can also provide a custom deprecation message by setting the `deprecated` property to a string. i.e. the migration
message.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
colors: {
primary: { value: 'blue.500', deprecated: 'use `blue.600` instead' }
}
}
}
})
```
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
recipes: {
btn: {
deprecated: 'will be removed in v2.0'
}
}
}
})
```
---
## Customizing Patterns
Panda provides the ability to customize the built-in patterns, as well as creating your own custom patterns. This is useful to create your own layout pattern abstractions that can be used in your application.
Panda allows you to customize built-in patterns and create custom patterns for reusable layout abstractions.
A pattern accepts the following parameters:
- `description` - The description of the pattern.
- `properties` - The list of properties that the pattern accepts.
- `defaultValues` - The default values for the properties. This is useful when you want to provide a default value for a
property.
- `transform` - The function that accepts the properties and returns a css object.
- `jsx` - The name of the JSX component that will be generated (when `jsxFramework` is set). Defaults to the pascal-case
version of the pattern name.
- `jsxElement` - The actual JSX element that will be rendered (when `jsxFramework` is set). Defaults to `div`.
- `blocklist` - The list of properties that are not allowed to be used in the pattern. Can be used to ensure strict
typings when using the pattern.
- `strict` - Whether to only generate types for the specified properties. This will disallow css properties.
## Creating a Pattern
To create a pattern, you can use the `patterns` property in the config. Let's say we want to create a "Scrollable"
pattern that applies preset styles to a container that allows for scrolling.
```js
const config = {
patterns: {
extend: {
scrollable: {
description: 'A container that allows for scrolling',
defaultValues: {
direction: 'vertical',
hideScrollbar: true
},
properties: {
// The direction of the scroll
direction: { type: 'enum', value: ['horizontal', 'vertical'] },
// Whether to hide the scrollbar
hideScrollbar: { type: 'boolean' }
},
// disallow the `overflow` property (in TypeScript)
blocklist: ['overflow'],
transform(props) {
const { direction, hideScrollbar, ...rest } = props
return {
overflow: 'auto',
height: direction === 'horizontal' ? '100%' : 'auto',
width: direction === 'vertical' ? '100%' : 'auto',
scrollbarWidth: hideScrollbar ? 'none' : 'auto',
WebkitOverflowScrolling: 'touch',
'&::-webkit-scrollbar': {
display: hideScrollbar ? 'none' : 'auto'
},
...rest
}
}
}
}
}
}
```
Then you can run the following command to generate the pattern JS code:
{/* */}
```bash
pnpm panda codegen
```
```bash
npm panda codegen
```
```bash
yarn panda codegen
```
```bash
bun panda codegen
```
{/* */}
Now you can import the pattern and use it in your application:
```js
import { scrollable } from '../styled-system/patterns'
const App = () => {
return (
Scrollable content
)
}
```
## Customizing Built-in Patterns
You can extend the [default patterns](/docs/concepts/patterns#predefined-patterns) by using the `patterns.extend`
property in the config.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
patterns: {
extend: {
// Extend the default `flex` pattern
flex: {
properties: {
// only allow row and column
direction: { type: 'enum', value: ['row', 'column'] },
jsx: ['Flex', 'CustomFlex'] // π match the `CustomFlex` component to this pattern
}
}
}
}
})
```
Then you can run the following command to update the pattern JS code:
{/* */}
```bash
pnpm panda codegen
```
```bash
npm panda codegen
```
```bash
yarn panda codegen
```
```bash
bun panda codegen
```
{/* */}
## Minimal setup
If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it
[here](/docs/guides/minimal-setup)
---
## Presets
Creating your own reusable preset for utilities and theme
By default, any configuration you add in your own `panda.config.js` file is smartly merged with the
[default configuration](#), allowing you to override or extend specific parts of the configuration.
You can specify a preset in your `panda.config.js` file by using the `presets` option:
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
presets: ['@acmecorp/panda-preset']
})
```
## Creating a preset
Presets are also valid Panda configuration objects, taking a similar shape to the configuration you would add in your
`panda.config.ts` file.
> **Note:** Every preset must have a unique name.
```js
// my-preset.js
import { definePreset } from '@pandacss/dev'
export default definePreset({
name: 'my-preset',
theme: {
tokens: {
colors: {
rose: {
50: { value: '#fff1f2' },
// ...
800: { value: '#9f2233' }
}
}
}
}
})
```
You can then use this preset in your `panda.config.ts` file:
```js
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
import myPreset from './my-preset'
export default defineConfig({
presets: [myPreset]
})
```
The available keys for a preset are:
- [`conditions`](/docs/concepts/conditional-styles)
- [`globalCss`](/docs/concepts/writing-styles#global-styles)
- [`globalFontface`](/docs/guides/fonts#global-font-face)
- [`patterns`](/docs/concepts/patterns)
- [`staticCss`](/docs/guides/static)
- [`theme`](/docs/customization/theme)
- [`utilities`](/docs/customization/utilities)
### Asynchronous presets
There are cases where you need to perform logic to determine the content of your preset, you'd call functions to do
this. In cases where they're asynchronous; panda allows promises, given that they resolve to a valid preset object.
```js
// my-preset.js
export default async function myPreset() {
const roseColors = await getRoseColors()
return definePreset({
name: 'my-preset',
theme: {
tokens: {
colors: {
rose: roseColors
}
}
}
})
}
```
You can then use this preset in your `panda.config.ts` file:
```js
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
import myPreset from './my-preset'
export default defineConfig({
presets: [myPreset()]
})
```
## Which panda presets will be included ?

- `@pandacss/preset-base`: ALWAYS included if NOT using `eject: true`
- `@pandacss/preset-panda`: only included by default if you haven't specified the `presets` config option, otherwise
you'll have to include that preset by yourself like so:
```ts
import pandaPreset from '@pandacss/preset-panda'
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
presets: [pandaPreset, myCustomPreset]
})
```
## Minimal setup
If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it
[here](/docs/guides/minimal-setup)
---
## Theme
Customizing the default theme
Panda comes with a default theme that is used to generate the utilities for your project. You can customize this theme
to match your design requirements.
## Breakpoints
Use the `breakpoints` key in the `theme` section of your Panda config file to customize the default breakpoints.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
breakpoints: {
'3xl': '1800px'
}
}
}
})
```
Panda ships with the following breakpoints by default:
## Tokens
### Colors
Use the `colors` key in the `token` section of your Panda config file to customize the default color values.
> We recommend using numeric ranges from `50` to `900`
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
colors: {
brand: { value: '#EA8433' }
}
}
}
}
})
```
Panda comes with a handful of colors picked from the amazing Tailwind color palette
### Spacing
Use the `spacing` key in the theme section of your Panda config file to customize the default spacing values.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
spacing: {
gutter: { value: '32px' }
}
}
}
}
})
```
Panda ships with the following spacing tokens by default:
### Border Radius
Use the `radii` key in the theme section of your Panda config file to customize the default border radius values.
### Shadows
Use the `shadows` key in the theme section of your Panda config file to customize the default box shadows values.
Panda ships with the following shadows by default:
### Sizing
Use the `sizes` key in the theme section of your Panda config file to customize the default sizing values.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
sizes: {
icon: { value: '24px' }
}
}
}
}
})
```
Panda ships with the following sizing tokens by default, in addition with the values from the default Panda
[spacing](#spacing) tokens:
### Fonts
Use the `fonts` key in the theme object to customize the default font families.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
fonts: {
marketing: { value: 'Inter Variable' }
}
}
}
}
})
```
Panda ships with the following font families tokens by default:
### Font Sizes
Use the `fontSizes` key in the theme object to customize the default font sizes.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
fontSizes: {
big: { value: '80px' }
}
}
}
}
})
```
Panda ships with the following font size tokens by default:
## Keyframes
Use the `keyframes` key in the `theme` section of your Panda config file to customize the default keyframes.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
keyframes: {
fadein: {
'0%': { opacity: '0' },
'100%': { opacity: '1' }
},
fadeout: {
'0%': { opacity: '1' },
'100%': { opacity: '0' }
}
}
}
}
})
```
Panda ships with the following keyframes by default:
## Minimal setup
If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it
[here](/docs/guides/minimal-setup)
---
## Utilities
The utility API is a way to create your own CSS properties, map existing properties to a set of values or tokens.
The utility API enables you to create custom CSS properties and map existing properties to specific values or tokens.
It's like building your own type-safe version of Chakra UI, Tailwind (in JS), or Styled System.
Panda comes with a set of utilities out of the box. You can customize them, or add your own.
Here are the properties you need to define or customize a utility:
- `className` : The className the property maps to
- `shorthand`: The shorthand or alias version of the property
- `values`: The possible values the property can have. Could be a token category, or an enum of values, string, number,
or boolean.
- `transform`: A function that converts the value to a valid css object
## Creating a custom utility
Let's say we want to create new property `br` that applies a border radius to an element.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/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 }
}
}
}
}
})
```
Then you can run the following command to generate the pattern JS code:
{/* */}
```bash
pnpm panda codegen
```
```bash
npm panda codegen
```
```bash
yarn panda codegen
```
```bash
bun panda codegen
```
{/* */}
Now, we can use the `br` property in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return
}
```
or use in JSX style props
```jsx
import { styled } from '../styled-system/jsx'
function App() {
return
}
```
### Using enum values
Let's say we want to create a new property `borderX` that applies a limited set of inline border to an element and
automatically applies the border color.
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
utilities: {
extend: {
borderX: {
values: ['1px', '2px', '4px'],
shorthand: 'bx', // `bx` or `borderX` can be used
transform(value, { token }) {
return {
borderInlineWidth: value,
borderColor: token('colors.red.200') // read the css variable for red.200
}
}
}
}
}
})
```
Now, we can use the `borderX` or `bx` property in our components.
```jsx
import { css } from '../styled-system/css'
function App() {
return
}
```
### Using mapped values
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
utilities: {
extend: {
borderX: {
values: { small: '2px', medium: '5px' },
shorthand: 'bx',
transform(value, { token }) {
return {
borderTopWidth: value,
borderTopColor: token('colors.gray.400')
}
}
}
}
}
})
```
### Using boolean values
```ts filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
utilities: {
extend: {
truncate: {
className: 'truncate',
values: { type: 'boolean' },
transform(value) {
if (!value) return {}
return {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
}
}
}
}
}
})
```
## Minimal setup
If you want to use Panda with the bare minimum, without any of the defaults, you can read more about it
[here](/docs/guides/minimal-setup)
---
# Guides
## 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",
"devDependencies": {
"@pandacss/dev": "^0.27.3"
},
"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"
}
}
```
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
```
```tsx
export const Funky: Story = {
// mark this as a button recipe usage
args: button.raw({
visual: 'funky',
shape: 'circle',
size: 'sm'
})
}
```
## Static expressions
Panda supports static expressions in your styles, as long as they are statically analyzable.
### Static Composition
You can compose different style objects together using the `css.raw()` function.
```tsx filename="App.tsx"
import { css } from 'styled-system/css'
const paragraphSpacingStyle = css.raw({
'& p': { marginBlockEnd: '1em' }
})
export const proseCss = css.raw({
'& h1': paragraphSpacingStyle
})
```
This will result in the following CSS:
```css
/* ... */
@layer utilities {
.\[\&_p\]\:mb_1em p,
.\[\&_h1\]\:\[\&_p\]\:mb_1em h1 p {
margin-block-end: 1em;
}
}
```
### Static Expressions
Panda supports the use of functions to generate the style objects as long they are statically analyzable.
You can only use functions that are defined in the ECMAScript spec such as `Math`, `Object`, `Array`, etc, to support
the evaluation of basic expressions like this:
```ts
import { cva } from '.panda/css'
const getVariants = () => {
const spacingTokens = Object.entries({
sm: 'token(spacing.1)',
md: 'token(spacing.2)'
})
// Generate variants programmatically
const variants = spacingTokens.map(([variant, token]) => [variant, { paddingX: token }])
return Object.fromEntries(variants)
}
const baseStyle = cva({
variants: {
variant: getVariants()
}
})
```
This will generate the following variants object:
```json
{
"sm": { "paddingX": "token(spacing.1)" },
"md": { "paddingX": "token(spacing.2)" }
}
```
And the following CSS
```css
@layer utilities {
.px_token\(spacing\.1\) {
padding-inline: var(--spacing-1);
}
.px_token\(spacing\.2\) {
padding-inline: var(--spacing-2);
}
}
```
## Runtime conditions
Even though we recommend that you first look for better alternatives (such as using
[recipe variants](/docs/concepts/recipes)), you may still occasionally need runtime conditions.
When encountering a runtime condition, Panda will first try to resolve it statically. If it can't, it will fallback to
the generating the corresponding CSS for each possible branches.
```tsx
import { useState } from 'react'
import { css } from '../styled-system/css'
import { Stack } from '../styled-system/jsx'
const App = () => {
const [isHovered, setIsHovered] = useState(false)
return (
)
}
```
Since none of the conditions above are statically extractable, Panda will generate css for all possible code path,
resulting in a css that looks like this:
```css
/* ... */
@layer utilities {
.hover\:text_red\.100:where(:hover, [data-hover]) {
color: var(--colors-red-100);
}
.text_red\.200 {
color: var(--colors-red-200);
}
.hover\:text_red\.300:where(:hover, [data-hover]) {
color: var(--colors-red-300);
}
@media screen and (min-width: 768px) {
.hover\:md\:text_red\.400:where(:hover, [data-hover]) {
color: var(--colors-red-400);
}
}
.text_red\.500 {
color: var(--colors-red-500);
}
.text_red\.600 {
color: var(--colors-red-600);
}
}
/* ... */
```
## Referenced values
Although you should have your styles inlined most of the time, maybe you want to store a value in a variable and re-use
in multiple places. This should be fine as long as you keep it statically analyzable.
Here's a short list of things to avoid:
- Variables that are not defined in the same file
- Variables resulting from a function call (e.g. `const color = getColor()`)
> If you don't know what value a variable holds with a quick glance, Panda won't be able to either.
```tsx
import { css } from '../styled-system/css'
// β Good: All values are statically extractable
const mainColor = 'red.300'
const sizes = { sm: '12px', md: '16px', '2xl': '42px' }
const App = () => {
return (
)
}
```
### Runtime reference on known objects
Using a more complex but still common example :
```tsx
import { useState } from 'react'
import { css } from '../styled-system/css'
const colorByType = {
primary: 'red.300',
secondary: 'blue.300',
tertiary: 'green.300'
}
const Section = () => {
const [type, setType] = useState('primary')
// β Avoid: since only "gray.100" is statically extractable here
// This will not work as expected, the color CSS won't be generated
return β Will not be extracted
}
```
Even though `colorByType` is statically analyzable, Panda does not _yet_ support this kind of automatic extraction
fallback. This is the perfect opportunity to use the [recipes](/docs/concepts/recipes).
```tsx
import { useState } from 'react'
import { cva } from '../styled-system/cva'
const sectionRecipe = cva({
base: { color: 'gray.100' },
variants: {
type: {
primary: { color: 'red.300' },
secondary: { color: 'blue.300' },
tertiary: { color: 'green.300' }
}
}
})
const Section = () => {
const [type, setType] = useState('primary')
// β Good: This will work as expected
return β With a recipe
}
```
Not only did you get the same end result, but you also got a more readable and maintainable code !
You can now :
- add more variants to your recipe
- add more properties
- use a shorthand or a condition
All of this with complete type-safety and without having to make drastic changes to the component.
> Note that you can also [integrate this recipe directly into your theme](/docs/concepts/recipes) if you want to only
> generate the CSS that you use, among other things
## Summary
### What you can do
```tsx
// β Good: Conditional styles
// β Good: Arbitrary value
// β Good: Arbitrary selector
span": { color: "red.100" } }} />
// β Good: Runtime value (with config.`staticCss`)
const Button = () => {
const [color, setColor] = useState('red.300')
return
}
// β Good: Runtime condition
// β Good: Referenced value
```
### What you can't do
```tsx
// β Avoid: Runtime value (without config.`staticCss`)
const Button = () => {
const [color, setColor] = useState('red.300')
return
}
// β Avoid: Referenced value (not statically analyzable or from another file)
const CustomCircle = (props) => {
const { circleSize = '3' } = props
return (
)
}
```
---
## Custom Font
How to use custom fonts in your project.
Adding custom fonts to your application or website is a typical requirement for projects. Panda recommends using custom
fonts through CSS variables for consistency.
## Setup
### Next.js
Next.js provides a built-in automatic self-hosting for any font file by using the `next/font` module. It allows you to
conveniently use all Google Fonts and any local font with performance and privacy in mind.
Here's an example of how to load a local "Mona Sans" font and a Google Font "Fira Code" in your Next.js project.
```js filename="styles/font.ts"
import { Fira_Code } from 'next/font/google'
import localFont from 'next/font/local'
export const MonaSans = localFont({
src: '../fonts/Mona-Sans.woff2',
display: 'swap',
variable: '--font-mona-sans'
})
export const FiraCode = Fira_Code({
weight: ['400', '500', '700'],
display: 'swap',
subsets: ['latin'],
variable: '--font-fira-code'
})
```
> Ideally, you should load the font in the layout file.
Next, you need to add the font variables to your HTML document. You can do this using either the App Router or the Pages
Router.
#### App Router
```jsx filename="app/layout.tsx"
import { FiraCode, MonaSans } from '../styles/font'
export default function Layout(props) {
const { children } = props
return (
{children}
)
}
```
> **Note π¨:** By default, Next.js attaches the className for the fonts to the `` element, for panda to
> appropriately load fonts, update the code to attach the `className` to the `` element.
#### Pages Router
```jsx filename="pages/_app.tsx"
import { FiraCode, MonaSans } from '../styles/font'
export default function App({ Component, pageProps }) {
return (
<>
>
)
}
```
### Fontsource
[Fontsource](https://fontsource.org/) streamlines the process of integrating fonts into your web application.
To begin, install your desired font package:
```bash
pnpm add @fontsource-variable/fira-code
```
Next, import the font into your project:
```jsx
import '@fontsource-variable/fira-code'
```
Lastly, create a variable to use it as a token in the panda config
```css filename="styles/font.css"
:root {
--font-fira-code: 'Fira Code Variable', monospace;
}
```
### Vanilla CSS
You can leverage the native font-face CSS property to load custom fonts in your project.
```css
@font-face {
font-family: 'Mona Sans';
src: url('../fonts/Mona-Sans.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
```
Then alias the font names to css variables.
```css
:root {
--font-mona-sans: 'Mona Sans', sans-serif;
}
```
### Global Font Face
You can also define global font face in your panda config.
```js
export default defineConfig({
globalFontface: {
Fira: {
src: 'url(/fonts/fira.woff2) format("woff2")',
fontWeight: 400,
fontStyle: 'normal',
fontDisplay: 'swap'
}
}
})
```
You can also define multiple font sources for the same weight.
```js
export default defineConfig({
globalFontface: {
Fira: {
src: ['url(/fonts/fira.woff2) format("woff2")', 'url(/fonts/fira.woff) format("woff")'],
fontWeight: 400,
fontStyle: 'normal',
fontDisplay: 'swap'
}
}
})
```
You can also define multiple font weights.
```js
export default defineConfig({
globalFontface: {
Fira: [
{
src: 'url(/fonts/fira.woff2) format("woff2")',
fontWeight: 400,
fontStyle: 'normal',
fontDisplay: 'swap'
},
{
src: 'url(/fonts/fira-bold.woff2) format("woff2")',
fontWeight: 700,
fontStyle: 'normal',
fontDisplay: 'swap'
}
]
}
})
```
Then expose the font names to css variables.
```css
:root {
--font-fira-code: 'Fira Code Variable', monospace;
}
```
You can also use [globalVars](/docs/concepts/writing-styles#global-vars) in your panda config to define the variables.
```js
export default defineConfig({
globalVars: {
'--font-fira-code': 'Fira Code Variable, monospace'
}
})
```
## Update Panda Config
```js
export default defineConfig({
theme: {
extend: {
tokens: {
fonts: {
fira: { value: 'var(--font-fira-code), Menlo, monospace' },
mona: { value: 'var(--font-mona-sans), sans-serif' }
}
}
}
}
})
```
## Use the custom fonts
```jsx
import { css } from '../styled-system/css'
function Page() {
return (
Mona Sans
Fira Code
)
}
```
---
## Minimal Setup
How to set up Panda with the bare minimum.
The default Panda setup includes utilities and design tokens by default. In this guide, you'll see how to strip out the
defaults and start from scratch.
## Removing default tokens
To remove the default design tokens injected by Panda, set the `presets` key to an empty array:
```js
export default defineConfig({
// ...
presets: []
})
```
This allows you to define your own tokens, without having to use the `extend` key in the theme.
```js
export default defineConfig({
// ...
theme: {
tokens: {
colors: {
primary: { value: '#ff0000' }
}
}
}
})
```
## Removing default utilities
Use the `eject: true` property to remove all the default utilities.
Panda doesn't automatically know which tokens are valid for which CSS properties, so it is necessary to tell Panda that
my tokens from the "colors" category are valid for the CSS property "color".
```js
export default defineConfig({
// ...
eject: true,
utilities: {
color: {
values: 'colors'
}
},
theme: {
tokens: {
colors: {
primary: { value: '#ff0000' }
}
}
}
})
```
This makes `
Text
` work as expected.
## Re-using Panda presets
Panda offers 2 presets:
- `@pandacss/preset-base`: This is a relatively unopinionated set of utilities for mapping CSS properties to values
(almost everyone will want these)
You can use these presets by installing them via npm and adding them to your `presets` key:
```js
export default defineConfig({
// ...
presets: ['@pandacss/preset-base']
})
```
- `@pandacss/preset-panda` as an opinionated set of tokens if you don't want to define your own colors/spacing/fonts
etc.
```js
export default defineConfig({
// ...
presets: ['@pandacss/preset-panda']
})
```
> Note: You don't need to install `@pandacss/preset-base` or `@pandacss/preset-panda`. Panda will automatically resolve
> them for you.
---
## Multi-Theme Tokens
Panda supports advance token definition beyond just light/dark mode; theming beyond just dark mode. You can define multi-theme tokens using nested conditions.
## Multi-Theme Tokens
Panda supports advance token definition beyond just light/dark mode; theming beyond just dark mode. You can define
multi-theme tokens using nested conditions.
Let's say your application supports a pink and blue theme, and each theme can have a light and dark mode. Let's see how
to model this in Panda.
We'll start by defining the following conditions for these theme and color modes:
```js
// panda.config.ts
const config = {
conditions: {
light: '[data-color-mode=light] &',
dark: '[data-color-mode=dark] &',
pinkTheme: '[data-theme=pink] &',
blueTheme: '[data-theme=blue] &'
}
}
```
> Conditions are a way to provide preset css selectors or media queries for use in your Panda project
Next, we'll define a `colors.text` semantic token for the pink and blue theme.
```js
// panda.config.ts
const theme = {
// ...
semanticTokens: {
colors: {
text: {
value: {
_pinkTheme: '{colors.pink.500}',
_blueTheme: '{colors.blue.500}'
}
}
}
}
}
```
Next, we'll modify `colors.text` to support light and dark color modes for each theme.
```js
// panda.config.ts
const theme = {
// ...
semanticTokens: {
colors: {
text: {
value: {
_pinkTheme: { base: '{colors.pink.500}', _dark: '{colors.pink.300}' },
_blueTheme: { base: '{colors.blue.500}', _dark: '{colors.blue.300}' }
}
}
}
}
}
```
Now, you can use the `text` token in your styles, and it will automatically change based on the theme and the color
scheme.
```jsx
// use pink and dark mode theme
Hello World
// use pink and light mode theme
Hello World
```
## Multi-Themes
The above example shows you how to define multi-theme tokens using nested conditions but you can also define clearly separated themes using the `themes` property in the config.
This allows you to apply a `theme` on multiple tokens at once, using data attributes and CSS variables.
> Theme variants can be applied using the `data-panda-theme` attribute with the theme key as the value.
```ts
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
// main theme
theme: {
extend: {
tokens: {
colors: {
text: { value: 'green' }
}
},
semanticTokens: {
colors: {
body: {
value: {
base: '{colors.green.600}',
_osDark: '{colors.green.400}'
}
}
}
}
}
},
// alternative theme variants
themes: {
primary: {
tokens: {
colors: {
text: { value: 'red' }
}
},
semanticTokens: {
colors: {
muted: { value: '{colors.red.200}' },
body: {
value: {
base: '{colors.red.600}',
_osDark: '{colors.red.400}'
}
}
}
}
},
secondary: {
tokens: {
colors: {
text: { value: 'blue' }
}
},
semanticTokens: {
colors: {
muted: { value: '{colors.blue.200}' },
body: {
value: {
base: '{colors.blue.600}',
_osDark: '{colors.blue.400}'
}
}
}
}
}
}
})
```
### Pregenerating themes
By default, no additional theme variant is generated, you need to specify the specific themes you want to generate in
`staticCss.themes` to include them in the CSS output.
```ts
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
themes: ['primary', 'secondary']
}
})
```
This will generate the following CSS:
```css
@layer tokens {
:where(:root, :host) {
--colors-text: blue;
--colors-body: var(--colors-blue-600);
}
[data-panda-theme='primary'] {
--colors-text: red;
--colors-muted: var(--colors-red-200);
--colors-body: var(--colors-red-600);
}
@media (prefers-color-scheme: dark) {
:where(:root, :host) {
--colors-body: var(--colors-blue-400);
}
[data-panda-theme='primary'] {
--colors-body: var(--colors-red-400);
}
}
}
```
### Dynamically importing themes
An alternative way of applying a theme is by using the new `styled-system/themes` entrypoint where you can import the
themes expected CSS and apply them in your app.
> βΉοΈ The `styled-system/themes` will always contain every themes (tree-shaken if not used), whereas `staticCss.themes` only
> applies to the CSS output.
Each theme has a corresponding JSON file with a similar structure:
```json
{
"name": "primary",
"id": "panda-themes-primary",
"css": "[data-panda-theme=primary] { ... }"
}
```
#### Dynamically import a theme using its name
```ts
import { getTheme } from '../styled-system/themes'
const theme = await getTheme('red')
// ^? {
// name: "red";
// id: string;
// css: string;
// }
```
#### Inject the theme styles into the DOM:
```ts
import { injectTheme } from '../styled-system/themes'
const theme = await getTheme('red')
injectTheme(document.documentElement, theme) // this returns the injected style element
```
#### SSR example with NextJS:
```tsx
// app/layout.tsx
import { cookies } from 'next/headers'
import './globals.css'
import { ThemeName, getTheme } from '../../styled-system/themes'
export default async function RootLayout({
children
}: {
children: React.ReactNode
}) {
const store = cookies()
const themeName = store.get('theme')?.value as ThemeName
const theme = themeName && (await getTheme(themeName))
return (
{themeName && (
)}
{children}
)
}
```
```tsx
// app/page.tsx
'use client'
import { getTheme, injectTheme } from '../../styled-system/themes'
export default function Home() {
return (
<>
>
)
}
// Set a Cookie
function setCookie(cName: string, cValue: any, expDays: number) {
let date = new Date()
date.setTime(date.getTime() + expDays * 24 * 60 * 60 * 1000)
const expires = 'expires=' + date.toUTCString()
document.cookie = cName + '=' + cValue + '; ' + expires + '; path=/'
}
```
### Theme contract
Finally, you can create a theme contract to ensure that all themes have the same structure:
```ts
import { defineThemeContract } from '@pandacss/dev'
const defineTheme = defineThemeContract({
tokens: {
colors: {
red: { value: '' } // theme implementations must have a red color
}
}
})
defineTheme({
tokens: {
colors: {
// ^^^^ β Property 'red' is missing in type '{}' but required in type '{ red: { value: string; }; }'
//
// β fixed with
// red: { value: 'red' },
}
}
})
```
---
## Static CSS Generator
Panda can be used to generate a static set of utility classes for your project.
Panda can be used to generate a static set of utility classes for your project.
This is useful if you want to use Panda in an HTML project or you want absolute zero runtime.
## Usage
To generate a static set of CSS classes, add them to your `panda.config.js` file:
```js
export default {
staticCss: {
// the css properties you want to generate
css: [],
// the recipes you want to generate
recipes: {}
}
}
```
The `static` property supports two properties:
- `css` - an array of CSS properties you want to generate with their `conditions`
- `recipes` - the component recipes you want to generate
## Generating CSS Properties
The `css` property is an array of CSS properties you want to generate with their `conditions`.
You can specify the following options:
- `properties`: the CSS properties you want to generate
- `conditions`: the CSS conditions or selectors you want to generate in addition to the default values. Values can be
`light, dark`, etc.
- `responsive`: whether or not to generate responsive classes
- `values`: the values you want to generate for the CSS property. When set to `*`, all values defined in the tokens will
be included. When set to an array, only the values in the array will be generated.
```js
export default {
staticCss: {
css: [
{
properties: {
margin: ['*'],
padding: ['*', '50px', '80px']
},
responsive: true
},
{
properties: {
color: ['*'],
backgroundColor: ['green.200', 'red.400']
},
conditions: ['light', 'dark']
}
]
}
}
```
## Generating Recipes
The `recipes` property is an object of component recipes you want to generate with their `conditions`.
```js
export default {
staticCss: {
recipes: {
button: [
{
size: ['sm', 'md'],
responsive: true
},
{ variant: ['*'] }
],
// shorthand for all variants
tooltip: ['*']
}
}
}
```
You can also directly specify a recipe's `staticCss` rules from inside a recipe config, e.g.:
```js
import { defineRecipe } from '@pandacss/dev'
const card = defineRecipe({
className: 'card',
base: { color: 'white' },
variants: {
size: {
small: { fontSize: '14px' },
large: { fontSize: '18px' }
}
},
staticCss: [{ size: ['*'] }]
})
```
would be the equivalent of defining it inside the main config:
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
recipes: {
card: {
size: ['*']
}
}
}
})
```
Or you could even generate the CSS for every config `recipe` / `slotRecipes` (and each of their variants):
```tsx filename="panda.config.ts"
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
staticCss: {
recipes: '*'
}
})
```
This is mostly useful for testing purposes with [`Storybook`](/docs/installation/storybook).
## Removing unused CSS
For an even smaller css output size, you can utilize [PurgeCSS](https://purgecss.com/) to treeshake and remove unused
CSS. This tool will analyze your template and match selectors against your CSS.
---
# Migration
## Migrating from Stitches
Migrate your project from Stitches to Panda.
This guide helps you migrate from Stitches to Panda and understand the design differences between the libraries.
> **Disclaimer:** This isn't about comparing which one is best. Panda and Stitches are two different CSS-in-JS solutions
> with design decisions.
Here are some similarities between the two libraries.
- Panda uses the object literal syntax to define styles. It also supports the shorthand syntax for the `margin` and
`padding` properties.
- Panda supports the `variants`, `defaultVariants` and `compoundVariants` APIs.
- Panda supports design tokens and themes.
- Panda supports all the variants of nested selectors (attribute, class, pseudo, descendant, child, sibling selectors
and more). It also requires the use of the `&` to chain selectors.
Below are some of the differences between the two libraries.
## css function
In Stitches, the `css` function is used to author both regular style objects and variant style objects.
```tsx
import { css } from '@stitches/react'
// definition
const styles = css({
border: 'solid 1px red',
backgroundColor: 'transparent',
variants: {
variant: {
// ...
}
}
})
// usage
```
In Panda, the `css` function is only used to author atomic styles, and the `cva` function to create variant style
objects.
**The css function**
```tsx
import { css } from '../styled-system/css'
// definition
const styles = css({
border: 'solid 1px red',
backgroundColor: 'transparent'
})
// usage
```
**The cva function**
```tsx
import { cva } from '../styled-system/css'
// definition
const styles = cva({
base: {
border: 'solid 1px red',
backgroundColor: 'transparent'
},
variants: {
variant: {
// ...
}
}
})
// usage
```
## styled function
In Stitches, the `styled` function can be used to create components that are bound to both regular and variant styles
objects.
```tsx
import { styled } from '@stitches/react'
const Button = styled('button', {
// base styles
backgroundColor: 'gainsboro',
borderRadius: '9999px',
variants: {
// variant styles
}
})
```
In Panda, the base styles object needs to added to the `base` key.
```tsx
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
// base styles
base: {
backgroundColor: 'gainsboro',
borderRadius: '9999px'
},
variants: {
// variant styles
}
})
```
In Stitches, the styled function generates a unique className for each variant.
```tsx
import { styled } from '@stitches/react'
const Button = styled('button', {})
// =>
```
In Panda, you can decide if you want unique classNames for the recipe or you want atomic classNames.
- **Atomic classes** using the `cva` function or defining the recipe inline in the `styled` function
```tsx
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
base: {
backgroundColor: 'gainsboro',
borderRadius: '9999px'
}
})
// =>
```
- **Selector classes** by defining the recipe in the `panda.config.ts` file. This approach only generates the classes
and css for the variants that are used in the project.
```ts
import { defineConfig, defineRecipe } from '@pandacss/dev'
const buttonStyle = defineRecipe({
className: 'button',
base: {
backgroundColor: 'gainsboro',
borderRadius: '9999px'
},
variants: {
// variant styles
}
})
export default defineConfig({
theme: {
extend: {
recipes: {
buttonStyle
}
}
}
})
```
> You might need to run `panda codegen --clean` to generate the recipe functions.
```tsx
import { styled } from '../styled-system/jsx'
import { buttonStyle } from '../styled-system/recipes'
// create a styled component using the recipe function
const Button = styled('button', buttonStyle)
// or you can use directly in the JSX
// =>
```
## Responsive Styles
In Stitches, you configure breakpoints in the `media` key of the `createStitches` method, and use it via the
`@` syntax.
```ts
import { createStitches } from '@stitches/react'
// configure
const { styled, css } = createStitches({
media: {
bp1: '(min-width: 640px)',
bp2: '(min-width: 768px)'
}
})
// usage
const styles = css({
backgroundColor: 'gainsboro',
'@bp1': {
backgroundColor: 'tomato'
}
})
```
In Panda, you configure breakpoints in the `theme.breakpoints` key of the `panda.config` function
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
breakpoints: {
bp1: '640px',
bp2: '768px'
}
}
}
})
// usage
import { css } from '../styled-system/css'
const styles = css({
bg: 'gainsboro',
bp1: { bg: 'tomato' },
// or
margin: { base: '10px', bp1: '20px' }
})
```
In Stitches, you use the `@initial` keyword to target the base styles.
In Panda, you use the `base` key to target the base styles.
## Tokens and Theme
### Tokens
In Stitches, tokens are defined in the `theme` key of the `createStitches` method.
```ts
import { createStitches } from '@stitches/react'
const { styled, css } = createStitches({
theme: {
colors: {
gray100: 'hsl(206,22%,99%)',
gray200: 'hsl(206,12%,97%)'
}
},
space: {},
fonts: {}
})
// usage
const styles = css({
backgroundColor: '$gray100'
})
```
In Panda, tokens are defined in the `theme` key of the `panda.config` function.
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
tokens: {
colors: {
gray100: { value: 'hsl(206,22%,99%)' },
gray200: { value: 'hsl(206,12%,97%)' }
},
spacing: {},
fonts: {}
},
semanticTokens: {
// ...
}
}
})
// usage
import { css } from '../styled-system/css'
const styles = css({
backgroundColor: 'gray100'
})
```
Notice that in Panda, you don't need to use the `$` prefix to access the tokens. If you really want to use the `$`
prefix, you can either update the name of the token:
```diff
export default defineConfig({
theme: {
colors: {
- gray100: { value: 'hsl(206,22%,99%)' },
+ $gray100: { value: 'hsl(206,22%,99%)' },
},
}
})
```
Or you can tweak the token engine to format them with the `$` prefix:
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// ...
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: path => '$' + path.join('-')
})
}
}
})
```
### Themes
In Stitches, the `createTheme` function is used to define dark theme values.
```tsx
import { createStitches } from '@stitches/react'
const { createTheme } = createStitches({})
// create theme
const darkTheme = createTheme({
colors: {
gray100: 'hsl(206,8%,12%)',
gray200: 'hsl(206,7%,14%)'
}
})
// apply theme
Content nested in dark theme.
```
In Panda, themes are designed as semantic tokens. You can define the semantic tokens in the `semanticTokens` key of the
`panda.config` function.
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
semanticTokens: {
colors: {
gray100: {
value: { base: 'hsl(206,22%,99%)', _dark: 'hsl(206,8%,12%)' }
},
gray200: {
value: { base: 'hsl(206,12%,97%)', _dark: 'hsl(206,7%,14%)' }
}
}
}
}
})
```
### Token Aliases
In Stitches, you can create locally scoped tokens using the `$$` prefix
```ts
import { styled } from '@stitches/react'
const Button = styled('button', {
$$shadowColor: '$colors$pink500',
boxShadow: '0 0 0 15px $$shadowColor'
})
```
In Panda, there's no special syntax, you need to use the css variable syntax. CSS variables are able to query the theme
tokens directly using dot notation
```ts
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
base: {
'--shadowColor': 'colors.pink500',
boxShadow: '0 0 0 15px var(--shadowColor)'
}
})
```
## Animations
In Stitches, you can define keyframes using the `keyframes` method.
```ts
import { keyframes, styled } from '@stitches/react'
const scaleUp = keyframes({
'0%': { transform: 'scale(1)' },
'100%': { transform: 'scale(1.5)' }
})
// usage
const Button = styled('button', {
'&:hover': {
animation: `${scaleUp} 200ms`
}
})
```
In Panda, you define keyframes in the `theme.keyframes` key of the `panda.config` function.
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
keyframes: {
scaleUp: {
'0%': { transform: 'scale(1)' },
'100%': { transform: 'scale(1.5)' }
}
}
}
}
})
// usage
import { css } from '../styled-system/css'
const style = css({
'&:hover': {
animation: 'scaleUp 200ms'
}
})
```
## Utils
In Stitches, you can define utilities by using the `utils` key in the `createStitches` method.
```ts
import { createStitches, type PropertyValue } from '@stitches/react'
const { styled, css } = createStitches({
utils: {
linearGradient: (value: PropertyValue<'backgroundImage'>) => ({
backgroundImage: `linear-gradient(${value})`
})
}
})
```
In Panda, you get a lot of built-in utilities (like mx, marginX, my, py, etc.) that you can use out of the box. You can
also create custom utilites using the `utilities` key in the `panda.config` function.
The utilities API allows you define the connected token scale, generated className, and transform function.
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
utilities: {
extend: {
linearGradient: {
// (optional): the css property this maps to (to inherit the types from)
property: 'backgroundImage',
// (optional): the className to generate
className: 'bg_gradient',
// (optional): the shorthand name to use in the css
shorthand: 'gradient',
// (required): maps the value to the raw css object
transform: value => ({
backgroundImage: `linear-gradient(${value})`
})
}
}
}
})
```
> Running `panda codegen` will update the typings for the utilities, allowing for a type-safe developer experience.
Then you can use the utility in your styles.
```tsx
import { css } from '../styled-system/css'
const buttonClass = css({
linearGradient: '19deg, #21D4FD 0%, #B721FF 100%'
})
```
## Global Styles
In Stitches, you define the global styles using the `globalCss` function, and then call it in your app.
```tsx
import { globalCss } from '@stitches/react'
const globalStyles = globalCss({
'*': { margin: 0, padding: 0 }
})
// then in your app
globalStyles()
```
In Panda, you define the global styles in the `panda.config.ts` using the `globalCss` function.
> The styles be injected automatically under the `base` cascade layer via PostCSS
```ts {3-5}
import { defineConfig, defineGlobalStyles } from '@pandacss/dev'
const globalCss = defineGlobalStyles({
'*': { margin: 0, padding: 0 }
})
export default defineConfig({
// ...
globalCss
})
```
## Targeting Components
In Stitches, you can directly target React or styled components via the `toString()` method.
```tsx
import { css } from '@stitches/react'
const Icon = () => (
);
// add a `toString` method
Icon.toString = () => '.right-arrow';
const buttonClass = css({
[`& ${Icon}`]: {
marginLeft: '5px'
}
})
```
In Panda, you need to use the native selector directly. This is largely due to the static nature of Panda
```tsx
import { css } from '../styled-system/css'
const Icon = () => (
);
const buttonClass = css({
"& .right-arrow": {
marginLeft: '5px'
}
})
```
## Server Side Rendering
In Stitches, you need to configure the server-side rendering for your framework.
```tsx
// stitches.config.ts
import { createStitches } from '@stitches/react'
export const { getCssText } = createStitches()
// _document.tsx
export default class Document extends NextDocument {
render() {
return (
)
}
}
```
In Panda, you don't need to configure anything. Panda automatically extracts the styles and injects them at build time
using PostCSS.
## Conclusion
Before choosing your preferred CSS-in-JS library, be sure to consider your engineering and design goals. Both Stitches
and Panda are capable of achieving many of the same styling goals, but they have different approaches.
---
## Migrating from Styled Components
Migrate your project from Styled Components to Panda.
This guide outlines the steps needed to migrate your project from Styled Components to Panda and highlights key design
differences between the two libraries.
> **Disclaimer:** This isn't about comparing which one is best. Panda and Styled Components are two different CSS-in-JS
> solutions with design decisions.
Here are some similarities between the two libraries.
- Both libraries support the use of tagged template literals or object syntax to style components.
- Both libraries provide a way to define design tokens (variables) and use them in your styles.
- Both libraries require the use of `&` for nested selectors.
Below are some differences between the two libraries.
## Installation and Syntax
In styled-components, you can use both tagged template literals and object syntax to style components.
In Panda, you need to decide which syntax you want to use. Panda recommends using the object syntax, but provides a way
to opt-in to tagged template literals.
To initialize a project with the object syntax, run the following command.
```bash
panda init -p --jsx-framework react
```
To initialize a project with the tagged template literal syntax, run the following command.
```bash
panda init -p --syntax template-literal --jsx-framework react
```
Then you need to add the cascade layers to the global styles of your project.
```css
@layer reset, base, tokens, recipes, utilities;
```
## Tagged Template Syntax
In styled-components, the recommended way to style components is to use tagged template literals.
```jsx
import styled from 'styled-components'
const Button = styled.button`
background-color: #fff;
border: 1px solid #000;
color: #000;
padding: 0.5rem 1rem;
`
```
In Panda, you will use the autogenerate code in the `styled-system` directory at the root of your project.
> Remember to initialize your project with the `--syntax template-literal` flag or update the panda.config.ts file.
```jsx
import { styled } from '../styled-system/jsx'
const Button = styled.button`
background-color: #fff;
border: 1px solid #000;
color: #000;
padding: 0.5rem 1rem;
`
```
## Object Syntax
In styled-components, you can use the object syntax to style components.
```jsx
import styled from 'styled-components'
const Button = styled.button({
backgroundColor: '#fff',
border: '1px solid #000',
color: '#000',
padding: '0.5rem 1rem'
})
```
In Panda, you add the style object to the `base` key of the style object. The `styled` factory allows you define base
styles, variants and compound variants of your component.
```jsx
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
base: {
backgroundColor: '#fff',
border: '1px solid #000',
color: '#000',
padding: '0.5rem 1rem'
}
})
```
## Prop Interpolation
In styled-components, you can interpolate the component's props to conditionally set styles.
```jsx
const Button = styled.button`
${props =>
props.color === 'violet' &&
`
background-color: 'blueviolet'
`}
${props =>
props.color === 'gray' &&
`
background-color: 'gainsboro'
`}
`
```
In Panda, we model interpolations using the variants API. This allows define style groups or recipes that can be applied
to components.
````jsx
const Button = styled('button', {
variants: {
color: {
violet: css`
background-color: blueviolet;
`,
gray: css`
background-color: gainsboro;
`
}
}
})
// Usage
``` -->
## Tokens and Themes
### Defining Tokens
In styled-components, you can define tokens in a theme object that is passed to the `ThemeProvider`.
This requires the use of React's context API to access the theme object in your styles
```tsx
import { ThemeProvider } from 'styled-components'
const theme = {
colors: {
primary: 'blue',
secondary: 'red'
}
}
const App = () => (
)
````
In Panda, you define tokens in the `theme` key of the `panda.config.ts` file. This allows you to access the tokens in
your styles without the need for React's context API.
```tsx
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
colors: {
primary: { value: 'blue' },
secondary: { value: 'red' }
}
}
}
}
})
```
### Using Tokens
In styled-components, you can use tokens in your styles using a function approach that provides the `theme` prop, and
requires ambient type declarations to get type safety.
```tsx
import styled from 'styled-components'
// link.tsx
const StyledLink = styled.a(({ theme }) => ({
color: theme.colors.primary,
display: 'block',
textDecoration: 'none'
}))
// theme.d.ts
declare module 'styled-components' {
export interface DefaultTheme {
colors: {
primary: string
secondary: string
}
}
}
```
In Panda, the tokens are automatically available in your styles and connected to each css property, removing the need
for an interpolation function.
```tsx
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
// extend the base theme
extend: {
tokens: {
// add custom colors
colors: {
primary: { value: 'blue' },
secondary: { value: 'red' }
}
}
}
}
})
// link.tsx
import { styled } from '../styled-system/jsx'
const StyledLink = styled('a', {
base: {
color: 'primary',
display: 'block',
textDecoration: 'none'
}
})
```
## Responsive Styles
### Tagged Template Syntax
In styled-components, you need to write the media query styles manually or use a helper function like
`styled-media-query`.
```tsx
import styled from 'styled-components'
const Button = styled.button`
background-color: #fff;
border: 1px solid #000;
color: #000;
padding: 0.5rem 1rem;
@media (min-width: 768px) {
padding: 1rem 2rem;
}
`
```
In Panda, it's pretty much the same thing except that you can't do any interpolation in the media query styles due the
static nature of Panda.
```tsx
import { styled } from '../styled-system/jsx'
const Button = styled.button`
background-color: #fff;
border: 1px solid #000;
color: #000;
padding: 0.5rem 1rem;
@media (min-width: 768px) {
padding: 1rem 2rem;
}
`
```
### Object Syntax
In styled-components, you can use the `styled-media-query` helper function to write responsive styles.
```tsx
import styled from 'styled-components'
import media from 'styled-media-query'
const Button = styled.button({
backgroundColor: '#fff',
border: '1px solid #000',
color: '#000',
padding: '0.5rem 1rem',
[media.greaterThan('medium')]: {
padding: '1rem 2rem'
}
})
```
In Panda, you can use the pseudo props API to define responsive styles.
```tsx
import { styled } from '../styled-system/jsx'
const Button = styled('button', {
base: {
backgroundColor: '#fff',
border: '1px solid #000',
color: '#000',
padding: { base: '0.5rem 1rem', md: '1rem 2rem' }
}
})
```
## Global Styles
In styled-components, you can use the `createGlobalStyle` function to define global styles.
```tsx
import { createGlobalStyle } from 'styled-components'
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
}
`
```
In Panda, you can use the `globalCss` key of the `panda.config.ts` file to define global styles. This will automatically
add styles to the project via PostCSS.
```tsx
// panda.config.ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
globalCss: {
body: {
margin: 0,
padding: 0
}
}
})
```
## Targeting Components
In styled-components, you can target existing styled components within the styled function
```tsx
import styled from 'styled-components'
const Link = styled.a`
background: papayawhip;
color: #bf4f74;
`
const Icon = styled.svg`
width: 48px;
height: 48px;
${Link}:hover & {
fill: rebeccapurple;
}
`
```
In Panda, you need to use the native selector directly. This is largely due to the static nature of Panda
```tsx
import { styled } from '../styled-system/jsx'
const Link = styled.a`
background: papayawhip;
color: #bf4f74;
`
const Icon = styled.svg`
width: 48px;
height: 48px;
.Link:hover & {
fill: rebeccapurple;
}
`
const App = () => (
)
```
## Animations
In styled components, you can define keyframes using the `keyframes` method.
```ts
import styled, { keyframes } from 'styled-components'
const rotate = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`
// usage
const Button = styled.button`
&:hover {
animation: ${rotate} 200ms;
}
`
```
In Panda, you define keyframes in the `theme.keyframes` key of the `panda.config` function.
```ts
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
keyframes: {
rotate: {
from: {
transform: 'rotate(0deg)'
},
to: {
transform: 'rotate(360deg)'
}
}
}
}
}
})
// usage
import { styled } from '../styled-system/jsx'
const Button = styled.button`
&:hover {
animation: rotate 200ms;
}
`
```
## Server-Side Rendering
In styled components, you need to configure the server-side rendering for your framework.
```tsx
import { renderToString } from 'react-dom/server'
import { ServerStyleSheet } from 'styled-components'
const sheet = new ServerStyleSheet()
try {
const html = renderToString(sheet.collectStyles())
const styleTags = sheet.getStyleTags() // or sheet.getStyleElement();
} catch (error) {
// handle error
console.error(error)
} finally {
sheet.seal()
}
```
In Panda, you don't need to configure anything. Panda automatically extracts the styles and injects them at build time
using PostCSS.
## Conclusion
Before choosing your preferred CSS-in-JS library, be sure to consider your engineering and design goals. Both Styled
components and Panda are capable of achieving many of the same styling goals, but they have different approaches.
---
## Migrating from Theme UI
Migrate your project from Theme UI to Panda.
This guide outlines the steps needed to migrate your project from Theme UI to Panda and highlights key design
differences between the two libraries.
Here are some similarities between the two libraries.
- Panda and Theme UI both support JSX style props.
- Supports design tokens and themes.
- Support for styling primitives like `Box`, `Flex`, `Grid`, etc.
Below are some of the differences between the two libraries.
## Performance
Theme UI relies on `@emotion/styled` to style components. This means that every time you use the `sx` prop, runtime
CSS-in-JS is required to compute the styles in the browser. This can lead to performance issues in larger applications.
Panda relies on `postcss` and converts CSS-in-JS styles to static CSS at build-time, leading to better performance in
larger applications.
## Theming
In Theme UI, you need to wrap your application in a `ThemeProvider` component which is a wrapper around `@emotion/react`
theme context.
```jsx
import { ThemeProvider } from 'theme-ui'
const theme = {
fonts: {
body: 'system-ui, sans-serif',
heading: '"Avenir Next", sans-serif'
},
colors: {
text: '#000',
background: '#fff'
}
}
export default function App({ Component, pageProps }) {
return (
)
}
```
In Panda, you don't need to wrap your application in a `ThemeProvider` component. Instead, you can pass the theme object
to the `panda.config.js` file.
The theme object in Panda is broken down into multiple parts, `tokens` and `semanticTokens`. The theme specification
also required passing the tokens as `{ value: XX }`
```js
// panda.config.js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
tokens: {
fonts: {
body: { value: 'system-ui, sans-serif' },
heading: { value: '"Avenir Next", sans-serif' }
},
colors: {
text: { value: '#000' },
background: { value: '#fff' }
}
}
}
}
})
```
## The `sx` prop
In Theme UI, you can use the `sx` prop to style any component when you add the `jsxImportSource` pragma to the top of
your file.
```jsx
/** @jsxImportSource theme-ui */
export const Demo = props => (
)
```
Panda offers three similar ways to style components. The first approach is to use the `styled` element syntax and rename
`sx` to `css`
```jsx
import { styled } from 'styled-system/jsx'
export const Demo = props => (
)
```
The second approach is to create styled components using the `styled` function. This approach allows you to create style
variants.
```jsx
import { styled } from 'styled-system/jsx'
export const Demo = styled('div', {
base: {
color: 'white',
bg: 'primary',
fontSize: 4
}
})
```
The simplest approach is to use the `css` function to write one-off styles.
```jsx
import { css } from 'styled-system/css'
export const Demo = props => (
)
```
## Variants
In Theme UI, variants are used to create groups of styles based on the theme. It offers variant groups in the theme for
several components.
- `Grid` maps to `theme.grids`
- `Button`, `IconButton` maps to `theme.buttons`
- `NavLink`, `Link` maps to `theme.links`
- `Input`, `Select`, `Textarea` maps to `theme.forms`
- `Heading`, `Text` maps to `theme.text`
```js
// theme.js
export default {
colors: {
primary: '#07c',
secondary: '#30c',
accent: '#609'
},
buttons: {
primary: {
color: 'white',
bg: 'primary'
},
secondary: {
color: 'white',
bg: 'secondary'
},
accent: {
color: 'white',
bg: 'accent'
}
}
}
// Button.js
```
In Panda, multi-variant styles are referred to as recipes. Recipes are a collection of styles that can be applied to any
component.
There are two ways to define recipes in Panda. The first approach is to use the `cva` function which produces atomic
classnames.
```js
import { cva } from 'styled-system/css'
const buttonStyles = cva({
base: {
display: 'inline-flex'
},
variants: {
variant: {
primary: {
color: 'white',
bg: 'primary'
},
secondary: {
color: 'white',
bg: 'secondary'
},
accent: {
color: 'white',
bg: 'accent'
}
}
}
})
const Demo = () => (
)
```
The second approach is to define the recipe in the `theme.recipes` property of the panda config. This is referred to as
'Config recipes' in Panda and allows for sharing recipes across components and projects.
```js
// panda.config.js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
recipes: {
button: {
className: 'button',
base: { display: 'inline-flex' },
variants: {
variant: {
primary: { color: 'white', bg: 'primary' },
secondary: { color: 'white', bg: 'secondary' },
accent: { color: 'white', bg: 'accent' }
}
}
}
}
}
}
})
// Button.js
import { button } from 'styled-system/recipes'
const Demo = () =>
```
## Color Modes
In Theme UI, colors modes can be used to create a user-configurable light and dark mode values that are automatically
applied to components depending on color mode.
```jsx
// theme.js
const theme = {
colors: {
primary: '#07c',
modes: {
dark: {
primary: '#0cf'
}
}
}
}
// Button.js
const Demo = () =>
```
In Panda, color modes related values are defined as `semanticTokens` in the theme. Semantic tokens are tokens that
change depending on the color mode.
```js
// panda.config.js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
theme: {
extend: {
semanticTokens: {
colors: {
primary: { value: { base: '#07c', _dark: '#0cf' } }
}
}
}
}
})
// Button.js
import { css } from 'styled-system/css'
const Demo = () => (
)
```
## Global Styles
Theme UI offers a Global component (that wraps Emotionβs) for adding global CSS with theme-based values.
```jsx
import { Global } from 'theme-ui'
export default props => (
)
```
In Panda, global styles are defined in the `theme.global` property of the panda config.
```js
// panda.config.js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
globalCss: {
button: {
m: 0,
bg: 'primary',
color: 'background',
border: 0
}
}
})
```
## Component Styles
Theme UI offers pre-defined layout components like `Box`, `Stack`, `Grid`, `Flex`
```jsx
import { Box, Grid } from 'theme-ui'
const Demo = () => (
BoxBoxBoxBox
)
```
In Panda, these are called "layout patterns", or "patterns" for short. Panda provides similar patterns that can be used
as a function or JSX element just like Theme UI.
```jsx
import { Box, Grid } from 'styled-system/jsx'
const Demo = () => (
BoxBox
)
```
The function approach can be handy as well
```jsx
import { css } from 'styled-system/css'
import { grid } from 'styled-system/patterns'
const Demo = () => (
Box
Box
)
```
---
# References
## CLI Reference
You can use the Command-Line Interface (CLI) provided by Panda to develop, build, and preview your project from a terminal window.
Use Panda's Command-Line Interface (CLI) to develop, build, and preview your project from a terminal.
## init
Initialize Panda in a project. This process will:
- Create a `panda.config.ts` file in your project with the default settings and presets.
- Emit CSS utilities for your project in the specified `output` directory.
| Flag | Description | Related |
| ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------- |
| `--interactive, -i` | Whether to run the interactive mode | - |
| `--force, -f` | Whether to overwrite existing files | - |
| `--postcss, -p` | Whether to emit a [postcss](https://postcss.org/) config file | - |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config) |
| `--cwd ` | Path to current working directory | - |
| `--silent` | Whether to suppress all output | - |
| `--no-gitignore` | Whether to update gitignore with the output directory | - |
| `--no-codegen` | Whether to run the codegen process | - |
| `--out-extension ` | The extension of the generated js files (default: 'mjs') | [`config.outExtension`](/docs/references/config#outextension) |
| `--outdir ` | The output directory for the generated files | [`config.outdir`](/docs/references/config#outdir) |
| `--jsx-framework ` | The jsx framework to use | [`config.jsxFramework`](/docs/references/config#jsxframework) |
| `--syntax ` | The css syntax preference | [`config.syntax`](/docs/references/config#syntax) |
| `--strict-tokens` | Set strictTokens to true | [`config.strictTokens`](/docs/references/config#stricttokens) |
| `--logfile ` | Outputs logs to a file | [Debugging](/docs/guides/debugging) |
---
## panda
Run the extract process to generate static CSS from your project.
By default it will scan and generate CSS for the entire project depending on your include and exclude options from your
config file.
```bash
pnpm panda
# You can also scan a specific file or folder
# using the optional glob argument
pnpm panda src/components/Button.tsx
pnpm panda "./src/components/**"
```
| Flag | Description | Related |
| ----------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `--outdir, -o [dir]` | The output directory for the generated CSS utilities | [`config.outdir`](/docs/references/config#outdir) |
| `--minify, -m` | Whether to minify the generated CSS | [`config.minify`](/docs/references/config#minify) |
| `--watch, -w` | Whether to watch for changes in the project | [`config.watch`](/docs/references/config#watch) |
| `--poll` | Whether to poll for file changes | [`config.poll`](/docs/references/config#poll) |
| `--config, -c ` | The path to the config file | [`config`](/docs/references/config.md) |
| `--cwd ` | The current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--preflight` | Whether to emit the preflight or reset CSS | [`config.preflight`](/docs/references/config#preflight) |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--exclude, -e ` | Files to exclude from the extract process | [`config`](/docs/references/config.md) |
| `--clean` | Whether to clean the output directory before emitting | [`config.clean`](/docs/references/config#clean) |
| `--hash` | Whether to hash the output classnames | [`config.hash`](/docs/references/config#hash) |
| `--lightningcss` | Use `lightningcss` instead of `postcss` for css optimization | [`config.lightningcss`](/docs/references/config#lightningcss) |
| `--polyfill` | Polyfill CSS @layers at-rules for older browsers | [`config.polyfill`](/docs/references/config#polyfill) |
| `--emitTokensOnly` | Whether to only emit the `tokens` directory | [`config.emitTokensOnly`](/docs/references/config#emittokensonly) |
| `--cpu-prof` | Generate a `panda-{command}-{timestamp}.cpuprofile` file for profiling | [Debugging](/docs/guides/debugging) |
| `--logfile ` | Outputs logs to a file | [Debugging](/docs/guides/debugging) |
---
## codegen
Generate new CSS utilities for your project based on the configuration file.
| Flag | Description | Related |
| --------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------ |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--clean` | Whether to clean the output directory before emitting | [`config.clean`](/docs/references/config#clean) |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--watch, -w` | Whether to watch for changes in the project | [`config.watch`](/docs/references/config#watch) |
| `--poll, -p` | Whether to poll for file changes | [`config.poll`](/docs/references/config#poll) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--cpu-prof` | Generate a `panda-{command}-{timestamp}.cpuprofile` file for profiling | [Debugging](/docs/guides/debugging) |
| `--logfile ` | Outputs logs to a file | [Debugging](/docs/guides/debugging) |
## cssgen
Generate the CSS from files.
You can use a `glob` to override the `config.include` option like this:
`panda cssgen "src/**/*.css" --outfile dist.css`
or you can use it with a `{type}` argument to generate only a specific type of CSS:
- preflight
- tokens
- static
- global
- keyframes
> Note that this only works when passing an `--outfile`.
You can use it like this:
```bash
panda cssgen "static" --outfile dist/static.css
```
| Flag | Description | Related |
| ---------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------- |
| `--outfile, -o ` | Output file for extracted css, default to './styled-system/styles.css' | - |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--minify, -m` | Whether to minify the generated CSS | [`config.minify`](/docs/references/config#minify) |
| `--clean` | Whether to clean the output directory before emitting | [`config.clean`](/docs/references/config#clean) |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--watch, -w` | Whether to watch for changes in the project | [`config.watch`](/docs/references/config#watch) |
| `--minimal` | Skip generating CSS for theme tokens, preflight, keyframes, static and global css | - |
| `--poll, -p` | Whether to poll for file changes | [`config.poll`](/docs/references/config#poll) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--lightningcss` | Use `lightningcss` instead of `postcss` for css optimization | [`config.lightningcss`](/docs/references/config#lightningcss) |
| `--polyfill` | Polyfill CSS @layers at-rules for older browsers | [`config.polyfill`](/docs/references/config#polyfill) |
| `--cpu-prof` | Generate a `panda-{command}-{timestamp}.cpuprofile` file for profiling | [Debugging](/docs/guides/debugging) |
| `--logfile ` | Outputs logs to a file | [Debugging](/docs/guides/debugging) |
## studio
Realtime documentation for your design tokens.
| Flag | Description | Related |
| --------------------- | --------------------------------- | ------------------------------------------- |
| `--build` | Build | - |
| `--preview` | Preview | - |
| `--port ` | Use custom port | - |
| `--host` | Expose to custom host | - |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--outdir ` | Output directory for static files | - |
| `--base ` | Base path of project | - |
## analyze
Analyze design token and recipe usage.
By default, it will analyze your project based on the `include` and `exclude` config options.
```bash
pnpm panda analyze
# analyze a specific file
pnpm panda analyze src/components/Button.tsx
# analyze a specific glob
pnpm panda analyze "src/components/**"
```
| Flag | Description | Related |
| ---------------------- | -------------------------------------------- | ------------------------------------------------------ |
| `--outfile ` | Output analyze report in given JSON filepath | - |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
## debug
Debug design token extraction & CSS generated from files in glob.
More details in [Debugging](/docs/guides/debugging) docs.
| Flag | Description | Related |
| --------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------- |
| `--silent` | Whether to suppress all output | - |
| `--dry` | Output debug files in stdout without writing to disk | - |
| `--outdir ` | Output directory for debug files, defaults to `../styled-system/debug` | - |
| `--only-config` | Should only output the config file, default to 'false' | - |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--cpu-prof` | Generate a `panda-{command}-{timestamp}.cpuprofile` file for profiling | [Debugging](/docs/guides/debugging#performance-profiling) |
| `--logfile ` | Outputs logs to a file | [Debugging](/docs/guides/debugging) |
## ship
Ship extract result from files in glob.
By default it will extract from the entire project depending on your include and exclude options from your config file.
```bash
pnpm panda ship
# You can also analyze a specific file or folder
# using the optional glob argument
pnpm panda ship src/components/Button.tsx
pnpm panda ship "./src/components/**"
```
| Flag | Description | Related |
| ---------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `--outfile ` | Output path for the JSON build info file, default to './styled-system/panda.buildinfo.json' | - |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--minify, -m` | Whether to minify the generated JSON | - |
| `--config, -c ` | Path to Panda config file | [`config`](/docs/references/config.md) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
| `--watch, -w` | Whether to watch for changes in the project | [`config.watch`](/docs/references/config#watch) |
| `--poll, -p` | Whether to poll for file changes | [`config.poll`](/docs/references/config#poll) |
## emit-pkg
Emit package.json with entrypoints, can be used to create a workspace package dedicated to the
[`config.outdir`](/docs/references/config#outdir), in combination with
[`config.importMap`](/docs/references/config#importmap)
| Flag | Description | Related |
| ---------------- | ---------------------------------------------------- | ------------------------------------------------------ |
| `--outdir ` | The output directory for the generated CSS utilities | [`config.outdir`](/docs/references/config#outdir) |
| `--base ` | The base directory of the package.json entrypoints | - |
| `--silent` | Whether to suppress all output | [`config.logLevel`](/docs/references/config#log-level) |
| `--cwd ` | Current working directory | [`config.cwd`](/docs/references/config#cwd) |
---
## Configuring Panda
Customize how Panda works via the `panda.config.ts` file in your project.
Customize how Panda works via the `panda.config.ts` file in your project.
```js
import { defineConfig } from '@pandacss/dev'
export default defineConfig({
// your configuration options here...
})
```
## Output css options
### presets
**Type**: `string[]`
**Default**: `['@pandacss/preset-base', '@pandacss/preset-panda']`
The set of reusable and shareable configuration presets.
By default, any preset you add will be smartly merged with the default configuration, with your own configuration acting
as a set of overrides and extensions.
```json
{
"presets": ["@pandacss/preset-base", "@pandacss/preset-panda"]
}
```
### eject
**Type**: `boolean`
**Default**: `false`
Whether to opt-out of the defaults config presets: [`@pandacss/preset-base`, `@pandacss/preset-panda`]
```json
{
"eject": true
}
```
### preflight
**Type**: `boolean` | `{ scope: string; }`
**Default**: `false`
Whether to enable css reset styles.
Enable preflight:
```json
{
"preflight": true
}
```
You can also scope the preflight; Especially useful for being able to scope the CSS reset to only a part of the app for
some reason.
Enable preflight and customize the scope:
```json
{
"preflight": { "scope": ".extension" }
}
```
The resulting `reset` css would look like this:
```css
.extension button,
.extension select {
text-transform: none;
}
.extension table {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
```
You can also set the level to `element` (defaults to `parent`) to only reset the elements that have the scope class
assigned.
```json
{
"preflight": { "scope": ".extension", "level": "element" }
}
```
The resulting `reset` css would look like this:
```css
button.extension,
select.extension {
text-transform: none;
}
table.extension {
text-indent: 0;
border-color: inherit;
border-collapse: collapse;
}
```
### emitTokensOnly
**Type**: `boolean`
**Default**: `false`
Whether to only emit the `tokens` directory
```json
{
"emitTokensOnly": false
}
```
### prefix
**Type**: `string`
The namespace prefix for the generated css classes and css variables.
Ex: when using a prefix of `panda-`
```json
{
"prefix": "panda"
}
```
```tsx
import { css } from '../styled-system/css'
const App = () => {
return
}
```
would result in:
```css
.panda-text_blue\.500 {
color: var(--panda-colors-blue-500);
}
```
### layers
**Type**: `Partial`
Cascade layers used in generated css.
Ex: when customizing the utilities layer
```json
{
"layers": {
"utilities": "panda_utilities"
}
}
```
```tsx
import { css } from '../styled-system/css'
const App = () => {
return
}
```
would result in:
```css
@layer panda_utilities {
.text_blue\.500 {
color: var(--colors-blue-500);
}
}
```
You should update the layer in your root css also.
### separator
**Type**: `'_' | '=' | '-'`
**Default**: `'_'`
The separator for the generated css classes.
```json
{
"separator": "_"
}
```
Using a `=` with:
```tsx
import { css } from '../styled-system/css'
const App = () => {
return
}
```
would result in:
```css
.text\=blue\.500 {
color: var(--colors-blue-500);
}
```
### minify
**Type**: `boolean`
**Default**: `false`
Whether to minify the generated css. This can be set to `true` to reduce the size of the generated css.
```json
{
"minify": false
}
```
### hash
**Type**: `boolean | { cssVar: boolean; className: boolean }`
**Default**: `false`
Whether to hash the generated class names / css variables. This is useful if want to shorten the class names or css
variables.
Hash the class names and css variables:
```json
{
"hash": true
}
```
This
```tsx
import { css } from '../styled-system/css'
const App = () => {
return
}
```
would result in something that looks like:
```css
.dOFUTE {
color: var(--cgpxvS);
}
```
You can also hash them individually.
E.g. only hash the css variables:
```json
{
"hash": { "cssVar": true, "className": false }
}
```
Then the result looks like this:
```css
.text_blue\.500 {
color: var(--cgpxvS);
}
```
Now only hash the class names:
```json
{
"hash": { "cssVar": false, "className": true }
}
```
Then the result looks like this:
```css
.dOFUTE {
color: var(--colors-blue-500);
}
```
## File system options
### gitignore
**Type**: `boolean`
**Default**: `true`
Whether to update the .gitignore file.
```json
{
"gitignore": true
}
```
Will add the following to your `.gitignore` file:
```txt
# Panda
styled-system
styled-system-static
```
### cwd
**Type**: `string`
**Default**: `process.cwd()`
The current working directory.
```json
{
"cwd": "src"
}
```
### clean
**Type**: `boolean`
**Default**: `false`
Whether to clean the output directory before generating the css.
```json
{
"clean": false
}
```
### outdir
**Type**: `string`
**Default**: `styled-system`
The output directory for the generated css.
```json
{
"outdir": "styled-system"
}
```
### importMap
**Type**: `string | Partial`
**Default**:
`{ "css": "styled-system/css", "recipes": "styled-system/recipes", "patterns": "styled-system/patterns", "jsx": "styled-system/jsx" }`
Allows you to customize the import paths for the generated outdir.
```json
{
"importMap": {
"css": "@acme/styled-system",
"recipes": "@acme/styled-system",
"patterns": "@acme/styled-system",
"jsx": "@acme/styled-system"
}
}
```
You can also use a string to customize the base import path and keep the default entrypoints:
```json
{
"importMap": "@scope/styled-system"
}
```
is the equivalent of:
```json
{
"importMap": {
"css": "@scope/styled-system/css",
"recipes": "@scope/styled-system/recipes",
"patterns": "@scope/styled-system/patterns",
"jsx": "@scope/styled-system/jsx"
}
}
```
Check out the [Component Library](/docs/guides/component-library) guide for more information on how to use the
`importMap` option.
### include
**Type**: `string[]`
**Default**: `[]`
List of files glob to watch for changes.
```json
{
"include": ["./src/**/*.{js,jsx,ts,tsx}", "./pages/**/*.{js,jsx,ts,tsx}"]
}
```
### exclude
**Type**: `string[]`
**Default**: `[]`
List of files glob to ignore.
```json
{
"exclude": []
}
```
### dependencies
**Type**: `string[]`
**Default**: `[]`
Explicit list of config related files that should trigger a context reload on change.
> We automatically track the config file and (transitive) files imported by the config file as much as possible, but
> sometimes we might miss some. You can use this option as a workaround for those edge cases.
```json
{
"dependencies": ["path/to/files/**.ts"]
}
```
### watch
**Type**: `boolean`
**Default**: `false`
Whether to watch for changes and regenerate the css.
```json
{
"watch": false
}
```
### poll
**Type**: `boolean`
**Default**: `false`
Whether to use polling instead of filesystem events when watching.
```json
{
"poll": false
}
```
### outExtension
**Type**: `'mjs' | 'js'`
**Default**: `mjs`
File extension for generated javascript files.
```json
{
"outExtension": "mjs"
}
```
### forceConsistentTypeExtension
**Type**: `boolean`
**Default**: `false`
Whether to force consistent type extensions for generated typescript .d.ts files.
If set to `true` and `outExtension` is set to `mjs`, the generated typescript `.d.ts` files will have the extension
`.d.mts`.
```json
{
"forceConsistentTypeExtension": true
}
```
### syntax
**Type**: `'object-literal' | 'template-literal'`
**Default**: `object-literal`
Decides which syntax to use when writing CSS. For existing projects, you might need to run the `panda codegen --clean`.
```json
{
"syntax": "template-literal"
}
```
Ex object-literal:
```tsx
const styles = css({
backgroundColor: 'gainsboro',
padding: '10px 15px'
})
```
Ex template-literal:
```tsx
const Container = styled.div`
background-color: gainsboro;
padding: 10px 15px;
`
```
### lightningcss
**Type**: `boolean`
**Default**: `false`
Whether to use `lightningcss` instead of `postcss` for css optimization.
```json
{
"lightningcss": true
}
```
### browserslist
**Type**: `string[]`
**Default**: `[]`
Browserslist query to target specific browsers. Only used when `lightningcss` is set to `true`.
```json
{
"browserslist": ["last 2 versions", "not dead", "not < 2%"]
}
```
### polyfill
**Type**: `boolean`
**Default**: `false`
Polyfill CSS @layers at-rules for older browsers.
```json
{
"polyfill": true
}
```
## Design token options
### shorthands
**Type**: `boolean`
**Default**: `true`
Whether to allow shorthand properties
```json
{
"shorthands": true
}
```
Ex `true`:
```tsx
const styles = css({
bgColor: 'gainsboro',
p: '10px 15px'
})
```
Ex false:
```tsx
const styles = css({
backgroundColor: 'gainsboro',
padding: '10px 15px'
})
```
### cssVarRoot
**Type**: `string`
**Default**: `:where(:host, :root)`
The root selector for the css variables.
```json
{
"cssVarRoot": ":where(:host, :root)"
}
```
### conditions
**Type**: `Extendable`
**Default**: `{}`
The css selectors or media queries shortcuts.
```json
{
"conditions": { "hover": "&:hover" }
}
```
### globalCss
**Type**: `Extendable`
**Default**: `{}`
The global styles for your project.
```json
{
"globalCss": {
"html, body": {
"margin": 0,
"padding": 0
}
}
}
```
### theme
**Type**: `Extendable`
**Default**: `{}`
The theme configuration for your project.
```json
{
"theme": {
"tokens": {
"colors": {
"red": { "value": "#EE0F0F" },
"green": { "value": "#0FEE0F" }
}
},
"semanticTokens": {
"colors": {
"danger": { "value": "{colors.red}" },
"success": { "value": "{colors.green}" }
}
}
}
}
```
### themes
**Type**: `Extendable`
**Default**: `{}`
The theme variants configuration for your project.
```json
{
"themes": {
"primary": {
"tokens": {
"colors": {
"text": { "value": "red" }
}
},
"semanticTokens": {
"colors": {
"muted": { "value": "{colors.red.200}" },
"body": {
"value": {
"base": "{colors.red.600}",
"_osDark": "{colors.red.400}"
}
}
}
}
},
"secondary": {
"tokens": {
"colors": {
"text": { "value": "blue" }
}
},
"semanticTokens": {
"colors": {
"muted": { "value": "{colors.blue.200}" },
"body": {
"value": {
"base": "{colors.blue.600}",
"_osDark": "{colors.blue.400}"
}
}
}
}
}
}
}
```
### utilities
**Type**: `Extendable`
**Default**: `{}`
The css utility definitions.
```js
{
"utilities": {
extend: {
borderX: {
values: ['1px', '2px', '4px'],
shorthand: 'bx', // `bx` or `borderX` can be used
transform(value, token) {
return {
borderInlineWidth: value,
borderColor: token('colors.red.200'), // read the css variable for red.200
}
},
},
},
}
}
```
### patterns
**Type**: `Extendable>`
**Default**: `{}`
Common styling or layout patterns for your project.
```js
{
"patterns": {
extend: {
// Extend the default `flex` pattern
flex: {
properties: {
// only allow row and column
direction: { type: 'enum', value: ['row', 'column'] },
},
},
},
},
}
```
### staticCss
**Type**: `StaticCssOptions`
**Default**: `{}`
Used to generate css utility classes for your project.
```js
{
"staticCss": {
css: [
{
properties: {
margin: ['*'],
padding: ['*', '50px', '80px'],
},
responsive: true,
},
{
properties: {
color: ['*'],
backgroundColor: ['green.200', 'red.400'],
},
conditions: ['light', 'dark'],
},
],
},
}
```
### strictTokens
**Type**: `boolean`
**Default**: `false`
Only allow token values and prevent custom or raw CSS values. Will only affect properties that have config tokens, such
as `color`, `bg`, `borderColor`, etc. [Learn more.](/docs/concepts/writing-styles#type-safety)
```json
{
"strictTokens": false
}
```
### strictPropertyValues
**Type**: `boolean`
**Default**: `false`
Only use valid CSS values for properties that do have a predefined list of values. Will throw for properties that do not
have config tokens, such as `display`, `content`, `willChange`, etc.
[Learn more.](/docs/concepts/writing-styles#type-safety)
```json
{
"strictPropertyValues": false
}
```
### globalFontface
**Type**: `GlobalFontfaceDefinition`
**Default**: `{}`
Global font face definitions.
```json
{
"globalFontface": {
"Inter": {
"src": "url(/fonts/inter.woff2) format('woff2')",
"fontWeight": "400",
"fontStyle": "normal"
},
"Roboto": {
"src": "url(/fonts/roboto.woff2) format('woff2')",
"fontWeight": "400",
"fontStyle": "normal"
}
}
}
```
Check out the [Custom Fonts](/docs/guides/fonts#global-font-face) guide for more information on how to use the
`globalFontface` option.
## JSX options
### jsxFramework
**Type**: `'react' | 'solid' | 'preact' | 'vue' | 'qwik' | (string & {})`
JS Framework for generated JSX elements.
```json
{
"jsxFramework": "react"
}
```
### jsxFactory
**Type**: `string`
The factory name of the element
```json
{
"jsxFactory": "panda"
}
```
Ex:
```tsx
Click me
```
### jsxStyleProps
**Type**: `all` | `minimal` | `none`
**Default**: `all`
The style props allowed on generated JSX components
- When set to 'all', all style props are allowed.
- When set to 'minimal', only the `css` prop is allowed.
- When set to 'none', no style props are allowed and therefore the `jsxFactory` will not be usable as a component:
- `` and `styled("div")` aren't valid
- but the recipe usage is still valid `styled("div", { base: { color: "red.300" }, variants: { ...} })`
Ex with 'all':
```jsx
Click me
```
Ex with 'minimal':
```jsx
Click me
```
Ex with 'none':
```jsx
```
## Documentation options
### studio
**Type**: `Partial`
**Default**: `{ title: 'Panda', logo: 'πΌ' }`
Used to customize the design system studio
```json
{
"studio": {
"logo": "πΌ",
"title": "Panda"
}
}
```
### log level
**Type**: `'debug' | 'info' | 'warn' | 'error' | 'silent'`
**Default**: `info`
The log level for the built-in logger.
```json
{
"logLevel": "info"
}
```
### validation
**Type**: `'none' | 'warn' | 'error'`
**Default**: `warn`
The validation strictness to use when validating the config.
- When set to 'none', no validation will be performed.
- When set to 'warn', warnings will be logged when validation fails.
- When set to 'error', errors will be thrown when validation fails.
```json
{
"validation": "error"
}
```
## Other options
### Hooks
**Type**: `PandaHooks`
Panda provides a set of callbacks that you can hook into for more advanced use cases. Check the
[Hooks](/docs/concepts/hooks) docs for more information.
### Plugins
**Type**: `PandaPlugin[]`
Plugins are currently simple objects that contain a `name` and a `hooks` object with the same structure as the `hooks`
object in the config.
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 '@pandacss/dev'
export default defineConfig({
// ...
plugins: [
{
name: 'token-format',
hooks: {
'tokens:created': ({ configure }) => {
configure({
formatTokenName: path => '$' + path.join('-')
})
}
}
}
]
})
```
---
---
_This is the complete Panda CSS documentation, automatically generated from the official sources._