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 codegenThat 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:
{ "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
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.
- Panda never ran, or it ran before the file that uses a style prop existed. Re-run
codegenand check that the class you expected is in the generated sheet. - 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 thepreparescript above is for, and re-runningpanda codegensettles it. - 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 loud0 components detectedwhen the answer is none. A component arriving from a dependency rather than your own source is whatcomponentsis for. - 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, throughdefineChakraConfig({ responsive }).