Chakra UI
A step-by-step guide for installing and configuring Chakra UI v3 in RedwoodSDK projects, including customization options and theming techniques.
Installing Chakra UI
Since RedwoodSDK is based on React and Vite, we can work through the "Using Vite" documentation from Chakra UI.
Version Requirements
The minimum Node version required is Node.20.x. Chakra UI v3 represents a major rewrite with significant changes from v2, including new dependencies, component structures, and theming approaches.
Install Chakra UI
npm install @chakra-ui/react @emotion/reactyarn add @chakra-ui/react @emotion/reactpnpm add @chakra-ui/react @emotion/reactbun add @chakra-ui/react @emotion/reactRemoved Dependencies
Unlike v2, Chakra UI v3 no longer requires @emotion/styled or framer-motion. These packages have been removed to improve performance and reduce bundle size.
Add Component Snippets
Chakra UI v3 introduces a snippet-based system that gives you full control over components. Snippets are pre-built component compositions that are copied into your project.
npx @chakra-ui/cli snippet addThis command adds the default snippet set and writes files into src/components/ui/.
You can also add all snippets or choose specific ones.
If you find the number of snippets overwhelming, you can remove the ones you don't need after installation. Only add snippets for components you plan to use.
Configure TypeScript Paths
Update your tsconfig.json to include path mappings for the snippets:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "Bundler",
"skipLibCheck": true,
"paths": {
"@/*": ["./src/*"]
}
}
}For JavaScript projects, create a jsconfig.json file with the same configuration.
Install Vite TypeScript Paths Plugin
To sync your TypeScript paths with Vite, install the vite-tsconfig-paths plugin:
npx install -D vite-tsconfig-pathsyarn dlx install -D vite-tsconfig-pathspnpx install -D vite-tsconfig-pathsbunx install -D vite-tsconfig-pathsConfigure the Vite Plugin
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import tsconfigPaths from "vite-tsconfig-paths";
import { redwood } from "rwsdk/vite";
import { cloudflare } from "@cloudflare/vite-plugin";
export default defineConfig({
plugins: [
cloudflare({
viteEnvironment: { name: "worker" },
}),
redwood(),
react(),
tsconfigPaths(),
],
});Set Up the Provider
The Chakra UI provider needs to wrap your application. In RedwoodSDK, you'll want to add this to your root component or layout.
First, create a provider component if the snippet didn't generate one:
import { ChakraProvider, defaultSystem } from "@chakra-ui/react";
import { ColorModeProvider } from "@/components/ui/color-mode";
export function Provider(props: { children: React.ReactNode }) {
return (
<ChakraProvider value={defaultSystem}>
<ColorModeProvider>{props.children}</ColorModeProvider>
</ChakraProvider>
);
}Then wrap your routes with a layout:
import { Provider } from "@/components/ui/provider";
export function AppLayout({ children }: { children?: React.ReactNode }) {
return <Provider>{children}</Provider>;
}import { layout, render, route } from "rwsdk/router";
import { defineApp } from "rwsdk/worker";
import { Document } from "@/app/Document";
import { AppLayout } from "@/app/layouts/AppLayout";
import { setCommonHeaders } from "@/app/headers";
import { Home } from "@/app/pages/Home";
export default defineApp([
setCommonHeaders(),
render(Document, [layout(AppLayout, [route("/", Home)])]),
]);Test Your Installation
Try using some Chakra UI components in your app to verify everything is working:
import { Button, HStack, Heading } from "@chakra-ui/react";
export function Home() {
return (
<div>
<Heading>Welcome to Chakra UI v3</Heading>
<HStack>
<Button colorScheme="blue">Primary Button</Button>
<Button variant="outline">Secondary Button</Button>
</HStack>
</div>
);
}Run Development Server
npm run devyarn run devpnpm run devbun run devCustomizing Chakra UI
Chakra UI v3 uses a completely new theming system based on the createSystem API, inspired by Panda CSS. The old extendTheme approach from v2 is no longer used.
Creating a Custom System
Create a theme configuration file:
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react";
const customConfig = defineConfig({
theme: {
tokens: {
colors: {
brand: {
50: { value: "#e6f7ff" },
100: { value: "#bae7ff" },
200: { value: "#91d5ff" },
300: { value: "#69c0ff" },
400: { value: "#40a9ff" },
500: { value: "#1890ff" },
600: { value: "#096dd9" },
700: { value: "#0050b3" },
800: { value: "#003a8c" },
900: { value: "#002766" },
},
},
fonts: {
heading: { value: "'Inter', sans-serif" },
body: { value: "'Inter', sans-serif" },
},
},
semanticTokens: {
colors: {
"bg.primary": {
value: { _light: "{colors.white}", _dark: "{colors.gray.900}" },
},
"text.primary": {
value: { _light: "{colors.gray.900}", _dark: "{colors.gray.100}" },
},
},
},
},
});
export const system = createSystem(defaultConfig, customConfig);Using Your Custom System
Update the provider to use your custom system:
import { ChakraProvider } from "@chakra-ui/react";
import { system } from "@/theme";
import { ColorModeProvider } from "@/components/ui/color-mode";
export function Provider(props: { children: React.ReactNode }) {
return (
<ChakraProvider value={system}>
<ColorModeProvider>{props.children}</ColorModeProvider>
</ChakraProvider>
);
}Customization Options
The new theming system uses tokens (design primitives), semantic tokens (contextual tokens that reference other tokens), and recipes (component variants) for styling.
Tokens
Tokens are the foundation of your design system. They represent raw design values:
defineConfig({
theme: {
tokens: {
colors: {
// Color tokens
primary: { value: "#3182ce" },
},
spacing: {
// Spacing tokens
xs: { value: "0.5rem" },
sm: { value: "1rem" },
},
radii: {
// Border radius tokens
base: { value: "0.375rem" },
},
},
},
});Semantic Tokens
Semantic tokens provide contextual meaning and can change based on conditions (like color mode):
defineConfig({
theme: {
semanticTokens: {
colors: {
"bg.canvas": {
value: {
_light: "{colors.white}",
_dark: "{colors.gray.950}",
},
},
"text.heading": {
value: {
_light: "{colors.gray.900}",
_dark: "{colors.gray.50}",
},
},
},
},
},
});Recipes
Recipes define component variants and styling patterns:
defineConfig({
theme: {
recipes: {
button: {
base: {
fontWeight: "semibold",
borderRadius: "md",
},
variants: {
variant: {
solid: {
bg: "brand.500",
color: "white",
},
outline: {
borderWidth: "1px",
borderColor: "brand.500",
color: "brand.500",
},
},
},
},
},
},
});Ejecting the Default Theme
If you want complete control over all tokens and recipes, you can eject the default theme:
npx @chakra-ui/cli eject --outdir src/themeThis generates a file containing all default Chakra UI tokens and recipes, which you can then customize as needed.
Ejecting the theme gives you maximum control but also means you're responsible for maintaining all theme values. Use this approach only if you need extensive customization.
Color Mode
Chakra UI v3 uses next-themes for color mode management instead of the built-in color mode from v2.
Using Color Mode
The snippet system should have generated a color mode component. You can use the useColorMode hook:
import { Button } from "@chakra-ui/react";
import { useColorMode } from "@/components/ui/color-mode";
export function ColorModeToggle() {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Button onClick={toggleColorMode}>
Toggle {colorMode === "light" ? "Dark" : "Light"} Mode
</Button>
);
}Forcing a Color Mode
To lock a section to a specific color mode, use the Theme component:
import { Theme } from "@chakra-ui/react";
import { ColorModeProvider } from "@/components/ui/color-mode";
export function DarkSection({ children }) {
return (
<ColorModeProvider forcedTheme="dark">
<Theme appearance="dark">{children}</Theme>
</ColorModeProvider>
);
}Component Changes from v2 to v3
Breaking Changes
Chakra UI v3 introduces significant component API changes. Most components now use a namespace pattern with compound components.
Common Migration Patterns
Before (v2)
<Menu>
<MenuButton as={Button}>Actions</MenuButton>
<MenuList>
<MenuItem>Download</MenuItem>
<MenuItem>Create a Copy</MenuItem>
</MenuList>
</Menu>After (v3)
<Menu.Root>
<Menu.Trigger asChild>
<Button>Actions</Button>
</Menu.Trigger>
<Menu.Content>
<Menu.Item value="download">Download</Menu.Item>
<Menu.Item value="copy">Create a Copy</Menu.Item>
</Menu.Content>
</Menu.Root>Icons
The @chakra-ui/icons package has been deprecated. Use icon libraries like react-icons or lucide-react:
import { Icon } from "@chakra-ui/react";
import { FaDownload } from "react-icons/fa";
export function DownloadButton() {
return (
<Button>
<Icon>
<FaDownload />
</Icon>
Download
</Button>
);
}Managing Snippets
Adding More Snippets
You can add additional snippets at any time:
# Add all snippets
npx @chakra-ui/cli snippet add --all
# Add a specific snippet
npx @chakra-ui/cli snippet add button
# List available snippets
npx @chakra-ui/cli snippet list
# Specify output directory
npx @chakra-ui/cli snippet add --outdir ./src/components/uiCustomizing Snippets
Since snippets are copied directly into your project, you have complete control to modify them. Edit the files in src/components/ui/ to match your needs.
Type Generation
Generate TypeScript types for your custom theme to get autocompletion and type safety:
# Generate types for your theme
npx @chakra-ui/cli typegen src/theme.ts
# Watch for changes and regenerate
npx @chakra-ui/cli typegen src/theme.ts --watch
# Generate strict types for component variants
npx @chakra-ui/cli typegen src/theme.ts --strict