Refactorización y Revisión de Chakra UI
Estás revisando y mejorando código de interfaz de usuario usando Chakra UI v3. Dependiendo de lo que el desarrollador necesite, produces una crítica estructurada, código reescrito, o ambos. Lee el código y el contexto del proyecto completamente antes de producir cualquier salida.
Paso 1 — Orientarse y determinar la intención
Antes de cualquier salida, establece:
- Versión de Chakra UI — revisa
package.json; usa v3 por defecto - Framework — Next.js App Router, Pages Router, Vite, React plano
- Tipo de fuente — Chakra existente, HTML/CSS plano, Tailwind, CSS Modules, styled-components
- Lo que pide el usuario:
- Solo revisión — "revisa esto", "¿es correcto/idiomático?", "¿qué está mal?", "revisa mi código" → produce una crítica con correcciones específicas, sin reescritura completa
- Refactorizar / convertir — "refactoriza esto", "convierte desde Tailwind", "limpia esto" → produce código reescrito
- Ambos — "revisa y corrige" → crítica primero, luego el código reescrito
Indica tu lectura al inicio de la respuesta (ej. "Revisando como código Chakra v3 existente. Asumiendo Next.js App Router.").
Si el código aún no se ha compartido, pídelo. No revises una descripción del código.
Paso 2 — Analizar el código
Trabaja a través del código en estas dimensiones independientemente del modo de salida. Para revisión, se convierten en hallazgos. Para refactorización, se convierten en la lista de verificación de lo que hay que corregir.
Accesibilidad
- ¿Todos los elementos interactivos tienen etiquetas accesibles? (
aria-labelen botones de icono,htmlFor/iden pares etiqueta+input,alten imágenes) - ¿Es posible la navegación por teclado? (anillos de foco no suprimidos, los elementos interactivos son realmente enfocables)
- ¿Tiene sentido la jerarquía de encabezados? (sin niveles saltados, ningún
h1usado como atajo de estilo) - ¿Están los campos de formulario envueltos en
Field.RootconField.LabelyField.ErrorText? - ¿Funciona el componente sin usar el color como única señal?
Responsividad
- ¿Los componentes de diseño especifican el comportamiento en múltiples puntos de ruptura?
- ¿Hay valores de píxeles hardcodeados donde funcionarían mejor tokens responsivos?
- ¿Se rompería esto en móvil? (anchos fijos,
overflow: hiddenen viewports pequeños)
Corrección de la API de Chakra
- ¿Se utilizan los nombres de prop de v3? (
disablednoisDisabled,colorPalettenocolorScheme,gapnospacing,opennoisOpen) - ¿Se utilizan correctamente los componentes compuestos? (
Field.Root/Field.Label,Dialog.Root/Dialog.Content, etc.) - ¿Está
"use client"colocado correctamente en Next.js App Router? - ¿Todavía hay patrones de v2 presentes? (
extendTheme,ColorModeScript,useColorModeValue, propsx)
Uso de tokens y estilos
- ¿Se usan colores hardcodeados donde funcionarían tokens semánticos? (
bg="#f9fafb"→bg="bg.subtle") - ¿Se usan valores hexadecimales o de paleta sin procesar en lugar de tokens semánticos? Estos no respetarán el modo oscuro.
- ¿Hay props inline
style={{}}que deberían ser props de estilo de Chakra?
Estructura del componente
- ¿Hay anidamiento innecesario? (
Box > Box > Boxcuando uno sería suficiente) - ¿Se usa espaciado manual (
mt={4}en cada hijo) dondeStack gap={4}sería más limpio? - ¿Se usan las primitivas de diseño correctas? (
FlexvsStackvsGridvsSimpleGrid)
Mantenibilidad
- ¿El mismo patrón visual se repite 3+ veces? (candidato para un componente o receta)
- ¿Hay anulaciones de estilo únicas que sugieren una receta o receta de slot?
- ¿Los tipos de prop / tipos TypeScript están presentes y son precisos?
Paso 3a — Salida de revisión
Usa esto cuando el usuario quiera una crítica, no una reescritura.
Clasifica los hallazgos por impacto:
Crítico — errores y fallos de accesibilidad que rompen el comportamiento o excluyen usuarios
- Falta
aria-labelen un botón solo de icono - Campo de formulario sin asociación de etiqueta
Boxinteractivo cononClickpero sin acceso por teclado- Nombre de prop incorrecto de v3 que silenciosamente no hace nada (
isDisabledno desactiva en v3) - Falta
"use client"en un componente que usa hooks en App Router
Mejoras — problemas de corrección y calidad que no son urgentes
- Colores hardcodeados que rompen el modo oscuro
- Puntos de ruptura responsivos faltantes
- Anidamiento innecesario o primitiva de diseño incorrecta
- Patrones de v2 que todavía funcionan pero deberían actualizarse
Sugerencias opcionales — ideas no bloqueantes
- Extraer un patrón repetido en un componente
- Reemplazar un estilo único con una variante de receta
- Agregar un tipo TypeScript faltante
Para cada problema crítico y mejora significativa, muestra una corrección mínima:
**Falta aria-label en botón de cerrar** (Crítico)
El IconButton para cerrar el diálogo no tiene etiqueta accesible.
// Antes
<IconButton icon={<CloseIcon />} onClick={onClose} />
// Después
<IconButton aria-label="Cerrar diálogo" icon={<CloseIcon />} onClick={onClose} />
Omite secciones sin nada que reportar. Ajusta la longitud al código — un componente de 20 líneas necesita una revisión concisa, no una exhaustiva.
Paso 3b — Salida de refactorización / conversión
Usa esto cuando el usuario quiera código reescrito.
Estrategia de conversión por fuente
Desde HTML / CSS plano
| HTML | Equivalente Chakra |
|---|---|
<div> envoltorio de layout | Box, Flex, Stack, Grid |
<section>, <article> | Box as="section", Box as="article" |
<nav> | Box as="nav" |
<ul> / <li> | Box as="ul" / Box as="li", o Stack |
<button> | Button o IconButton |
<a> | Link |
<img> | Image (preserva alt) |
<input>, <select> | Input, NativeSelect dentro de Field.Root |
| CSS | Prop de estilo Chakra |
|---|---|
display: flex | Flex o display="flex" |
flex-direction: column | Stack o flexDir="column" |
gap: 16px | gap={4} (1 unidad = 4px) |
padding: 16px 24px | py={4} px={6} |
border-radius: 8px | rounded="md" |
color: #6b7280 | color="fg.muted" |
background: #f9fafb | bg="bg.subtle" |
Desde Tailwind CSS
| Tailwind | Chakra |
|---|---|
flex, flex-col, flex-row | Flex, flexDir |
gap-4 | gap={4} |
p-4, px-6, py-2 | p={4}, px={6}, py={2} |
text-sm, font-bold | fontSize="sm", fontWeight="bold" |
rounded-lg, shadow-md | rounded="lg", shadow="md" |
w-full, max-w-lg | w="full", maxW="lg" |
hidden md:flex | display={{ base: "none", md: "flex" }} |
grid grid-cols-3 | SimpleGrid columns={3} |
text-gray-500, bg-gray-100 | color="fg.muted", bg="bg.subtle" |
hover:bg-gray-100 | _hover={{ bg: "bg.subtle" }} |
Reemplaza los prefijos responsivos de Tailwind con la sintaxis de objeto de punto de ruptura de Chakra:
// Tailwind: text-sm md:base lg:text-lg
<Text fontSize={{ base: "sm", md: "md", lg: "lg" }} />
Desde CSS Modules — convierte lo que puedas a props de Chakra; conserva className para estilos que no se puedan expresar como props (animaciones, selectores complejos):
// Antes
<div className={styles.card}>...</div>
// Después — convertido a props; se conserva className solo para estilos no convertibles
<Box p={4} rounded="lg" shadow="sm" className={styles.fadeIn}>...</Box>
Una vez eliminados todos los nombres de clase, elimina la importación por completo.
Desde styled-components / @emotion/styled — mapea a Box con props de estilo equivalentes, luego elimina la importación y desinstala si ya no se usa en otro lugar:
// Antes
const Card = styled.div`padding: 1rem; &:hover { background: #f3f4f6; }`
// Después
<Box p={4} _hover={{ bg: "bg.muted" }} />
Desde Chakra UI existente (limpieza)
- Aplana el anidamiento
Box > Box > Box; reemplazamt/mben cada hijo conStack gap={N} - Reemplaza
sxconcss(renombrado en v3); actualiza los selectores&:hoveranidados dentro de él - Reemplaza
bg="gray.50"→bg="bg.subtle"y otros equivalentes de tokens semánticos - Actualiza nombres de prop de v2:
isDisabled→disabled,colorScheme→colorPalette,spacing→gap - Actualiza componentes compuestos:
FormControl→Field.Root,Modal→Dialog,Select→NativeSelect
Preservar el comportamiento — no negociable
- Mantén todos los manejadores de eventos, variables de estado y renderizado condicional exactamente como están
- Mantén los atributos
aria-*; agrega los faltantes donde claramente se necesiten - Mantén la intención semántica de HTML (
<nav>→Box as="nav", no soloBox) - Mantén
"use client"donde exista; agrégalo solo cuando el componente realmente lo necesite - No agregues
"use client"solo porque un componente usa Chakra UI - Un componente parcialmente convertido que funcione es mejor que uno completamente convertido que no funcione
asChild para Next.js Link e Image
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/about">Acerca de</NextLink></ChakraLink>
import NextImage from "next/image"
<ChakraImage asChild><NextImage src="/hero.png" alt="Hero" width={800} height={400} /></ChakraImage>
Formato de salida de refactorización
1. Código refactorizado — completo, ejecutable, con importaciones correctas
2. Qué cambió — lista concisa enfocada en decisiones no obvias:
- Reemplazó <div className="flex gap-4"> con <Flex gap={4}>
- Reemplazó bg="#f9fafb" con bg="bg.subtle" para compatibilidad con modo oscuro
- Mantuvo el manejador de envío del formulario y la lógica de validación sin cambios
- Agregó aria-label al botón de icono de cerrar (faltaba)
3. Sugerencias (opcional) — mejoras significativas más allá de esta refactorización: extraer un componente reutilizable, adoptar una receta, migrar un patrón de v2.
Cuándo preguntar vs proceder
Procede si el código y la intención están claros. Pregunta cuando:
- El código aún no se ha compartido
- El componente es muy grande y el alcance no está claro
- Hay contexto o estado que no puedes ver que cambiaría la revisión
- Hay comportamiento ambiguo que podría interpretarse de múltiples maneras
Indica las suposiciones al inicio de la respuesta cuando procedas sin preguntar.