Publicado el

¿Qué es shadcn/ui? Su propósito, ventajas y uso en aplicaciones React modernas

Autores

    ¿Qué es shadcn/ui? Su propósito, ventajas y uso en aplicaciones React modernas

    Los proyectos React modernos suelen afrontar una decisión difícil: ¿utilizar una biblioteca de interfaz ya construida (rápida, pero inflexible) o diseñar tu propio sistema (flexible, pero lento de construir)?
    Ahí es donde entra shadcn/ui, un nuevo enfoque del desarrollo de interfaces que te da control total sobre tu código y ofrece a la vez el acabado de una biblioteca de componentes madura.

    En esta guía, exploraremos qué es shadcn/ui, por qué se ha vuelto tan popular entre los desarrolladores React y Next.js y cómo puedes utilizarlo para acelerar tu trabajo de interfaz sin perder flexibilidad.

    ¿Qué es shadcn/ui?

    shadcn/ui (a menudo escrito simplemente como shadcn) no es un paquete npm tradicional ni una biblioteca de componentes con temas personalizables como Material UI o Chakra UI.
    Es una colección de componentes React de alta calidad y código abierto construidos con:

    • Tailwind CSS (para los estilos)
    • Radix UI (para primitivas accesibles y sin estilos)
    • Lucide Icons (para iconos SVG claros y coherentes)

    Pero esta es la diferencia:

    En lugar de instalarlo como dependencia, copias el código fuente real de cada componente en tu propio proyecto.

    Esto significa que cada botón, diálogo o menú desplegable vive en tu propia base de código, donde tú puedes editarlo, personalizar su tema y controlar sus versiones.

    Puedes considerarlo un generador de componentes o un kit inicial de interfaz, no una dependencia.

    Cómo funciona

    El proyecto shadcn/ui proporciona una herramienta de línea de comandos que genera componentes directamente en tu proyecto:

    npx shadcn-ui@latest add button
    

    Este comando descarga un componente Button accesible y ya construido, y lo añade a tu carpeta local components/ui/. Desde ahí puedes personalizarlo, cambiar las clases de Tailwind, ajustar variantes o adaptarlo a tu sistema de diseño.

    Cada componente es simplemente React + Tailwind + Radix, sin lógica oculta ni dependencia en tiempo de ejecución.

    Por qué los desarrolladores utilizan shadcn/ui

    1. Propiedad total del código

    A diferencia de las bibliotecas de interfaz en las que dependes de dependencias opacas, shadcn te da el código fuente completo del componente. Puedes:

    • Editar directamente los estilos
    • Añadir propiedades o variantes
    • Integrar lógica personalizada (como análisis de uso o permisos)

    Es tu interfaz y tus reglas, sin esperar a que los responsables del mantenimiento fusionen una solicitud de incorporación.

    2. Construido sobre bases probadas

    Cada componente se construye utilizando:

    • Tailwind CSS → estilos basados en utilidades
    • Radix UI → primitivas básicas accesibles y sin estilos
    • Lucide Icons → iconos SVG modernos
    • clsx / tailwind-variants → gestión clara de clases condicionales

    Esto garantiza que tus componentes sean accesibles y estén preparados para producción, siguiendo las buenas prácticas de los sistemas de diseño de forma predeterminada.

    3. Coherencia y velocidad

    Obtienes un punto de partida cohesionado y atractivo para tu interfaz:

    • Sistema coherente de espaciado, tipografía y color
    • Modo oscuro y temas mediante variables CSS
    • Patrones de disposición e interacción listos para usar (menús desplegables, ventanas modales, información emergente)

    Puedes empezar a entregar interfaces que parecen diseñadas, sin reinventar cada componente.

    4. Sin dependencia del proveedor

    Como los componentes son simplemente código, puedes:

    • Crear versiones derivadas
    • Sustituirlos
    • Combinarlos con otras bibliotecas

    Si shadcn/ui cambia o deja de cubrir tus necesidades, tus componentes siguen perteneciéndote por completo.

    Componentes habituales y ejemplos

    Estos son algunos de los componentes más populares de shadcn/ui y su aspecto en funcionamiento.

    Ejemplo 1: Botón

    import { Button } from '@/components/ui/button'
    
    export default function Example() {
      return (
        <div className="space-x-2">
          <Button>Default</Button>
          <Button variant="outline">Outline</Button>
          <Button variant="destructive">Delete</Button>
        </div>
      )
    }
    

    Por qué es excelente:

    • Variantes integradas como outline, destructive y ghost.
    • Temas completamente personalizables con los tokens de diseño de Tailwind.
    • Suficientemente sencillo para personalizarlo sin perder coherencia.

    Comprender las variantes del botón

    Cuando ejecutas:

    npx shadcn-ui@latest add button
    

    La herramienta de línea de comandos crea un archivo button.tsx dentro de components/ui/, normalmente así:

    // components/ui/button.tsx
    import * as React from 'react'
    import { cva } from 'class-variance-authority'
    import { cn } from '@/lib/utils'
    
    const buttonVariants = cva(
      'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none',
      {
        variants: {
          variant: {
            default: 'bg-primary text-primary-foreground hover:bg-primary/90',
            outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
            destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
            ghost: 'hover:bg-accent hover:text-accent-foreground',
            link: 'text-primary underline-offset-4 hover:underline',
          },
          size: {
            default: 'h-10 px-4 py-2',
            sm: 'h-9 rounded-md px-3',
            lg: 'h-11 rounded-md px-8',
            icon: 'h-10 w-10',
          },
        },
        defaultVariants: {
          variant: 'default',
          size: 'default',
        },
      }
    )
    
    export interface ButtonProps
      extends React.ButtonHTMLAttributes<HTMLButtonElement>,
        VariantProps<typeof buttonVariants> {}
    
    function Button({ className, variant, size, ...props }: ButtonProps) {
      return <button className={cn(buttonVariants({ variant, size, className }))} {...props} />
    }
    
    export { Button, buttonVariants }
    

    Entonces, ¿qué son outline, destructive y ghost?

    Son variantes de estilo predefinidas en esa configuración buttonVariants. No necesitas definirlas manualmente, vienen con el componente generado de forma predeterminada.

    Cada variante corresponde a un patrón diferente de clases de Tailwind:

    VarianteEstilo visualUso habitual
    defaultBotón principal sólido (bg-primary, texto blanco)Llamada principal a la acción (por ejemplo, “Guardar”, “Enviar”).
    outlineFondo transparente, borde visibleAcción secundaria o con menor énfasis (“Cancelar”).
    destructiveColor rojo/de peligro (bg-destructive)Acciones con consecuencias destructivas (“Eliminar”, “Quitar”).
    ghostEstilo mínimo, efecto sutil al pasar el cursorBotones de bajo énfasis (por ejemplo, iconos, enlaces secundarios).
    linkEstilo de enlace de textoPara navegación integrada en el texto.

    Así, cuando escribes:

    <Button variant="destructive">Delete</Button>
    

    le indicas al componente Button que utilice el estilo rojo de peligro, porque la variante corresponde a bg-destructive y text-destructive-foreground.

    ¿Qué son los “tokens de diseño de Tailwind”?

    Los “tokens de diseño” son variables con nombre para colores y espaciado utilizadas en todo tu tema. En shadcn/ui, se definen en tu archivo globals.css (o tailwind.config.js) así:

    :root {
      --background: 0 0% 100%;
      --foreground: 222.2 47.4% 11.2%;
      --primary: 222.2 47.4% 11.2%;
      --primary-foreground: 210 40% 98%;
      --destructive: 0 84.2% 60.2%;
      --destructive-foreground: 210 40% 98%;
      /* etc. */
    }
    

    Después, Tailwind hace referencia a ellos como “tokens” mediante su sintaxis theme() o clases abreviadas:

    className = 'bg-primary text-primary-foreground hover:bg-primary/90'
    

    Estos tokens:

    • Mantienen los colores coherentes entre componentes.
    • Admiten automáticamente el modo oscuro mediante variables CSS.
    • Permiten a diseñadores y desarrolladores compartir un lenguaje visual (por ejemplo, “primary”, “accent”, “destructive”) en lugar de códigos hexadecimales sin procesar.

    Por qué esto es útil

    • Puedes añadir o modificar variantes (por ejemplo, success, warning) fácilmente en el mismo button.tsx.
    • Tu interfaz mantiene la coherencia visual porque todas las variantes utilizan tokens de diseño compartidos.
    • Actualizar tu tema (colores, espaciado, etc.) actualiza al instante todos los componentes.
    • Es flexible, utiliza las variantes integradas o amplíalas para adaptarlas a tu marca.

    En resumen: Esas variantes (outline, destructive, ghost, etc.) son estilos ya construidos e impulsados por tokens de diseño que puedes ampliar o sobrescribir. Son parte de lo que hace que los componentes de shadcn/ui estén preparados para producción de forma predeterminada, sean coherentes, se adapten al tema y se personalicen fácilmente.

    Ejemplo 2: Diálogo (ventana modal)

    import {
      Dialog,
      DialogContent,
      DialogHeader,
      DialogTitle,
      DialogTrigger,
    } from '@/components/ui/dialog'
    
    export default function Example() {
      return (
        <Dialog>
          <DialogTrigger asChild>
            <Button>Open Dialog</Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>Confirm Action</DialogTitle>
            </DialogHeader>
            <p>This action cannot be undone.</p>
          </DialogContent>
        </Dialog>
      )
    }
    

    Por qué es excelente: El diálogo utiliza primitivas de Radix internamente, lo que significa que es accesible mediante teclado, compatible con lectores de pantalla y adaptable de forma predeterminada.

    Ejemplo 3: Campos de entrada y componentes de formulario

    import { Input } from '@/components/ui/input'
    import { Label } from '@/components/ui/label'
    
    export default function LoginForm() {
      return (
        <form className="space-y-4">
          <div>
            <Label htmlFor="email">Email</Label>
            <Input id="email" type="email" placeholder="you@example.com" />
          </div>
          <Button type="submit">Login</Button>
        </form>
      )
    }
    

    Claro, mínimo y fácil de ampliar para cualquier página de autenticación o configuración.

    Cuándo utilizar shadcn/ui y cuándo no

    ✅ Utilízalo cuando

    • Creas un producto personalizado (SaaS, panel, aplicación) y quieres una interfaz coherente rápidamente.
    • Necesitas control total sobre el diseño y la accesibilidad.
    • Ya utilizas Tailwind CSS y Next.js.

    ❌ Evítalo cuando

    • Prefieres un sistema de diseño listo para incorporar (como MUI, Chakra UI).
    • No utilizas Tailwind (está estrechamente vinculado a él).
    • Quieres avanzar extremadamente rápido sin tocar el código de los componentes.

    Primeros pasos (configuración rápida)

    1. Instala Tailwind CSS (si aún no lo has hecho):

      npx create-next-app my-app
      cd my-app
      npx tailwindcss init -p
      
    2. Inicializa shadcn/ui

      npx shadcn-ui@latest init
      
    3. Añade componentes

      npx shadcn-ui@latest add button card dialog input
      
    4. Importa y personaliza Tus nuevos componentes aparecerán en components/ui/.

    🧩 shadcn frente a otras bibliotecas de interfaz

    Característicashadcn/uiChakra UIMaterial UIHeadless UI
    Propiedad del código✅ Te pertenece❌ Controlado por la biblioteca❌ Controlado por la biblioteca✅ Te pertenece
    EstilosTailwindStyled SystemEmotion / CSSTailwind
    Accesibilidad✅ Radix UI✅✅✅
    Temas✅ (variables CSS + Tailwind)✅✅⚙️ Personalizados
    Curva de aprendizaje🟢 Baja🟢 Media🔴 Alta🟡 Media
    Libertad de personalización🟢 Total🟡 Parcial🔴 Limitada🟢 Total

    Ideas principales

    • shadcn/ui no es un paquete, es un modelo de componentes de copiar y poseer.
    • Obtienes control real, sin dependencia del proveedor y una gran experiencia de desarrollo.
    • Construido con Tailwind, Radix y patrones modernos de React, es ideal para equipos que quieren una base de diseño clara, accesible y ampliable.

    Es el punto intermedio perfecto entre “construirlo todo tú mismo” y “depender de una biblioteca de interfaz pesada”.