Installation

Add Pockets UI to a React app: install the package, point Panda CSS at the design system, generate the styled system, and start building.

1. Install the packages

@pockets-ui/components is the whole design system: the React components, the tokens and recipes, and a generated Panda styled system. Panda CSS itself is a dev dependency, plus the plugin for your bundler.

bun add @pockets-ui/components
bun add -D @pandacss/dev @pandacss/postcss
  • @pockets-ui/components — the React components, built on React Aria, and the Panda design system they are styled with (css(), tokens, recipes, patterns).
  • @pandacss/dev — Panda CSS (v2 or later; needs Node 22+). Generates the styled system and the CSS.
  • @pandacss/postcss — emits the CSS at build time. Use @pandacss/vite or @pandacss/bun instead if that is your bundler.
  • @pockets-ui/utils — framework utilities like createPocket, which wraps the React context boilerplate for compound-component state. Already a dependency of @pockets-ui/components; install it directly when you import from it yourself.

2. Point Panda at the design system

A panda.config.ts at your project root opts into the design system with one line. You only declare where your own app code lives.

import { defineConfig } from "@pandacss/dev"

export default defineConfig({
  designSystem: "@pockets-ui/components",
  include: ["./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}"],
})

Do not list @pockets-ui/components in include, and do not set prefix, hash, or separator — the design system owns those and Panda will refuse the config.

Then wire up the rest of the consumer contract:

  • postcss.config.mjs — registers the Panda plugin:

    export default { plugins: { "@pandacss/postcss": {} } }
  • package.json — a "prepare": "panda codegen" script (or predev / prebuild) so the styled system regenerates on every install.

  • app/globals.css — declares the cascade-layer order Panda emits into: @layer reset, base, tokens, recipes, utilities;

  • data-pockets-theme="light" (or "dark", "winter", "christmas") on a root element such as <html>.

3. Generate the styled system

Codegen writes a thin styled-system/ folder into your app: your own token-aware css() function and tokens, with jsx, recipes, and patterns re-exported from @pockets-ui/components. The prepare script runs it on install, but you can run it directly any time — for example after upgrading @pockets-ui/components or editing panda.config.ts.

bunx panda codegen

4. Use it

Import components from @pockets-ui/components and style your own elements with css() from your app's styled-system/css. Every property is typed against the token scales, and semantic tokens like bg and fg.subtle adapt to light and dark mode automatically.

import { Button } from "@pockets-ui/components"
import { css } from "./styled-system/css"

const banner = css({
  padding: "4",
  borderRadius: "lg",
  backgroundColor: "bg.subtle",
  color: "fg",
})

export function Welcome() {
  return (
    <div className={banner}>
      <Button variant="primary">Get started</Button>
    </div>
  )
}

If your app extends nothing in the theme, css() from @pockets-ui/components/css is the same function and skips the local folder. The recipes are always available as @pockets-ui/components/recipes.

Extending the theme

panda.config.ts accepts the full Panda config surface, so app-level additions — say, wiring your framework's font variables into the heading and body font tokens — go under theme.extend. Re-run codegen after any config change.

import { defineConfig } from "@pandacss/dev"

export default defineConfig({
  designSystem: "@pockets-ui/components",
  include: ["./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}"],
  theme: {
    extend: {
      tokens: {
        fonts: {
          heading: { value: "var(--font-funnel-display)" },
          body: { value: "var(--font-instrument-sans)" },
        },
      },
    },
  },
})

Without Panda

For an app with no Panda build step — a Rails view, a legacy bundle — the package ships a complete stylesheet with every recipe variant and text style pre-built:

import "@pockets-ui/components/styles.css"

The components work as-is on this path. The one limit: css() and style props on those components generate class names at runtime with no matching CSS, so only recipe variants are styled.