Installation

How to install and set up chakra-ui-solid in your project

Requires Panda CSS in your build. Not optional — this library publishes no CSS.

Every class name a component computes is a name in your stylesheet, produced by your Panda run over your source. There is no prebuilt sheet to fall back on, and no version of this library that works without one.

The same run also writes the styling runtime that computes those names, which you hand to a <ChakraProvider> at your app root. One config decides both halves, so a custom utility, an added variant, a renamed class or a hashed sheet agree by construction.

Build Setup

There is no per-framework guide here, because there is no per-framework difference. Client-rendered, server-rendered or TanStack Start, chakra-ui-solid asks nothing of your build beyond @solidjs/vite-plugin — which is the plugin a SolidJS app compiles with anyway. Build setup is one screen on why that holds, and on what the symptoms look like when a toolchain gets it wrong.

The minimum SolidJS version required is 2.0. Not 1.x — the packages import @solidjs/web, and a 1.x install fails at load.

Installation

To set up chakra-ui-solid in your project, follow the steps below.

Install the packages

Two of ours, and one of Panda’s.

pnpm add chakra-ui-solid @chakra-ui-solid/panda-preset
pnpm add -D @pandacss/dev

@pandacss/dev is declared as a non-optional peer dependency of our packages, which is deliberate: the install warning is the enforcement. Without it the failure is that you install, run the app, every component renders naked, and no tool anywhere says why.

Write panda.config.ts

import { defineChakraConfig } from "@chakra-ui-solid/panda-preset";
 
export default defineChakraConfig({
  include: [
    "./node_modules/chakra-ui-solid/dist/panda.buildinfo.json",
    "./src/**/*.{ts,tsx}",
  ],
  outdir: "styled-system-app",
});

That first path is ours and it is one file, not a glob: a few components style themselves with values your source never spells, and panda.buildinfo.json is how those reach your extractor. Your own glob is what decides everything else — which components’ CSS you get is read off the specifiers your files name us in.

Three things about that, and no more. There is no defineConfig import — this call is your config. The preset is not imported either; defineChakraConfig() already puts it in presets. And you add to it rather than spreading it, so nothing you write can replace what it set:

export default defineChakraConfig({
  // Ours stays first; yours is later, so yours wins on a conflict.
  presets: [myPreset],
  // Customizations go under `extend`. A bare `theme` is a type error here.
  theme: { extend: { tokens: { colors: { brand: { value: "#5b8" } } } } },
  // `include` and `outdir` as above — keep the buildinfo path.
  include: ["./node_modules/chakra-ui-solid/dist/panda.buildinfo.json", "./src/**/*.{ts,tsx}"],
  outdir: "styled-system-app",
});

The four keys that decide what Panda extracts — eject, jsxFramework, jsxFactory and importMap — are a type error to pass, and if one reaches Panda anyway it is put back with a warning. Every key that decides what Panda names is yours, hash and prefix included. defineChakraConfig is the whole account.

Generate the styled-system

pnpm panda codegen

That one run writes three things into styled-system-app/: your stylesheet, a chakra-system.ts holding the styling runtime, and the declarations that type it. Put it in prepare, so a fresh install and a CI checkout both have it:

package.json
{ "scripts": { "prepare": "panda codegen" } }

Everything on the page below comes out of that single run, which is why a class name on an element and the rule behind it cannot disagree.

Wrap your app, and import the stylesheet you generated

src/app.tsx
import { ChakraProvider } from "chakra-ui-solid";
import { system } from "../styled-system-app/chakra-system";
import "../styled-system-app/styles.css";
 
export default function App() {
  return <ChakraProvider value={system}>{/* your app */}</ChakraProvider>;
}

The provider is required. It is what hands every component the styling runtime its class names are computed from, so a component rendered outside one throws by name rather than rendering unstyled. The React version’s context is strict in exactly the same way.

It renders no element and injects no stylesheet — the @layer order and any globalCss arrive in the sheet on the line above it. That import is the sentence keeping “we publish no CSS” from reading as “there is no CSS”: your sheet exists and it is yours; ours does not exist at all.

Enjoy!

import { Box } from "chakra-ui-solid";
 
const Demo = () => {
  return (
    <Box p="4" bg="bg.panel" borderWidth="1px">
      Click me
    </Box>
  );
};

Did it work?

Render something, then read a computed style:

import { Box } from "chakra-ui-solid";
 
<Box p="4" bg="bg.panel" />;
 
// then, in a test or the console:
getComputedStyle(el).padding; // "16px"

Read getComputedStyle(el).padding, not el.classList.contains("p_4"). A class-name check passes on a completely unstyled element, so an install that silently did nothing looks identical to one that worked. This is the highest-value paragraph on the page, and it belongs here at the end of setup rather than in a testing guide.

Everything renders naked

Four causes, in the order they actually occur.

  1. Panda never ran, or it ran before the file that uses a style prop existed. Re-run codegen and check that the class you expected is in the generated sheet.
  2. The page is rendering against a stale styled-system-app/. The runtime and the sheet come out of one run, so they cannot disagree with each other — but both can be older than the config that was supposed to produce them. That is what the prepare script above is for, and re-running panda codegen settles it.
  3. Your globs never reached the file that uses the component. Which components’ CSS is generated is read off the specifiers your scanned files name us in, so one reached only from a file Panda never parsed gets no recipe rules. Every run prints what it found — 🐼 chakra-ui-solid 4 components → 7 recipes: …, or a loud 0 components detected when the answer is none. A component arriving from a dependency rather than your own source is what components is for.
  4. A recipe variant needs the responsive opt-in. Responsive style props work with no configuration. A responsive recipe variant — <Button size={{ base: "sm", md: "lg" }}> — is generated only for the recipes you opt in, through defineChakraConfig({ responsive }).