- Aunque el botón de opción ya viene integrado de forma nativa en los navegadores web como un elemento HTML simple, la librería de UI de Shadcn lo reconstruye en varias capas de componentes de React
<RadioGroup> y <RadioGroupItem> de Shadcn vuelven a envolver componentes de Radix UI y usan íconos de lucide-react junto con decenas de clases de Tailwind
- Radix usa atributos ARIA para accesibilidad y personalización, pero en la práctica reutiliza elementos de botón en lugar del
<input type="radio"> nativo
- Aunque el mismo estilo se puede lograr con CSS simple, esta estructura agrega cientos de líneas de código y varias dependencias, provocando una complejidad innecesaria
- Al no reutilizar elementos HTML nativos, empeoran el rendimiento y la carga de mantenimiento, y se daña la simplicidad del desarrollo web
Análisis de la estructura del botón de opción en Shadcn
- Shadcn implementa los botones de opción mediante dos componentes:
<RadioGroup> y <RadioGroupItem>
- Cada componente envuelve primitivas importadas desde
@radix-ui/react-radio-group y usa CircleIcon de lucide-react
- Incluye más de 45 líneas de código y 3 imports externos, con estilo definido mediante más de 30 clases de Tailwind
- Se carga una librería de íconos SVG solo para mostrar un círculo simple
- Es una función que podría reemplazarse con
border-radius en CSS o con un elemento <circle>
El papel de Radix UI
- Radix, usado por Shadcn, es una librería de componentes UI de bajo nivel enfocada en accesibilidad y personalización
- La implementación del grupo de botones de opción en Radix tiene alrededor de 215 líneas de código React e importa 7 archivos
- Radix configura los botones de opción para que funcionen como tales agregando atributos ARIA a elementos
<button>
- Sin embargo, el primer principio del uso de ARIA del W3C establece que “cuando sea posible, se deben usar elementos HTML nativos”
- Radix no sigue este principio y reutiliza botones en lugar de
<input>
- Dentro de un
<form>, la estructura añade un <input type="radio"> oculto solo en ese contexto, lo que reduce la consistencia
Una alternativa simple posible con CSS
- Los botones de opción HTML nativos pueden estilizarse fácilmente con
appearance: none, ::before, :checked, border-radius, etc.
- En el código de ejemplo se logra una personalización completa sin dependencias, JavaScript ni atributos ARIA
- El mismo efecto también puede implementarse con Tailwind
- La idea de que “dar estilo a los botones de opción es difícil” es un problema del pasado; hoy CSS puro ofrece control suficiente
El problema de la acumulación de complejidad
- Si se usan Shadcn y Radix juntos, hay que entender dos librerías y cientos de líneas de código
- Para un solo botón de opción simple se cargan varios KB de JavaScript
- El usuario debe esperar el parseo y la ejecución de JS solo para alternar un botón
- Esta estructura termina generando más carga cognitiva, más posibilidades de errores y peor rendimiento web
Volver a la simplicidad
- Los navegadores ya incluyen botones de opción por defecto, y una sola línea como
<input type="radio" name="beverage" value="coffee" /> es suficiente
- Las abstracciones innecesarias y el uso de librerías anidadas dañan la simplicidad y eficiencia originales del desarrollo web
- Incluso en elementos pequeños de UI, un diseño que reutiliza funciones nativas favorece tanto el mantenimiento como el rendimiento
4 comentarios
Aburrido y pedante:
Se termina rápido y se recuerda por mucho tiempo:
Si ves el componente de botón de React Aria, como que te desmayas jajaja
Como trabajo en frontend, es un problema que he sufrido durante mucho tiempo y, cómo decirlo, de verdad es un problema muy difícil de resolver. La implementación ha seguido cambiando con el tiempo, pero el hecho de no resolverlo con
input typesigue siendo igual en cualquier época...¿Qué se supone que intentan hacer implementando por separado las especificaciones de accesibilidad solo para imitar el comportamiento de los botones de opción y casillas de verificación del navegador web?... No lo entiendo... Como dice el artículo, ahora también hay alternativas con CSS, así que resulta hasta un poco gracioso ver que insisten en implementarlo como componente pase lo que pase.
Opiniones de Hacker News
No trabajo en frontend tan seguido, pero desde el momento en que React se volvió dominante ya se veía venir un aumento en la complejidad
Otras capas de abstracción tienden a simplificarse, pero React termina creando una abstracción mucho más compleja que la tecnología sobre la que se basa
Siento que los desarrolladores que solo conocen React siguen apilando capas cada vez más altas, y eso termina produciendo resultados sobreingenierizados
Por ejemplo, Shadcn y Radix son librerías de UI exclusivas para React, pero por su marketing parecen librerías de UI generales
Cuando el proyecto crece, al final uno termina armando su propio framework o frustrándose con los existentes, y React sí resuelve ese problema hasta cierto punto
Más que React en sí, el problema es la sobrecarga de complejidad del ecosistema. Si solo trabajas con React, todavía puede ser agradable de usar
Solo intentan esquivarlo con herramientas como Tailwind. Yo uso React para manejar el estado, pero prefiero hacer el estilo directamente con CSS
Lo más difícil es convencer a mis compañeros de equipo de que aprendan CSS
Yo evito estos frameworks “modernos” y prefiero las tecnologías base siempre que sea posible
React solo te da una “caja”, y el desarrollador decide qué meter dentro. Ese es su verdadero poder
Este ejemplo del radio button da risa pero también impresiona
El resultado final es indistinguible de un radio button básico con CSS, así que uno se pregunta por qué hacerlo tan complejo
Me da curiosidad si existen sitios grandes construidos sin este tipo de complejidad innecesaria
Tenía más líneas de código que ahora, pero la interfaz daba una sensación de respuesta inmediata
Se puede ver el código del proyecto Takeoff
Como dice el dicho, “nadie fue despedido por elegir React”, así que se volvió la opción segura
Los desarrolladores deberían recordar que siempre pueden cuestionar los requisitos de diseño
A un desarrollador que estaba perdiendo 4 horas en un problema simple de layout en React Native le dijeron que preguntara si se podía cambiar un poco el diseño, y se resolvió en 10 minutos
Con puro CSS se pueden lograr resultados bastante buenos. Me da curiosidad qué recomiendan quienes ya hayan usado este enfoque
El mayor error de 2025 fue haber elegido Shadcn
Ver que seguía importando Radix fue la primera alerta, y ver el componente radio fue la segunda
Como el proyecto ya estaba avanzado, seguí adelante y lo corregí con Copilot, pero al final tampoco me gustó depender de la IA
El POC anterior era mucho más simple y eficiente. Algún día me gustaría rehacerlo todo con HTML vanilla
Remix o React Router 7 al menos intentaban mantenerse más cerca de los estándares web
Con Tailwind fue cuando pensé “esto ya no va”, y si mis amigos siguen diciendo que está bien después de refactorizar, entonces lo volveré a mirar
React ya tiene estilo basado en props, así que no hay mucha razón para usar bloques enormes de clases CSS
Si tu prioridad es la accesibilidad, con Radix UI basta
El problema es que los elementos
<input>del navegador, sobre todo radio y select, son difíciles de personalizarLos radio buttons por defecto tienen mala usabilidad en móvil
Me gustaría saber más concretamente qué problema hubo en móvil
<label>y le das padding, en móvil sigue siendo perfectamente usableLa mayoría de los proyectos empiezan con buenas intenciones, pero tarde o temprano terminan llenos de código de radio button de 200 líneas y 7 imports
Así es como empieza la putrefacción del código (code rot)
Hace poco probé daisyUI y me gustó bastante
Como está basado en CSS puro, puede aprovechar bien las nuevas funciones del navegador (como dialog)
Por ejemplo, Drawer no logra atrapar el foco, y Accordion abusa de los radio buttons como reemplazo de JS
Por eso librerías como Radix inevitablemente terminan siendo complejas
Estoy de acuerdo con la idea central del artículo, pero si quieres implementar en todos los navegadores el estilo exacto que hizo un diseñador en Figma, me pregunto si eso realmente es posible con CSS vanilla
¿Se puede reproducir por completo algo como la demo de Radix?
Se puede ver en este ejemplo de CodePen
Basta con extraer el CSS y aplicarlo a un componente simple de React
¿De verdad tiene sentido agregar decenas de KB de código y carga de mantenimiento solo para evitar pequeñas diferencias visuales?
Como decía Nam June Paik: “si es demasiado perfecto, Dios se enoja”
El costo real no está en el código, sino en el tiempo de onboarding
A un desarrollador nuevo le puede tomar semanas entender un radio button de 47 líneas basado en Radix
En cambio, la versión vanilla se hace en un día y se explica en 20 minutos
Claro, si estás construyendo un producto como Figma o Linear, donde la accesibilidad y la navegación por teclado son importantes, esa complejidad sí se justifica
Muchos comentarios critican a Shadcn, pero yo más bien creo que fomenta bien la estructura de componentes y la reutilización
La esencia de Shadcn es la idea de “posee tus componentes y modifícalos tú mismo”
Ese es un enfoque radicalmente distinto al de las librerías de UI tradicionales