O que Migração Chakra UI: v2 → v3 faz?
Você está guiando um desenvolvedor na migração do projeto dele do Chakra UI v2 para a v3. Siga as etapas abaixo em ordem. Inspecione o projeto primeiro — nunca adivinhe as versões dos pacotes ou o framework.
Requisito Node: O Chakra UI v3 requer Node >= 20.x. Confirme antes de prosseguir se o ambiente for incerto.
Passo 1 — Inspecione o projeto
Leia estes arquivos para entender o estado atual:
package.json
Procure por:
- Versão atual do
@chakra-ui/react(v2.x vs v3.x) - Pacotes relacionados:
@chakra-ui/icons,@chakra-ui/hooks,@chakra-ui/next-js,@emotion/styled,framer-motion - Framework: Next.js (App Router ou Pages Router), Vite, React puro
- Gerenciador de pacotes (a partir dos lockfiles:
pnpm-lock.yaml,yarn.lock,bun.lock,package-lock.json)
Também verifique arquivos-chave quando útil:
- Configuração do provider / tema (
_app.tsx,layout.tsx,theme.ts) - Uso de modo de cor (
ColorModeScript,useColorMode,useColorModeValue) - Quaisquer arquivos de componentes que mostrem padrões pesados da v2
Passo 2 — Atualize os pacotes
Remova dependências exclusivas da v2
# 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 e framer-motion não são mais necessários na v3.
Instale os pacotes principais da v3
# npm
npm install @chakra-ui/react @emotion/react
# pnpm
pnpm add @chakra-ui/react @emotion/react
# yarn
yarn add @chakra-ui/react @emotion/react
Substituições para pacotes removidos
| Removido | Substituição |
|---|---|
@chakra-ui/icons | lucide-react ou react-icons |
@chakra-ui/hooks | react-use ou usehooks-ts |
@chakra-ui/next-js | Padrão de prop asChild (veja seção Next.js) |
Passo 3 — Execute o codemod
O codemod oficial lida com a maioria das alterações mecânicas: renomeação de componentes, atualizações de props, reescrita de imports e reestruturação de componentes compostos. Ele não substitui a revisão manual — planeje auditar a saída.
Dry run primeiro (nenhum arquivo alterado):
npx @chakra-ui/codemod upgrade --dry
Revise o que ele propõe. Quando estiver satisfeito:
npx @chakra-ui/codemod upgrade
Após o codemod, faça commit das alterações antes de fazer edições manuais para ter um diff limpo para trabalhar.
Passo 4 — Atualize o Provider
Padrão antigo da v2
// v2
import { ChakraProvider } from "@chakra-ui/react"
import theme from "./theme"
;<ChakraProvider theme={theme}>{children}</ChakraProvider>
Novo padrão da v3 (usando snippets do Chakra CLI)
Gere os snippets do provider e de componentes:
npx @chakra-ui/cli snippet add
Isso cria components/ui/provider.tsx (além de snippets toaster e tooltip)
e instala automaticamente as dependências npm necessárias — incluindo
next-themes. Importe e use:
// v3 — app/layout.tsx (Next.js App Router)
import { Provider } from "@/components/ui/provider"
;<html lang="en" suppressHydrationWarning>
<body>
<Provider>{children}</Provider>
</body>
</html>
O arquivo Provider inclui "use client" — não o adicione em layout.tsx. Veja
a seção Next.js para posicionamento no Pages Router.
Tema personalizado na v3
Substitua extendTheme por createSystem:
// 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)
Passe system para ChakraProvider via value={system}.
Passo 5 — Migração do modo de cor
Remova todos os padrões de modo de cor da v2
// REMOVA estes imports e usos da v2:
import { ColorModeScript } from "@chakra-ui/react"
// ❌
import { useColorMode } from "@chakra-ui/react"
// ❌ (use next-themes)
import { useColorModeValue } from "@chakra-ui/react"
// ❌ (use tokens CSS)
import { DarkMode, LightMode } from "@chakra-ui/react"
// ❌
// Também remova de _document.tsx:
;<ColorModeScript initialColorMode={theme.config.initialColorMode} /> // ❌
Abordagem de modo de cor na v3
O modo de cor é gerenciado por next-themes através do Provider gerado. Use
tokens semânticos que respondem automaticamente ao modo de cor ativo:
// Use tokens semânticos do Chakra — eles alternam automaticamente no modo escuro
<Box color="fg.default" bg="bg.subtle">
...
</Box>
Para um alternador de modo de cor, use o snippet gerado components/ui/color-mode.tsx
ou useColorMode do next-themes diretamente.
Passo 6 — Renomeação de props
Estas props booleanas e de estilo foram renomeadas na v3 para consistência com HTML e convenções modernas do React. O codemod captura a maioria delas, mas verifique manualmente depois.
Props booleanas
| v2 | v3 |
|---|---|
isOpen | open |
defaultIsOpen | defaultOpen |
isDisabled | disabled |
isInvalid | invalid |
isRequired | required |
isReadOnly | readOnly |
isChecked | checked |
isLoaded | loaded |
isIndeterminate | indeterminate |
Props de estilo e layout
| v2 | v3 |
|---|---|
colorScheme | colorPalette |
noOfLines | lineClamp |
truncated | truncate |
spacing (Stack) | gap |
apply | textStyle ou layerStyle |
Props de estilo aninhadas
// v2 — sx com pseudo-seletores aninhados
<Box sx={{ "&:hover": { color: "blue.500" } }} />
// v3 — prop css com seletores "&"
<Box css={{ "&:hover": { color: "blue.500" } }} />
Passo 7 — Migrações de componentes
Componentes renomeados
| v2 | v3 |
|---|---|
Modal | Dialog |
FormControl | Field |
Select | NativeSelect |
AlertDialog | AlertDialog (composto, veja abaixo) |
Modal é a renomeação mais comum — cada <Modal>, <ModalOverlay>,
<ModalContent>, <ModalHeader>, <ModalBody>, <ModalFooter>, e
<ModalCloseButton> se torna uma parte composta Dialog.*:
// v2
<Modal isOpen={open} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Título</ModalHeader>
<ModalBody>Corpo</ModalBody>
<ModalFooter><Button onClick={onClose}>Fechar</Button></ModalFooter>
</ModalContent>
</Modal>
// v3
<Dialog.Root open={open} onOpenChange={({ open }) => setOpen(open)}>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header><Dialog.Title>Título</Dialog.Title></Dialog.Header>
<Dialog.Body>Corpo</Dialog.Body>
<Dialog.Footer><Button onClick={() => setOpen(false)}>Fechar</Button></Dialog.Footer>
<Dialog.CloseTrigger />
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
Reescrita de componentes compostos
A v3 adota uma API de componente composto consistente. O codemod lida com muitas delas, mas usos personalizados complexos precisam de revisão manual.
Checkbox
// v2
<Checkbox isChecked={val} onChange={fn}>Rótulo</Checkbox>
// v3
<Checkbox.Root checked={val} onCheckedChange={fn}>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
<Checkbox.Label>Rótulo</Checkbox.Label>
</Checkbox.Root>
Progress
// v2
<Progress value={60} colorScheme="blue" />
// v3
<Progress.Root value={60} colorPalette="blue">
<Progress.Track><Progress.Range /></Progress.Track>
</Progress.Root>
Accordion
// 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
// v2
<FormControl isInvalid={!!error} isRequired>
<FormLabel>Email</FormLabel>
<Input type="email" />
<FormErrorMessage>{error}</FormErrorMessage>
<FormHelperText>Nunca compartilharemos seu email.</FormHelperText>
</FormControl>
// v3
<Field.Root invalid={!!error} required>
<Field.Label>Email</Field.Label>
<Input type="email" />
<Field.ErrorText>{error}</Field.ErrorText>
<Field.HelpText>Nunca compartilharemos seu email.</Field.HelpText>
</Field.Root>
Todas as subpartes de FormControl mapeiam para Field.*:
FormLabel→Field.LabelFormErrorMessage→Field.ErrorTextFormHelperText→Field.HelpText- Props de
FormControlisInvalid,isRequired,isDisabled→invalid,required,disabled
Dialog / Drawer / Menu / Tabs seguem o mesmo padrão composto: use
NomeDoComponente.Root, .Trigger, .Content, .Item, etc. Consulte a
documentação do Chakra UI v3 para a API composta específica de cada um.
Image e Link do Next.js (substituindo @chakra-ui/next-js)
// v2 — @chakra-ui/next-js
import { LinkOverlay } from "@chakra-ui/next-js"
// v3 — padrão asChild
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/sobre">Sobre</NextLink></ChakraLink>
import NextImage from "next/image"
<ChakraImage asChild><NextImage src="..." alt="..." /></ChakraImage>
Passo 8 — Migração de theming
styleConfig e multiStyleConfig → recipes
// v3 — componente único (recipe)
import { defineRecipe } from "@chakra-ui/react"
// v2
const buttonStyle = {
baseStyle: { fontWeight: "bold" },
variants: { solid: { bg: "blue.500" } },
defaultProps: { variant: "solid" },
}
const buttonRecipe = defineRecipe({
base: { fontWeight: "bold" },
variants: { variant: { solid: { bg: "blue.500" } } },
defaultVariants: { variant: "solid" },
})
// v3 — slot recipe
import { defineSlotRecipe } from "@chakra-ui/react"
// v2 — multiStyleConfig (componente multiparte)
const cardStyle = multiStyleConfig({
parts: ["root", "header"],
baseStyle: { root: { bg: "white" }, header: { fontWeight: "bold" } },
})
const cardSlotRecipe = defineSlotRecipe({
slots: ["root", "header"],
base: { root: { bg: "white" }, header: { fontWeight: "bold" } },
})
Typegen para tokens personalizados
Após adicionar tokens personalizados, tokens semânticos, recipes ou slot recipes, execute typegen para manter os tipos TypeScript sincronizados:
npx @chakra-ui/cli typegen ./theme.ts
Migrações de tema complexas — se você estiver movendo um tema v2 grande com muitos tokens personalizados, tokens semânticos ou estilos de componentes multiparte, use a habilidade
chakra-ui-theming. Ela cobre a API completa de token/recipe/slot-recipe em profundidade e é um guia melhor do que esta seção sozinha.
Passo 9 — Especificidades do Next.js
App Router
- Coloque
<Provider>emapp/layout.tsx(Server Component — sem"use client") - O
components/ui/provider.tsxgerado já tem"use client" - Adicione
suppressHydrationWarningao<html>para evitar cintilação do modo de cor - Não envolva todo o app ou layout em
"use client"
Pages Router
// pages/_app.js
import { Provider } from "@/components/ui/provider"
export default function App({ Component, pageProps }) {
return (
<Provider>
<Component {...pageProps} />
</Provider>
)
}
Remova qualquer ColorModeScript de pages/_document.tsx — ele não é usado na v3.
Passo 10 — Checklist de validação
Trabalhe através disso após a migração estar completa:
- Reinstalar dependências:
npm install/pnpm install - TypeScript:
npx tsc --noEmit— resolva todos os erros de tipo - Lint:
npm run lint - Build:
npm run build - Verificar visualmente o alternador de modo de cor (claro ↔ escuro)
- Testar componentes interativos: Dialog, Drawer, Menu, Tabs, Accordion
- Testar componentes de formulário: Checkbox, Select/NativeSelect, Input, Radio
- Verificar regressões visuais nas páginas principais
- Pesquisar no código por imports remanescentes da v2:
grep -r "ColorModeScript\|useColorModeValue\|extendTheme\|styleConfig\|@chakra-ui/icons\|@chakra-ui/next-js" src/
Perguntas de esclarecimento (quando o contexto não está claro)
Se a versão do usuário, framework ou escopo for ambíguo, pergunte:
- "Qual versão do
@chakra-ui/reactvocê está usando atualmente?" - "Você está usando Next.js App Router, Pages Router, Vite ou React puro?"
- "Você está migrando o código inteiro ou apenas componentes específicos?"
Declare as suposições claramente se você prosseguir sem perguntar.