default.tsx
1'use client';23import { Button } from '@/components/ui/button';4import { Drawer } from '@/components/ui/drawer';56const notifications = [7 { from: 'Jane', message: 'Your report is ready for download.' },8 { from: 'System Alert', message: 'Scheduled maintenance at 3:00 AM UTC.' },9 { from: 'John', message: 'Please review the updated project plan.' },10] as const;1112export function Default() {13 return (14 <Drawer>15 <Drawer.Trigger variant="outline">Open Drawer</Drawer.Trigger>16 <Drawer.Content side="right">17 <div className="flex flex-col gap-4">18 <h2 className="text-lg font-semibold">Notifications</h2>19 <p className="text-muted-foreground text-sm">20 You have 3 new messages and 1 system alert. Review them below.21 </p>2223 <div className="space-y-2 text-sm">24 {notifications.map((n) => (25 <div key={n.from} className="bg-accent/10 rounded-md border p-3">26 <strong>27 {n.from === 'System Alert' ? 'System Alert:' : `Message from ${n.from}:`}28 </strong>{' '}29 {n.message}30 </div>31 ))}32 </div>3334 <div className="mt-4 flex justify-end gap-2">35 <Drawer.Close>Dismiss All</Drawer.Close>36 <Button>View Details</Button>37 </div>38 </div>39 </Drawer.Content>40 </Drawer>41 );42}
Instalación
pnpm dlx nachui add drawerAnatomía
1import { Drawer } from '@/components/ui/drawer';
1<Drawer>2 <Drawer.Trigger>3 <Button>Abrir Drawer</Button>4 </Drawer.Trigger>5 <Drawer.Content>6 <Drawer.Header>7 <Drawer.Title>Título del Drawer</Drawer.Title>8 <Drawer.Description>Este es un componente drawer.</Drawer.Description>9 </Drawer.Header>10 <div>Tu contenido aquí</div>11 </Drawer.Content>12</Drawer>
Características
- Múltiples lados - Desliza desde abajo, arriba, izquierda o derecha
- Arrastrar para cerrar - Desliza para descartar en cualquier dirección
- Responsivo - Se adapta a diferentes tamaños de pantalla
- Animaciones suaves - Transiciones de deslizamiento basadas en resorte
- Trampa de foco - La navegación por teclado se mantiene dentro del drawer
- Bloqueo de scroll - Evita el desplazamiento del fondo cuando está abierto
Variantes
Posiciones (Positions)
positions.tsx
1'use client';23import { Drawer } from '@/components/ui/drawer';45const DRAWER_SIDES = ['top', 'right', 'bottom', 'left'] as const;67export function Positions() {8 return (9 <div className="grid grid-cols-2 gap-4">10 {DRAWER_SIDES.map((side) => (11 <Drawer key={side}>12 <Drawer.Trigger className="w-full capitalize" variant="outline">13 {side}14 </Drawer.Trigger>15 <Drawer.Content side={side}>16 <Drawer.Header>17 <Drawer.Title>Edit profile</Drawer.Title>18 <Drawer.Description>19 Make changes to your profile here. Click save when you're done.20 </Drawer.Description>21 </Drawer.Header>22 <div className="py-4">23 <p className="text-muted-foreground text-sm">24 This drawer is appearing from the {side}.25 </p>26 </div>27 <div className="flex justify-end">28 <Drawer.Close>Save changes</Drawer.Close>29 </div>30 </Drawer.Content>31 </Drawer>32 ))}33 </div>34 );35}
Formulario (Form)
form.tsx
1'use client';23import { Drawer } from '@/components/ui/drawer';4import { Input } from '@/components/ui/input';5import { Label } from '@/components/ui/label';67const fields = [8 { id: 'name', label: 'Name', defaultValue: 'Ignacio Figueroa', type: 'text' },9 { id: 'username', label: 'Username', defaultValue: '@figueroaignacio', type: 'text' },10] as const;1112export function Form() {13 return (14 <Drawer>15 <Drawer.Trigger variant="outline">Edit Profile</Drawer.Trigger>16 <Drawer.Content side="bottom">17 <Drawer.Header>18 <Drawer.Title>Edit profile</Drawer.Title>19 <Drawer.Description>20 Make changes to your profile here. Click save when you're done.21 </Drawer.Description>22 </Drawer.Header>23 <div className="grid gap-4 py-4">24 {fields.map((field) => (25 <div key={field.id} className="grid grid-cols-4 items-center gap-4">26 <Label htmlFor={field.id} className="text-right">27 {field.label}28 </Label>29 <Input30 id={field.id}31 type={field.type}32 defaultValue={field.defaultValue}33 className="col-span-3"34 />35 </div>36 ))}37 </div>38 <div className="flex justify-end">39 <Drawer.Close>Save changes</Drawer.Close>40 </div>41 </Drawer.Content>42 </Drawer>43 );44}
Referencia de API
Drawer
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
children | ReactNode | - | Activador y contenido del drawer |
defaultOpen | boolean | false | Estado abierto inicial |
open | boolean | - | Estado abierto controlado |
onOpenChange | (open: boolean) => void | - | Callback cuando cambia el estado |
Drawer.Trigger
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
children | ReactNode | - | Contenido del botón activador |
className | string | - | Clases CSS adicionales |
variant | ButtonProps['variant'] | - | Variante del botón |
size | ButtonProps['size'] | - | Tamaño del botón |
Drawer.Content
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
side | 'bottom' | 'top' | 'left' | 'right' | 'bottom' | Lado desde el que deslizar |
showDragHandle | boolean | true | Mostrar asa de arrastre para cerrar |
className | string | - | Clases CSS adicionales |
Drawer.Header
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | - | Clases CSS adicionales |
Drawer.Title
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | - | Clases CSS adicionales |
Drawer.Description
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
className | string | - | Clases CSS adicionales |
Drawer.Close
| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
children | ReactNode | - | Contenido clicable |
¿Encontraste algo que mejorar?
¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.