componentes / drawer
Drawer
Panel lateral que se desliza desde cualquier borde, con el mismo comportamiento de diálogo que Modal.
Cómo usar
Misma accesibilidad que `Modal` (foco atrapado, bloqueo de scroll, Esc, fondo). `side` elige el borde: los paneles izquierdo/derecho miden hasta 400px, los de arriba/abajo ocupan el ancho y hasta 80% del alto. Usa `DrawerClose` alrededor de un botón para cerrar desde dentro.
preview
Drawer.tsx
import { Button, Drawer, DrawerClose } from "vaiperui"; <Drawer trigger={<Button>Abrir</Button>} side="right" title="Filtros" footer={<DrawerClose><Button>Aplicar</Button></DrawerClose>}> Contenido del panel</Drawer>Lados
preview
lados.tsx
<Drawer side="top" title="top" trigger={<Button>top</Button>}>...</Drawer><Drawer side="right" title="right" trigger={<Button>right</Button>}>...</Drawer><Drawer side="bottom" title="bottom" trigger={<Button>bottom</Button>}>...</Drawer><Drawer side="left" title="left" trigger={<Button>left</Button>}>...</Drawer>Props
| Prop | Valores | Predeterminado | Descripción |
|---|---|---|---|
| title | ReactNode | obligatorio | Título y nombre accesible (aria-labelledby) |
| footer | ReactNode | ninguno | Botones de acción; sin él no se muestran ni el pie ni su divisor |
| trigger | ReactElement | ninguno | Elemento que lo abre; innecesario si es controlado |
| open / defaultOpen / onOpenChange | boolean / boolean / (open) => void | ninguno | Estado abierto controlado o no controlado |
| showClose / closeLabel | boolean / string | true / "Close" | Botón × en el encabezado y su nombre accesible |
| closeOnEscape / closeOnBackdropClick | boolean | true | Si Esc o clic en el fondo lo cierran |
| side | left | right | top | bottom | right | Borde donde se coloca el panel |
| animation | none | smooth | fast | bounce | smooth | Transición de entrada |
Accesibilidad
- El panel se renderiza en un portal en `document.body` con `role="dialog"` y `aria-modal="true"`.
- `title` se renderiza como `h2` y se enlaza con `aria-labelledby`; el cuerpo se enlaza con `aria-describedby`.
- Al abrir, el foco va al primer elemento enfocable del panel (o al propio panel) y vuelve al elemento enfocado antes al cerrar, si sigue en el DOM.
- Tab y Shift+Tab quedan atrapados dentro del panel mientras está abierto, y el scroll del body se bloquea.
- El disparador recibe `aria-haspopup="dialog"` y `aria-expanded`.
- El botón de cerrar tiene `aria-label` de `closeLabel` (por defecto "Close"); el fondo es `aria-hidden`.
Teclado
| Tecla | Acción |
|---|---|
| Tab / Shift+Tab | Mueve el foco entre los elementos del panel, volviendo al inicio/fin |
| Esc | Cierra (se desactiva con `closeOnEscape={false}`) |
Ten en cuenta
- `title` es obligatorio y debe describir el diálogo; traduce `closeLabel`, ya que su valor por defecto está en inglés.
- La página de fondo no se marca como `inert` ni `aria-hidden`; depende de `aria-modal` y de la trampa de Tab. Hacer clic en el fondo cierra, salvo con `closeOnBackdropClick={false}`.