Overview

A guide for configuring the chakra-ui-solid theming system

Source: packages/panda-preset/src/config.tsChakra UI

Architecture

The React version’s theming system is built around the API of Panda CSS. This one is built on Panda CSS. The config object is therefore close to the same object — it lives in panda.config.ts, and a build compiles it instead of an engine serializing it while your app runs.

Almost nothing on this page is ours. theme.extend, tokens, semantic tokens, recipes, conditions — all of it is Panda’s own API, and Panda’s docs are the reference for any key not covered here. This library contributes two things to it: the preset carrying Chakra’s design system, and defineChakraConfig(), which stands in for Panda’s defineConfig and sets the handful of keys that have to agree with our published runtime.

Three steps here as well, and the last two are where they part:

  • Define the styling system configuration using defineChakraConfig
  • Generate the stylesheet with panda codegen
  • Import the stylesheet you generated
panda.config.ts
import { defineChakraConfig } from "@chakra-ui-solid/panda-preset";
 
export default defineChakraConfig({
  theme: {
    extend: {
      tokens: {
        colors: { brand: { 500: { value: "tomato" } } },
      },
    },
  },
  include: ["./node_modules/chakra-ui-solid/dist/**/*.jsx", "./src/**/*.{ts,tsx}"],
  outdir: "styled-system-app",
});

Nothing wraps your app. There is no createSystem, because there is no engine to hand a system to, and no ChakraProvider, because by the time the app runs your theme is a stylesheet. Three differences with the React version’s theme.ts, and they are the whole of it: the config object is Panda’s rather than Chakra’s, customizations go under theme.extend rather than merging with a defaultConfig, and a build step replaces the provider.

defineChakraConfig() already puts the preset in presets — do not import it again here. It is also the only call in the file: there is no defineConfig to wrap it in and nothing to spread, so no key you write can replace one it set. Installation covers the setup this page assumes.

Config

The system is configured using the defineChakraConfig function. This function accepts a configuration object that allows you to customize the styling system’s behavior.

After a config is defined, panda codegen reads it and writes the stylesheet.

cssVarRoot

cssVarRoot is the root element where the token CSS variables will be applied. Note the name: the React version spells it cssVarsRoot.

panda.config.ts
export default defineChakraConfig({
  cssVarRoot: ":where(:root, :host)",
  include: [...],
});

prefix

Not available, and a type error rather than a documented warning. Both halves of Panda’s prefix change names our published runtime has already committed to, and the failure is silent — see Keys that must match ours.

globalCss

globalCss is used to apply global styles to the system.

panda.config.ts
export default defineChakraConfig({
  globalCss: {
    "html, body": { margin: 0, padding: 0 },
  },
  include: [...],
});

preflight

preflight is used to apply css reset styles to the system. defineChakraConfig() turns it on; pass false to drop it, or a scope to confine it to one element.

panda.config.ts
export default defineChakraConfig({
  preflight: { scope: ".chakra-reset" },
  include: [...],
});

theme

Use the theme config property to define the system theme. Under extend, it accepts the same properties the React version’s does:

  • breakpoints: for defining breakpoints
  • keyframes: for defining css keyframes animations
  • tokens: for defining tokens
  • semanticTokens: for defining semantic tokens
  • textStyles: for defining typography styles
  • layerStyles: for defining layer styles
  • recipes: for defining component recipes
  • slotRecipes: for defining component slot recipes
panda.config.ts
export default defineChakraConfig({
  theme: {
    extend: {
      breakpoints: { sm: "320px", md: "768px", lg: "960px", xl: "1200px" },
      tokens: {
        colors: { red: { value: "#EE0F0F" } },
      },
      semanticTokens: {
        colors: { danger: { value: "{colors.red}" } },
      },
      keyframes: {
        spin: {
          from: { transform: "rotate(0deg)" },
          to: { transform: "rotate(360deg)" },
        },
      },
    },
  },
  include: [...],
});

Recipes are keyed by the names the preset already registers — button, input, heading and the rest — so overriding one is adding to that key rather than declaring a new recipe:

