Want to skip the docs? Check out pandamastery.com - the best way to learn Panda CSS

design systems
overview

Using Panda in a Component Library

How to build and ship a component library on Panda, from setup through packaging and troubleshooting.

A component library ships finished, styled components: a <Button>, a <Card>, a <Tabs>, ready to drop into any project that installs it. That's different from shipping a design system as a preset, a pure config package with no components at all, just the tokens and recipes another team builds their own components from. If you're not sure which one you're building, the difference is what you're shipping: compiled components mean you're on this page; pure definePreset config means you want Building a design system. If you own the apps and want one package plus designSystem, use Build a design system. Mature libraries often ship both, a components package built on top of their own preset, so it's not an either-or choice, just a question of which one you need first.

The rest of this section walks through building a component library on Panda, in the order you'll likely need it:

Quick answers

If you already know what you're looking for:

If you use the include-source-files or build-info approach and your library has custom tokens, recipes, or patterns, you'll likely still need to ship a preset alongside it.

FAQ

Why should my component library use an external styled-system package?

De-coupling the component library from its styled-system means your users share the same runtime code between your library and their app, instead of bundling two copies of css(), cva(), and the JSX factory.

component-lib/src/button.tsx

import { css } from '@acme-org/styled-system/css'
 
export function Button({ children, css: cssProp }) {
  return (
    <button type="button" className={css({ bg: 'red.300', px: '2', py: '3' }, cssProp)}>
      {children}
    </button>
  )
}

app/src/App.tsx

import { Button } from '@acme-org/design-system'
import { css } from '@acme-org/styled-system/css'
 
export function App() {
  return <Button css={{ color: 'white' }}>Click me</Button>
}

Marking the styled-system package as external in your build tool keeps that runtime code, the css function in the example above, imported once, not duplicated per package. See Set up a library package for the full setup.

How do I use the shared styled-system package day to day?

Like any other workspace dependency: install it, then set importMap in panda.config.ts to the same package name so Panda knows which imports belong to it.

pnpm add @acme-org/styled-system

panda.config.ts

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  //...
  importMap: '@acme-org/styled-system'
})

How do I override tokens used by the shared package?

Extend theme in your users' own panda.config.ts, same as overriding any preset's tokens:

panda.config.ts

import { defineConfig } from '@pandacss/dev'
 
export default defineConfig({
  //...
  presets: ['@acme-org/preset'],
  theme: {
    extend: {
      tokens: {
        colors: { primary: { value: 'blue.500' } }
      }
    }
  }
})

See Theme for the full set of things theme.extend can override, not just tokens.

See also