- name
- chakra-ui-migrate
- description
- > Use when this capability is needed.
# Chakra UI Migration: v2 → v3
You are guiding a developer through migrating their project from Chakra UI v2 to
v3. Work through the steps below in order. Inspect the project first — never
guess the package versions or framework.
> **Node requirement:** Chakra UI v3 requires Node >= 20.x. Confirm before
> proceeding if the environment is uncertain.
---
## Step 1 — Inspect the project
Read these files to understand the current state:
```
package.json
```
Look for:
- Current `@chakra-ui/react` version (v2.x vs v3.x)
- Related packages: `@chakra-ui/icons`, `@chakra-ui/hooks`,
`@chakra-ui/next-js`, `@emotion/styled`, `framer-motion`
- Framework: Next.js (App Router or Pages Router), Vite, plain React
- Package manager (from lockfiles: `pnpm-lock.yaml`, `yarn.lock`, `bun.lock`,
`package-lock.json`)
Also spot-check key files when helpful:
- Provider / theme setup (`_app.tsx`, `layout.tsx`, `theme.ts`)
- Color mode usage (`ColorModeScript`, `useColorMode`, `useColorModeValue`)
- Any component files showing heavy v2 patterns
---
## Step 2 — Update packages
### Remove v2-only dependencies
```bash
# npm
npm uninstall @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion
# pnpm
pnpm remove @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion
# yarn
yarn remove @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion
```
`@emotion/styled` and `framer-motion` are no longer required in v3.
### Install v3 core packages
```bash
# npm
npm install @chakra-ui/react @emotion/react
# pnpm
pnpm add @chakra-ui/react @emotion/react
# yarn
yarn add @chakra-ui/react @emotion/react
```
### Replacements for removed packages
| Removed | Replacement |
| -------------------- | -------------------------------------------- |
| `@chakra-ui/icons` | `lucide-react` or `react-icons` |
| `@chakra-ui/hooks` | `react-use` or `usehooks-ts` |
| `@chakra-ui/next-js` | `asChild` prop pattern (see Next.js section) |
---
## Step 3 — Run the codemod
The official codemod handles most mechanical changes: component renames, prop
updates, import rewrites, and compound component restructuring. It does not
replace manual review — plan to audit the output.
**Dry run first (no files changed):**
```bash
npx @chakra-ui/codemod upgrade --dry
```
Review what it proposes. When satisfied:
```bash
npx @chakra-ui/codemod upgrade
```
After the codemod, commit the changes before making manual edits so you have a
clean diff to work from.
---
## Step 4 — Update the Provider
### Old v2 pattern
```tsx
// v2
import { ChakraProvider } from "@chakra-ui/react"
import theme from "./theme"
;<ChakraProvider theme={theme}>{children}</ChakraProvider>
```
### New v3 pattern (using Chakra CLI snippets)
Generate the provider and component snippets:
```bash
npx @chakra-ui/cli snippet add
```
This creates `components/ui/provider.tsx` (plus `toaster` and `tooltip`
snippets) and automatically installs required npm dependencies — including
`next-themes`. Import and use it:
```tsx
// v3 — app/layout.tsx (Next.js App Router)
import { Provider } from "@/components/ui/provider"
;<html lang="en" suppressHydrationWarning>
<body>
<Provider>{children}</Provider>
</body>
</html>
```
The `Provider` file includes `"use client"` — do not add it to `layout.tsx`. See
the Next.js section for Pages Router placement.
### Custom theme in v3
Replace `extendTheme` with `createSystem`:
```ts
// v2
import { extendTheme } from "@chakra-ui/react"
// v3
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"
export const theme = extendTheme({ colors: { brand: { 500: "#2196f3" } } })
const config = defineConfig({
theme: { tokens: { colors: { brand: { 500: { value: "#2196f3" } } } } },
})
export const system = createSystem(defaultConfig, config)
```
Pass `system` to `ChakraProvider` via `value={system}`.
---
## Step 5 — Color mode migration
### Remove all v2 color mode patterns
```tsx
// REMOVE these v2 imports and usages:
import { ColorModeScript } from "@chakra-ui/react"
// ❌
import { useColorMode } from "@chakra-ui/react"
// ❌ (use next-themes)
import { useColorModeValue } from "@chakra-ui/react"
// ❌ (use CSS tokens)
import { DarkMode, LightMode } from "@chakra-ui/react"
// ❌
// Also remove from _document.tsx:
;<ColorModeScript initialColorMode={theme.config.initialColorMode} /> // ❌
```
### v3 color mode approach
Color mode is handled by `next-themes` via the generated `Provider`. Use
semantic tokens that automatically respond to the active color mode:
```tsx
// Use Chakra semantic tokens — they flip automatically in dark mode
<Box color="fg.default" bg="bg.subtle">
...
</Box>
```
For a color mode toggle, use the generated `components/ui/color-mode.tsx`
snippet or `useColorMode` from `next-themes` directly.
---
## Step 6 — Prop renames
These boolean and style props were renamed in v3 for consistency with HTML and
modern React conventions. The codemod catches most of these, but verify manually
afterward.
### Boolean props
| v2 | v3 |
| ----------------- | --------------- |
| `isOpen` | `open` |
| `defaultIsOpen` | `defaultOpen` |
| `isDisabled` | `disabled` |
| `isInvalid` | `invalid` |
| `isRequired` | `required` |
| `isReadOnly` | `readOnly` |
| `isChecked` | `checked` |
| `isLoaded` | `loaded` |
| `isIndeterminate` | `indeterminate` |
### Style and layout props
| v2 | v3 |
| ----------------- | --------------------------- |
| `colorScheme` | `colorPalette` |
| `noOfLines` | `lineClamp` |
| `truncated` | `truncate` |
| `spacing` (Stack) | `gap` |
| `apply` | `textStyle` or `layerStyle` |
### Nested style props
```tsx
// v2 — sx with nested pseudo-selectors
<Box sx={{ "&:hover": { color: "blue.500" } }} />
// v3 — css prop with "&" selectors
<Box css={{ "&:hover": { color: "blue.500" } }} />
```
---
## Step 7 — Component migrations
### Renamed components
| v2 | v3 |
| ------------- | ----------------------------------- |
| `Modal` | `Dialog` |
| `FormControl` | `Field` |
| `Select` | `NativeSelect` |
| `AlertDialog` | `AlertDialog` (compound, see below) |
`Modal` is the most common rename — every `<Modal>`, `<ModalOverlay>`,
`<ModalContent>`, `<ModalHeader>`, `<ModalBody>`, `<ModalFooter>`, and
`<ModalCloseButton>` becomes a `Dialog.*` compound part:
```tsx
// v2
<Modal isOpen={open} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Title</ModalHeader>
<ModalBody>Body</ModalBody>
<ModalFooter><Button onClick={onClose}>Close</Button></ModalFooter>
</ModalContent>
</Modal>
// v3
<Dialog.Root open={open} onOpenChange={({ open }) => setOpen(open)}>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header><Dialog.Title>Title</Dialog.Title></Dialog.Header>
<Dialog.Body>Body</Dialog.Body>
<Dialog.Footer><Button onClick={() => setOpen(false)}>Close</Button></Dialog.Footer>
<Dialog.CloseTrigger />
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
```
### Compound component rewrites
v3 adopts a consistent compound component API. The codemod handles many of
these, but complex custom usage needs manual review.
**Checkbox**
```tsx
// v2
<Checkbox isChecked={val} onChange={fn}>Label</Checkbox>
// v3
<Checkbox.Root checked={val} onCheckedChange={fn}>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
<Checkbox.Label>Label</Checkbox.Label>
</Checkbox.Root>
```
**Progress**
```tsx
// v2
<Progress value={60} colorScheme="blue" />
// v3
<Progress.Root value={60} colorPalette="blue">
<Progress.Track><Progress.Range /></Progress.Track>
</Progress.Root>
```
**Accordion**
```tsx
// v2
<Accordion><AccordionItem><AccordionButton /><AccordionPanel /></AccordionItem></Accordion>
// v3
<Accordion.Root>
<Accordion.Item value="item-1">
<Accordion.ItemTrigger />
<Accordion.ItemContent />
</Accordion.Item>
</Accordion.Root>
```
**FormControl → Field**
```tsx
// v2
<FormControl isInvalid={!!error} isRequired>
<FormLabel>Email</FormLabel>
<Input type="email" />
<FormErrorMessage>{error}</FormErrorMessage>
<FormHelperText>We'll never share your email.</FormHelperText>
</FormControl>
// v3
<Field.Root invalid={!!error} required>
<Field.Label>Email</Field.Label>
<Input type="email" />
<Field.ErrorText>{error}</Field.ErrorText>
<Field.HelpText>We'll never share your email.</Field.HelpText>
</Field.Root>
```
All `FormControl` sub-parts map to `Field.*`:
- `FormLabel` → `Field.Label`
- `FormErrorMessage` → `Field.ErrorText`
- `FormHelperText` → `Field.HelpText`
- `FormControl` props `isInvalid`, `isRequired`, `isDisabled` → `invalid`,
`required`, `disabled`
**Dialog / Drawer / Menu / Tabs** follow the same compound pattern: use
`ComponentName.Root`, `.Trigger`, `.Content`, `.Item`, etc. Check the Chakra UI
v3 docs for the specific compound API for each.
### Next.js Image and Link (replacing @chakra-ui/next-js)
```tsx
// v2 — @chakra-ui/next-js
import { LinkOverlay } from "@chakra-ui/next-js"
// v3 — asChild pattern
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/about">About</NextLink></ChakraLink>
import NextImage from "next/image"
Auf GitHub ansehen