Chakra UI — Complete Usage & Design System Guide
Chakra UI is a design-system–first React framework built on a modern architecture that includes a styling engine, tokens, recipes, semantic theming, and headless primitives. It enables predictable styling, scalable theme customization, and a consistent development experience for large applications.
1. Installation
Install Chakra UI:
npm install @chakra-ui/reactTo use Chakra components, wrap your application with ChakraProvider in your root layout:
import { createSystem, defaultConfig, ChakraProvider } from '@chakra-ui/react'
const system = createSystem(defaultConfig)
export function RootLayout({ children }) {
return (
<html lang="en">
<body>
<ChakraProvider value={system}>{children}</ChakraProvider>
</body>
</html>
)
}2. What Are Snippets?
Snippets in Chakra UI are pre-built, ready-to-use code templates generated through the CLI. They help you configure common patterns that usually require setup or repeated boilerplate.
Snippets help with:
- Color mode system (light/dark mode)
- Tooltips
- Toaster notifications
- Password input behaviors
- Provider setups
- Component recipes & patterns
Why use snippets?
✔ Faster development ✔ Fewer configuration mistakes ✔ Built-in best practices ✔ Consistent architecture across the app
3. Snippet: Color Mode
Color mode is essential for:
- Light/Dark theme switching
- Conditional styles using
_dark/_light - Semantic tokens mapped to color schemes
Install the color-mode snippet:
npx @chakra-ui/cli snippet add color-modeUse ColorModeProvider in your root layout:
export function RootLayout({ children }) {
return (
<html lang="en">
<body>
<ColorModeProvider>{children}</ColorModeProvider>
</body>
</html>
)
}Provides:
✔ Persisted color preference
✔ Auto-applied dark/light CSS variables
✔ Enables conditional styling (e.g. _dark)
4. Optional Useful Snippets
There are many other snippets you can use theme such as:
4.1 Tooltip
Install:
npx @chakra-ui/cli snippet add tooltipUse tooltips for icons, actions, or short hints:
<Tooltip content="Delete item">
<IconButton icon={<Trash />} />
</Tooltip>4.2 Toaster
Use for notifications (success, error, info).
Install:
npx @chakra-ui/cli snippet add toasterimport { Toaster, toaster } from '@chakra-ui/react'
;<Toaster /> // place in root layout
// Notify
toaster.success('Saved!')4.3 Password Input
Install:
npx @chakra-ui/cli snippet add password-inputUsage:
<PasswordInput placeholder="Enter password" />5. Chakra Core Components
Chakra components combine:
- System props
- Styled primitives
- Recipes & slots
- Theme tokens
Box
Most basic building block:
<Box p={4} bg="gray.100" rounded="lg" />Flex
Same as Box but with display: flex:
<Flex justify="space-between" align="center" />Stack / HStack / VStack
Flex (horizontally or vertically) with some gap:
<Stack>
<Box>1</Box>
<Box>2</Box>
</Stack>Button
Supports states, variants, sizes, recipes:
<Button variant="solid">Save</Button>And there are many other components you can see them in documentation and customize them in the theme.ts
6. Customizing the Theme System
You can fully override and extend Chakra by creating your own system configuration:
import { createSystem, defaultConfig, defineConfig } from '@chakra-ui/react'
const config = defineConfig({
theme: {
// customizations here
}
})
export const system = createSystem(defaultConfig, config)Then apply it:
<ChakraProvider value={system} />6.1 Tokens
Tokens are the foundation of Chakra’s design system.
Why tokens?
- Global consistency
- Auto-generated CSS variables
- Work seamlessly with recipes and conditional styles
- Scale well in large applications
Example:
tokens: {
colors: {
brand: { 500: '#5A31F4' }
}
}6.2 Semantic Tokens
Semantic tokens represent meaning, not raw colors.
semanticTokens: {
colors: {
bg: {
default: "white",
_dark: "gray.900",
},
text: {
default: "gray.900",
_dark: "gray.100",
},
},
}Why semantic tokens?
✔ One label works for both light/dark ✔ Centralized decision-making ✔ Cleaner, scalable design ✔ Easier refactoring
6.3 Other config
In the defineConfig there are many of configuration such as defining backgrounds and keyframes, You can find details of them in the documentation.
6.4 Recipes (Component Style Definitions)
Recipes define reusable component styles—almost like Tailwind components with variants.
Example:
import { defineRecipe } from '@chakra-ui/react'
export const buttonRecipe = defineRecipe({
key: 'button',
base: {
borderRadius: 'md',
fontWeight: '500'
},
variants: {
variant: {
solid: {
bg: 'brand.500',
color: 'white',
_hover: { bg: 'brand.600' }
},
outline: {
border: '1px solid',
borderColor: 'brand.500'
}
},
size: {
sm: { px: 3, py: 2 },
md: { px: 4, py: 3 }
}
},
defaultVariants: {
variant: 'solid',
size: 'md'
}
})Register (this will change the recipe of Chakra ui Button):
theme: {
recipes: {
button: buttonRecipe
}
}Or you can use it like this:
const recipe = useRecipe({ key: 'button' })
const styles = recipe({ size, variant })
return <button styles={styles}>Save</button>6.4 Slot Recipes
Used for multi-part components (Card, Modal, Alert, etc.).
const cardRecipe = defineSlotRecipe({
key: 'new-card',
slots: ['root', 'title', 'description'],
base: {
root: { p: 5, rounded: 'lg', shadow: 'md' },
title: { fontSize: 'xl', fontWeight: 'bold' },
description: { color: 'gray.600' }
}
})Register (this will change the recipe of Chakra ui Card):
theme: {
slotRecipes: {
card: cardRecipe
}
}Or you can use it like this:
const recipe = useRecipe({ key: 'new-card' })
const styles = recipe({})
export const Card = {
Root: (...props) => <Box css={styles.root} {...props} />,
Title: (...props) => <Text css={styles.title} {...props} />,
Description: (...props) => <Text css={styles.description} {...props} />
}6.5 Context Slot Recipes (Advanced)
These allow the root component to pass props into child slots automatically and use the compound variants.
Example: Action menu
'use client'
import {
createSlotRecipeContext,
HTMLChakraProps,
IconButtonProps,
MenuContentProps,
MenuItemProps,
MenuTriggerProps
} from '@chakra-ui/react'
import { IconButton, Menu } from '@chakra-ui/react'
import { EditPencil, Eye, MoreHoriz, Trash } from 'iconoir-react'
import Link from 'next/link'
import DeleteButton from '../delete-button'
import { actionMenuRecipe } from './recipe'
const { withProvider, withContext, usePropsContext, PropsProvider } =
createSlotRecipeContext({
recipe: actionMenuRecipe
})
interface ActionMenuRootProps extends HTMLChakraProps<'div'> {
label?: string
}
const ActionMenuRoot = withProvider<HTMLDivElement, ActionMenuRootProps>(
Menu.Root,
'root',
{
wrapElement: (el, props) => (
<PropsProvider value={props}>{el}</PropsProvider>
),
defaultProps: {
label: 'Item'
}
}
)
const ActionMenuTrigger = withContext<MenuTriggerProps, IconButtonProps>(
({ children, ...props }) => (
<Menu.Trigger asChild>
{children || (
<IconButton size="xs" variant="ghost" {...props}>
<MoreHoriz />
</IconButton>
)}
</Menu.Trigger>
),
'trigger'
)
const ActionMenuContent = withContext<MenuContentProps, HTMLChakraProps<'div'>>(
props => (
<Menu.Positioner>
<Menu.Content {...props} />
</Menu.Positioner>
),
'content'
)
const ActionMenuItem = withContext<MenuItemProps, HTMLChakraProps<'div'>>(
Menu.Item,
'item'
)
export interface ActionMenuViewItemProps extends Omit<MenuItemProps, 'value'> {
href?: string
}
const ActionMenuViewItem = withContext<MenuItemProps, ActionMenuViewItemProps>(
props => {
const { label } = usePropsContext()
return (
<Menu.Item as={props.href ? Link : 'div'} value="view" {...props}>
<Eye /> View {label}
</Menu.Item>
)
},
'viewItem'
)
export interface ActionMenuDeleteItemProps
extends Omit<MenuItemProps, 'value'> {
href?: string
}
const ActionMenuEditItem = withContext<
MenuItemProps,
ActionMenuDeleteItemProps
>(props => {
const { label } = usePropsContext()
return (
<Menu.Item as={props.href ? Link : 'div'} value="edit" {...props}>
<EditPencil /> Edit {label}
</Menu.Item>
)
}, 'editItem')
export interface ActionMenuDeleteItemProps
extends Omit<MenuItemProps, 'value'> {
onDelete?: (props?: any) => any
}
const ActionMenuDeleteItem = withContext<
MenuItemProps,
ActionMenuDeleteItemProps
>(({ onDelete, ...props }) => {
const { label } = usePropsContext()
return (
<DeleteButton onDelete={onDelete}>
<Menu.Item value="delete" closeOnSelect={false} {...props}>
<Trash /> Delete {label}
</Menu.Item>
</DeleteButton>
)
}, 'deleteItem')
export const ActionMenu = {
Root: ActionMenuRoot,
Trigger: ActionMenuTrigger,
Content: ActionMenuContent,
Item: ActionMenuItem,
ViewItem: ActionMenuViewItem,
EditItem: ActionMenuEditItem,
DeleteItem: ActionMenuDeleteItem
}Usage:
<ActionMenu.Root>
<ActionMenu.Trigger />
<ActionMenu.Content>
<ActionMenu.Item />
{/** other items */}
</ActionMenu.Content>
</ActionMenu.Root>This creates an usable action menu and can be customized easily.
6.6 Compound Variants
Apply styles based on multiple variants together.
compoundVariants: [
{
variant: 'outline',
size: 'lg',
css: { borderWidth: '3px' }
}
]7. Changing Default Font
Define fonts with tokens:
tokens: {
fonts: {
body: { value: "Inter, sans-serif" },
heading: { value: "Poppins, sans-serif" },
}
}8. Defining Global CSS
Defined in the system:
globalCss: {
'html, body': {
bg: 'bg',
color: 'text',
fontFamily: 'body',
},
a: {
color: 'brand.500',
},
}9. Conditional Styles (Dark/Light Mode)
Option 1: Component-level condition:
<Box bg={{ base: 'white', _dark: 'gray.800' }} />Option 2: Semantic token:
<Box bg="bg" color="text" />10. Locale provider
If you are using i18n for localizing so you may provide an locale provider to force chakra component to some locale.
<LocaleProvider locale={currentLocale}>{children}</LocaleProvider>11. References
Official Docs: https://chakra-ui.com/docs/components/concepts/overview
12. Summary Checklist
| Topic | Key Points |
|---|---|
| Install | npm install @chakra-ui/react |
| Core Components | Box, Flex, Stack, Button |
| Snippets | CLI-based templates for common patterns |
| Required Snippet | Color mode setup |
| Optional Snippets | Tooltip, Toaster, Password Input |
| Provider | Wrap your app with ChakraProvider |
| System | Customize via tokens, recipes, semantic tokens |
| Recipes | Define component styles with variants |
| Slot Recipes | Multi-part component styling |
| Context Slot Recipes | Pass root props to child slots |
| Fonts | Token-based font definitions |
| Global CSS | Defined in globalCss |
| Dark/Light | _dark, _light, or semantic tokens |