panda.config.ts
theme: {
  extend: {
    recipes: {
      button: { variants: { size: { xl: { px: "8", h: "14" } } } },
    },
  },
}

A bare theme would drop Chakra’s whole token table and all 19 recipesextend merges, the key itself replaces. So theme here accepts extend and nothing else: theme: { tokens: … } is a type error naming the fix.

conditions

Use the conditions config property to define custom selectors and media query conditions for use in the system.

panda.config.ts
export default defineChakraConfig({
  conditions: { cqSm: "@container(min-width: 320px)", child: "& > *" },
  include: [...],
});

The condition is real in your own css() calls, and it does not reach the style props on our components:

// ✅ your generated runtime knows the condition
<div class={css({ mt: "40px", _cqSm: { mt: "0px" } })} />
 
// ❌ our published runtime does not, and emits a class your sheet has no rule for
<Box mt="40px" _cqSm={{ mt: "0px" }} />

The second line is the boundary this whole package sits on: css() for a component of ours ships compiled inside @chakra-ui-solid/styled-system, built against our config, and a condition added after the fact is not in it. Nothing errors — the prop is simply inert.

strictTokens

strictTokens enforces the usage of only design tokens, raising a TS error on a raw value. Setting it applies to the runtime your Panda run generates. It does not tighten the style props on our components: those types come from our published package, which was generated without it.

TypeScript

There is no separate typegen step. Types for our style props and tokens ship compiled in @chakra-ui-solid/styled-system, and panda codegen regenerates yours from your own config:

pnpm panda codegen

Keys that must match ours

Panda’s usual model is that you generate the runtime and the stylesheet together, from one config. Here you generate only the stylesheet: the css() that computes a component’s class names was compiled into @chakra-ui-solid/styled-system before you installed it. Every key below decides a name on both sides of that boundary, so a change made on yours alone produces a stylesheet whose rules our class names never match — an unstyled component, with nothing raised anywhere.

KeyWhy
hashHashed rules; our runtime still emits p_4
prefixclassName renames the rules; cssVar renames the variables, and the var(--sizes-*) strings inside SimpleGrid and Bleed are already compiled
separatorp_4 becomes p=4 in the sheet only
presetsA re-declare drops every Chakra token and recipe
importMapUnregisters the chakra factory, and every <chakra.button> emits nothing
staticCssA css array of yours replaces the preset’s outright — in extend too — taking <Flex inline>, <Wrap> and every StackSeparator with it

None of these is yours to get wrong, and none of them takes a documented warning. The first three, plus jsxFramework, jsxFactory and eject, are a type error to pass. The last three are merged: your presets come after ours, and your staticCss is unioned with the preset’s. defineChakraConfig is the full account.

The system object

The React version’s createSystem returns a system with helpers hanging off it. Each one that survives compilation is imported here from the package we publish:

The React versionHere
system.token("colors.red.500")token("colors.red.500") from @chakra-ui-solid/styled-system/tokens
system.token.var("colors.red.500")token.var("colors.red.500")
system.css({ ... })css({ ... }) from @chakra-ui-solid/styled-system/css
system.cva({ ... })cva({ ... })
system.sva({ ... })sva({ ... })
system.isValidProperty(prop)isCssProperty(prop) from @chakra-ui-solid/styled-system/is-valid-prop
system.splitCssProps(props)splitCssProps(props) from the same module
system.breakpoints.up("sm")No counterpart
system.tokens.flatMapNo counterpart
import { css } from "@chakra-ui-solid/styled-system/css";
import { token } from "@chakra-ui-solid/styled-system/tokens";
 
token("colors.red.500");
// => "#ef4444"
 
token.var("colors.red.500");
// => "var(--colors-red-500)"
 
css({ color: "red.500", bg: "blue.200" });
// => "c_red.500 bg_blue.200"

One difference worth reading twice: system.css returns a style object for a CSS-in-JS library to insert, and css here returns a class name string naming rules your stylesheet already contains. cva and sva likewise return functions that return class names.