Chakra UI
Installing Chakra UI
Section titled “Installing Chakra UI”Since the Redwood SDK is based on React and Vite, we can work through the “Using Vite” documentation from Chakra UI.
-
Install Chakra UI
Terminal window npm i @chakra-ui/react @emotion/reactTerminal window pnpm add @chakra-ui/react @emotion/reactTerminal window yarn add @chakra-ui/react @emotion/react -
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.
Terminal window 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. -
Configure TypeScript Paths
Update your
tsconfig.jsonto include path mappings for the snippets:tsconfig.json {"compilerOptions": {"target": "ESNext","module": "ESNext","moduleResolution": "Bundler","skipLibCheck": true,"paths": {"@/*": ["./src/*"]}}}For JavaScript projects, create a
jsconfig.jsonfile with the same configuration. -
Install Vite TypeScript Paths Plugin
To sync your TypeScript paths with Vite, install the
vite-tsconfig-pathsplugin:Terminal window npx install -D vite-tsconfig-pathsTerminal window pnpm install -D vite-tsconfig-pathsTerminal window yarn install -D vite-tsconfig-paths -
Configure the Vite Plugin
vite.config.mts 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 Redwood SDK, you’ll want to add this to your root component or layout.
First, create a provider component if the snippet didn’t generate one:
src/components/ui/provider.tsx 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:
src/app/layouts/AppLayout.tsx import { Provider } from "@/components/ui/provider";export function AppLayout({ children }: { children?: React.ReactNode }) {return <Provider>{children}</Provider>;}src/worker.tsx 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:
src/app/pages/Home.tsx 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
Terminal window npm run devTerminal window pnpm run devTerminal window yarn run dev
Customizing Chakra UI
Section titled “Customizing 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
Section titled “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
Section titled “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
Section titled “Customization Options”Tokens
Section titled “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
Section titled “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
Section titled “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
Section titled “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.
Color Mode
Section titled “Color Mode”Chakra UI v3 uses next-themes for color mode management instead of the built-in color mode from v2.
Using Color Mode
Section titled “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
Section titled “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
Section titled “Component Changes from v2 to v3”Common Migration Patterns
Section titled “Common Migration Patterns”Before (v2)
Section titled “Before (v2)”<Menu> <MenuButton as={Button}>Actions</MenuButton> <MenuList> <MenuItem>Download</MenuItem> <MenuItem>Create a Copy</MenuItem> </MenuList></Menu>After (v3)
Section titled “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>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
Section titled “Managing Snippets”Adding More Snippets
Section titled “Adding More Snippets”You can add additional snippets at any time:
# Add all snippetsnpx @chakra-ui/cli snippet add --all
# Add a specific snippetnpx @chakra-ui/cli snippet add button
# List available snippetsnpx @chakra-ui/cli snippet list
# Specify output directorynpx @chakra-ui/cli snippet add --outdir ./src/components/uiCustomizing Snippets
Section titled “Customizing 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
Section titled “Type Generation”Generate TypeScript types for your custom theme to get autocompletion and type safety:
# Generate types for your themenpx @chakra-ui/cli typegen src/theme.ts
# Watch for changes and regeneratenpx @chakra-ui/cli typegen src/theme.ts --watch
# Generate strict types for component variantsnpx @chakra-ui/cli typegen src/theme.ts --strict