Introduccion a shadcn/ui - Componentes de UI reutilizables

Principiante | 40 min de lectura | 2025.12.13

Lo que aprenderas en este tutorial

✓ Configuracion de shadcn/ui
✓ Agregar componentes
✓ Personalizacion de temas
✓ Construccion de formularios
✓ Modo oscuro

Step 1: Configuracion

npx create-next-app@latest my-app --typescript --tailwind
cd my-app
npx shadcn-ui@latest init

Selecciona lo siguiente en la configuracion inicial:

  • TypeScript: yes
  • Style: Default
  • Base color: Slate
  • CSS variables: yes

Step 2: Agregar componentes

# Agregar individualmente
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add input
npx shadcn-ui@latest add form

# Agregar multiples
npx shadcn-ui@latest add button card input dialog

Step 3: Uso basico

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';

export default function HomePage() {
  return (
    <div className="p-8">
      <Card className="max-w-md">
        <CardHeader>
          <CardTitle>Iniciar sesion</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <Input placeholder="Correo electronico" />
          <Input type="password" placeholder="Contrasena" />
          <Button className="w-full">Iniciar sesion</Button>
        </CardContent>
      </Card>
    </div>
  );
}

Step 4: Variantes

<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>

Step 5: Construccion de formularios

npx shadcn-ui@latest add form
npm install zod react-hook-form @hookform/resolvers
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';

const schema = z.object({
  email: z.string().email('Ingresa un correo electronico valido'),
  password: z.string().min(8, '8 caracteres o mas'),
});

export function LoginForm() {
  const form = useForm({
    resolver: zodResolver(schema),
    defaultValues: { email: '', password: '' },
  });

  const onSubmit = (data: z.infer<typeof schema>) => {
    console.log(data);
  };

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Correo electronico</FormLabel>
              <FormControl>
                <Input {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="password"
          render={({ field }) => (
            <FormItem>
              <FormLabel>Contrasena</FormLabel>
              <FormControl>
                <Input type="password" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit" className="w-full">Iniciar sesion</Button>
      </form>
    </Form>
  );
}
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';

export function ConfirmDialog() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="destructive">Eliminar</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>¿Estas seguro de eliminar?</DialogTitle>
          <DialogDescription>
            Esta accion no se puede deshacer.
          </DialogDescription>
        </DialogHeader>
        <div className="flex justify-end gap-2">
          <Button variant="outline">Cancelar</Button>
          <Button variant="destructive">Eliminar</Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}

Step 7: Personalizacion del tema

/* globals.css */
@layer base {
  :root {
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    /* Color personalizado */
  }

  .dark {
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
  }
}

Resumen

shadcn/ui es una biblioteca de UI basada en copiar y pegar, con total capacidad de personalizacion. Esta basada en Radix UI y Tailwind CSS.

← Volver a la lista