componentes / lightbox
Lightbox
Visor de imágenes a pantalla completa con navegación, contador y subtítulos.
Cómo usar
Un `role="dialog"` modal renderizado en un portal: el foco queda atrapado, el scroll de la página se bloquea, Esc cierra y ←/→ navegan (dando la vuelta). `open` e `index` pueden ser controlados; sin ellos guarda su propio estado (`defaultOpen`, `defaultIndex`). El foco vuelve al elemento de origen al cerrar, salvo que `onCloseAutoFocus` llame a `preventDefault()`.
preview
Lightbox.tsx
import { useState } from "react";import { Lightbox } from "vaiperui"; const [open, setOpen] = useState(false); <button onClick={() => setOpen(true)}>Abrir</button><Lightbox open={open} onOpenChange={setOpen} items={[ { src: "/photos/road.jpg", alt: "Mountain road", caption: "Road" }, { src: "/photos/sky.jpg", alt: "Starry sky" }, ]}/>Predeterminado
preview
predeterminado.tsx
<Lightbox open={open} onOpenChange={setOpen} items={items} />Props
| Prop | Valores | Predeterminado | Descripción |
|---|---|---|---|
| items | { src, alt, caption? }[] | — | Imágenes a mostrar |
| open / defaultOpen | boolean | false | Visibilidad controlada / inicial |
| onOpenChange | (open: boolean) => void | ninguno | Llamado cuando pide cerrarse |
| index / defaultIndex | number | 0 | Imagen controlada / inicial |
| onIndexChange | (index: number) => void | ninguno | Llamado cuando cambia la imagen |
| label | string | Image viewer | Nombre accesible del diálogo |
| closeLabel / previousLabel / nextLabel | string | Close / Previous image / Next image | Nombres accesibles de los botones |
| counterLabel | (index, total) => string | 1 / 6 | Texto del contador |
| onCloseAutoFocus | (event: Event) => void | ninguno | Al cerrar; preventDefault() evita devolver el foco |
Accesibilidad
- El visor es un `role="dialog"` con `aria-modal="true"`, nombrado por `label`, renderizado en un portal.
- Al abrir, el foco entra y Tab circula dentro del diálogo (focus trap); el scroll de la página se bloquea mientras está abierto.
- Al cerrar, el foco vuelve al elemento que lo tenía antes, salvo que `onCloseAutoFocus` llame a `preventDefault()`.
- Cerrar, anterior y siguiente son botones reales nombrados por `closeLabel`, `previousLabel` y `nextLabel`; anterior/siguiente solo existen con más de una imagen y dan la vuelta.
- La imagen usa su `alt`, dentro de un `<figure>` con la `caption` como `<figcaption>`.
- El contador (`counterLabel`, p. ej. `2 / 5`) es una región `aria-live="polite"`, así que el cambio de imagen se anuncia.
Teclado
| Tecla | Acción |
|---|---|
| Esc | Cierra el visor |
| ArrowLeft / ArrowRight | Imagen anterior / siguiente (con más de una) |
| Tab / Shift+Tab | Circula por los botones dentro del diálogo |
Ten en cuenta
- Cada elemento necesita un `alt`; el componente no lo genera.
- Hacer clic en el fondo oscuro también cierra, pero es un atajo de mouse; quien usa teclado cierra con Esc o el botón de cerrar. Traduce las etiquetas al idioma de la página.