Configuración de shadcn/ui
Instala, configura y aplica tema a shadcn/ui - componentes copy-paste construidos sobre Radix UI y Tailwind CSS.
Busca en todas las páginas de la documentación
Instala, configura y aplica tema a shadcn/ui - componentes copy-paste construidos sobre Radix UI y Tailwind CSS.
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
Tarjeta de referencia rápida - lista para copiar y pegar.
# Inicializa shadcn en tu proyecto
npx shadcn@latest init
# Agrega componentes específicos
npx shadcn@latest add button
npx shadcn@latest add input
npx shadcn@latest add card
# Agrega varios a la vez
npx shadcn@latest add button input card dialog form// components.json - generado por init
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"tailwind": {
"config": "",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}// lib/utils.ts - la utilidad cn
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}Cuándo usarlo: Al inicio de cualquier proyecto Next.js o React en el que quieras componentes de UI pulidos y accesibles con control total sobre el código fuente.
/* app/globals.css - tema shadcn con variables CSS */
@import "tailwindcss";
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
@layer base {
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--radius: 0.625rem;
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
}
}// app/layout.tsx
import { ThemeProvider } from "next-themes";
import "@/app/globals.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body className="bg-background text-foreground antialiased">
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
);
}// Demostración rápida con componentes shadcn
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export function LoginCard() {
return (
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Iniciar sesión</CardTitle>
<CardDescription>Introduce tus credenciales para continuar.</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Correo electrónico</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="password">Contraseña</Label>
<Input id="password" type="password" />
</div>
<Button className="w-full">Iniciar sesión</Button>
</CardContent>
</Card>
);
}Qué demuestra esto:
ThemeProvider desde next-themescn() para fusionar nombres de clasecomponents/ui/ y son totalmente editablescn() fusiona nombres de clase con clsx y resuelve conflictos de Tailwind con tailwind-mergeColores de tema personalizados:
/* Usa el generador de temas de shadcn en ui.shadcn.com/themes */
:root {
--primary: oklch(0.5 0.2 260); /* azul personalizado */
--destructive: oklch(0.5 0.2 25); /* rojo personalizado */
}Agregar un componente con dependencias:
# Algunos componentes instalan automáticamente sus dependencias
npx shadcn@latest add dialog
# Esto instala @radix-ui/react-dialog y el componente DialogConfiguración de alias de rutas:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}// La utilidad cn está completamente tipada
import { cn } from "@/lib/utils";
cn("bg-red-500", undefined, false, "text-white");
// devuelve "bg-red-500 text-white"
// Los props del componente extienden tipos de Radix
// p. ej., Button extiende React.ButtonHTMLAttributes<HTMLButtonElement>
import { Button, type ButtonProps } from "@/components/ui/button";
function MyButton(props: ButtonProps) {
return <Button variant="outline" {...props} />;
}No es un paquete - es código fuente - npm install shadcn es incorrecto. Solución: Usa npx shadcn@latest add <component> para copiar componentes en tu proyecto.
Compatibilidad con Tailwind v4 - shadcn/ui es compatible con Tailwind v4. Asegúrate de ejecutar la última versión de npx shadcn@latest init, que genera el CSS compatible con v4.
Las variables CSS deben estar definidas - Si omites la configuración de variables CSS, los componentes se renderizan sin colores. Solución: Asegúrate de que tu globals.css incluya los bloques completos de variables :root y .dark.
Ruta de importación de cn() - Los componentes importan desde @/lib/utils. Si tu alias es distinto, actualiza components.json y ejecuta init de nuevo.
Actualizaciones de componentes - Como los componentes se copian, no se actualizan automáticamente. Solución: Vuelve a ejecutar npx shadcn@latest add <component> para obtener la última versión (pero esto sobrescribe tus cambios).
| Alternativa | Úsala cuando | No la uses cuando |
|---|---|---|
| Radix UI (bare) | Quieres primitivos sin opiniones sobre el estilo | Quieres componentes preestilizados y listos para usar |
| Headless UI | Usas Tailwind pero prefieres otra biblioteca de primitivos | Quieres el ecosistema completo de shadcn |
| MUI / Chakra UI | Quieres una biblioteca de componentes totalmente empaquetada | Quieres control total sobre el código fuente de los componentes |
| Mantine | Quieres una biblioteca de componentes React con todo incluido | Usas Tailwind para el estilo |
No. shadcn/ui copia el código fuente de los componentes en tu proyecto. Usa npx shadcn@latest add <component>, no npm install shadcn.
components.json con la configuración del proyectolib/utils.ts con la utilidad cn()globals.css para el themingcn() combina clsx (fusión condicional de clases) con tailwind-merge (resolución de conflictos de Tailwind). Garantiza que las sobrescrituras de className funcionen correctamente en los componentes shadcn.
En components/ui/ por defecto. Cada componente es un archivo fuente totalmente editable, no una dependencia de node_modules.
Edita las variables CSS en globals.css bajo :root (claro) y .dark (oscuro). Usa el generador de temas en ui.shadcn.com/themes para presets rápidos.
Las variables CSS se definen dos veces: una en :root para el modo claro y otra en .dark para el modo oscuro. Usa next-themes con attribute="class" para alternar la clase .dark.
npx shadcn@latest add button input card dialog formFaltan las variables CSS. Asegúrate de que globals.css incluya los bloques completos de variables :root y .dark generados por npx shadcn@latest init.
Volver a ejecutar npx shadcn@latest add <component> sobrescribe el archivo. Haz una copia de seguridad de tus personalizaciones antes de actualizar, o usa control de versiones.
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}ClassValue acepta strings, arrays, objetos, undefined, null y booleanos.
import { Button, type ButtonProps } from "@/components/ui/button";
function MyButton(props: ButtonProps) {
return <Button variant="outline" {...props} />;
}Los props del componente extienden sus tipos subyacentes de Radix o del elemento HTML.
Revisado por Chris St. John·Última actualización: 16 jul 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