Migración de Chakra UI: v2 → v3
Estás guiando a un desarrollador para migrar su proyecto de Chakra UI v2 a v3. Sigue los pasos a continuación en orden. Inspecciona el proyecto primero — nunca adivines las versiones de los paquetes o el framework.
Requisito de Node: Chakra UI v3 requiere Node >= 20.x. Confirma antes de continuar si el entorno es incierto.
Paso 1 — Inspeccionar el proyecto
Lee estos archivos para entender el estado actual:
package.json
Busca:
- Versión actual de
@chakra-ui/react(v2.x vs v3.x) - Paquetes relacionados:
@chakra-ui/icons,@chakra-ui/hooks,@chakra-ui/next-js,@emotion/styled,framer-motion - Framework: Next.js (App Router o Pages Router), Vite, React simple
- Gestor de paquetes (a partir de lockfiles:
pnpm-lock.yaml,yarn.lock,bun.lock,package-lock.json)
También revisa archivos clave cuando sea útil:
- Configuración del proveedor / tema (
_app.tsx,layout.tsx,theme.ts) - Uso del modo de color (
ColorModeScript,useColorMode,useColorModeValue) - Archivos de componentes que muestren patrones pesados de v2
Paso 2 — Actualizar paquetes
Eliminar dependencias solo de 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 y framer-motion ya no son necesarios en v3.
Instalar paquetes principales de 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
Reemplazos para paquetes eliminados
| Eliminado | Reemplazo |
|---|---|
@chakra-ui/icons | lucide-react o react-icons |
@chakra-ui/hooks | react-use o usehooks-ts |
@chakra-ui/next-js | Patrón de prop asChild (ver sección de Next.js) |
Paso 3 — Ejecutar el codemod
El codemod oficial maneja la mayoría de los cambios mecánicos: renombrados de componentes, actualizaciones de props, reescrituras de imports y reestructuración de componentes compuestos. No reemplaza la revisión manual — planifica auditar el resultado.
Ejecución en seco primero (sin cambios en archivos):
npx @chakra-ui/codemod upgrade --dry
Revisa lo que propone. Cuando estés satisfecho:
npx @chakra-ui/codemod upgrade
Después del codemod, confirma los cambios antes de hacer ediciones manuales para tener un diff limpio desde donde trabajar.
Paso 4 — Actualizar el Proveedor
Patrón antiguo de v2
// v2
import { ChakraProvider } from "@chakra-ui/react"
import theme from "./theme"
;<ChakraProvider theme={theme}>{children}</ChakraProvider>
Nuevo patrón de v3 (usando fragmentos de Chakra CLI)
Genera el proveedor y los fragmentos de componentes:
npx @chakra-ui/cli snippet add
Esto crea components/ui/provider.tsx (además de fragmentos toaster y tooltip) e instala automáticamente las dependencias npm necesarias — incluyendo next-themes. Impórtalo y úsalo:
// v3 — app/layout.tsx (Next.js App Router)
import { Provider } from "@/components/ui/provider"
;<html lang="en" suppressHydrationWarning>
<body>
<Provider>{children}</Provider>
</body>
</html>
El archivo Provider incluye "use client" — no lo agregues a layout.tsx. Consulta la sección de Next.js para la colocación en Pages Router.
Tema personalizado en v3
Reemplaza extendTheme con 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)
Pasa system a ChakraProvider mediante value={system}.
Paso 5 — Migración del modo de color
Eliminar todos los patrones de modo de color de v2
// ELIMINA estos imports y usos de v2:
import { ColorModeScript } from "@chakra-ui/react"
// ❌
import { useColorMode } from "@chakra-ui/react"
// ❌ (usa next-themes)
import { useColorModeValue } from "@chakra-ui/react"
// ❌ (usa tokens CSS)
import { DarkMode, LightMode } from "@chakra-ui/react"
// ❌
// También elimina de _document.tsx:
;<ColorModeScript initialColorMode={theme.config.initialColorMode} /> // ❌
Enfoque de modo de color en v3
El modo de color es manejado por next-themes a través del Provider generado. Usa tokens semánticos que responden automáticamente al modo de color activo:
// Usa tokens semánticos de Chakra — se alternan automáticamente en modo oscuro
<Box color="fg.default" bg="bg.subtle">
...
</Box>
Para un alternador de modo de color, usa el fragmento generado components/ui/color-mode.tsx o useColorMode de next-themes directamente.
Paso 6 — Renombrado de props
Estas props booleanas y de estilo fueron renombradas en v3 para consistencia con HTML y las convenciones modernas de React. El codemod captura la mayoría de estos cambios, pero verifica manualmente después.
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 y diseño
| v2 | v3 |
|---|---|
colorScheme | colorPalette |
noOfLines | lineClamp |
truncated | truncate |
spacing (Stack) | gap |
apply | textStyle o layerStyle |
Props de estilo anidadas
// v2 — sx con pseudo-selectores anidados
<Box sx={{ "&:hover": { color: "blue.500" } }} />
// v3 — prop css con selectores "&"
<Box css={{ "&:hover": { color: "blue.500" } }} />
Paso 7 — Migraciones de componentes
Componentes renombrados
| v2 | v3 |
|---|---|
Modal | Dialog |
FormControl | Field |
Select | NativeSelect |
AlertDialog | AlertDialog (compuesto, ver abajo) |
Modal es el renombrado más común — cada <Modal>, <ModalOverlay>, <ModalContent>, <ModalHeader>, <ModalBody>, <ModalFooter> y <ModalCloseButton> se convierte en una parte compuesta de Dialog.*:
// v2
<Modal isOpen={open} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Título</ModalHeader>
<ModalBody>Cuerpo</ModalBody>
<ModalFooter><Button onClick={onClose}>Cerrar</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>Cuerpo</Dialog.Body>
<Dialog.Footer><Button onClick={() => setOpen(false)}>Cerrar</Button></Dialog.Footer>
<Dialog.CloseTrigger />
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
Reescrituras de componentes compuestos
v3 adopta una API de componentes compuestos consistente. El codemod maneja muchos de estos cambios, pero el uso personalizado complejo necesita revisión manual.
Checkbox
// v2
<Checkbox isChecked={val} onChange={fn}>Etiqueta</Checkbox>
// v3
<Checkbox.Root checked={val} onCheckedChange={fn}>
<Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
<Checkbox.Label>Etiqueta</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 compartiremos tu 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 compartiremos tu email.</Field.HelpText>
</Field.Root>
Todas las sub-partes de FormControl se asignan a Field.*:
FormLabel→Field.LabelFormErrorMessage→Field.ErrorTextFormHelperText→Field.HelpText- Los props
isInvalid,isRequired,isDisableddeFormControl→invalid,required,disabled
Dialog / Drawer / Menu / Tabs siguen el mismo patrón compuesto: usa NombreComponente.Root, .Trigger, .Content, .Item, etc. Consulta la documentación de Chakra UI v3 para la API compuesta específica de cada uno.
Next.js Image y Link (reemplazando @chakra-ui/next-js)
// v2 — @chakra-ui/next-js
import { LinkOverlay } from "@chakra-ui/next-js"
// v3 — patrón asChild
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/about">Acerca de</NextLink></ChakraLink>
import NextImage from "next/image"
<ChakraImage asChild><NextImage src="..." alt="..." /></ChakraImage>
Paso 8 — Migración de theming
styleConfig y multiStyleConfig → recipes
// v3 — componente individual (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 de múltiples partes)
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
Después de agregar tokens personalizados, tokens semánticos, recipes o slot recipes, ejecuta typegen para mantener los tipos de TypeScript sincronizados:
npx @chakra-ui/cli typegen ./theme.ts
Migraciones de temas complejas — si estás migrando un tema grande de v2 con muchos tokens personalizados, tokens semánticos o estilos de componentes de múltiples partes, usa la habilidad
chakra-ui-theming. Cubre la API completa de tokens/recipes/slot-recipes en profundidad y es una mejor guía que esta sección por sí sola.
Paso 9 — Específicos de Next.js
App Router
- Coloca
<Provider>enapp/layout.tsx(Componente de Servidor — sin"use client") - El archivo generado
components/ui/provider.tsxya tiene"use client" - Agrega
suppressHydrationWarninga<html>para evitar parpadeo del modo de color - No envuelvas toda la aplicación o layout en
"use client"
Pages Router
// pages/_app.js
import { Provider } from "@/components/ui/provider"
export default function App({ Component, pageProps }) {
return (
<Provider>
<Component {...pageProps} />
</Provider>
)
}
Elimina cualquier ColorModeScript de pages/_document.tsx — no se usa en v3.
Paso 10 — Lista de verificación de validación
Trabaja a través de esto después de que la migración esté completa:
- Reinstalar dependencias:
npm install/pnpm install - TypeScript:
npx tsc --noEmit— resuelve todos los errores de tipo - Lint:
npm run lint - Build:
npm run build - Verificar visualmente el alternador de modo de color (claro ↔ oscuro)
- Probar componentes interactivos: Dialog, Drawer, Menu, Tabs, Accordion
- Probar componentes de formulario: Checkbox, Select/NativeSelect, Input, Radio
- Verificar regresiones visuales en páginas clave
- Buscar en el código base imports sobrantes de v2:
grep -r "ColorModeScript\|useColorModeValue\|extendTheme\|styleConfig\|@chakra-ui/icons\|@chakra-ui/next-js" src/
Preguntas aclaratorias (cuando el contexto no está claro)
Si la versión, el framework o el alcance del usuario son ambiguos, pregunta:
- "¿Qué versión de
@chakra-ui/reacttienes actualmente?" - "¿Estás usando Next.js App Router, Pages Router, Vite o React simple?"
- "¿Estás migrando toda la base de código o solo componentes específicos?"
Declara las suposiciones claramente si procedes sin preguntar.