# Dialog

> Una tarea corta encima de la página, sin perder el contexto de atrás.

```tsx
import { Dialog, DialogClose, DialogContent, DialogDescription, … } from "sebs7n-ui/dialog"
```

## Ejemplos

### Básico

El trigger usa `render={<Button … />}`, no `asChild`.

```tsx
import { Button } from "sebs7n-ui/button"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "sebs7n-ui/dialog"
import { Input } from "sebs7n-ui/input"
import { Label } from "sebs7n-ui/label"
import { useId } from "react"

function Basico() {
  const id = useId()
  return (
    <Dialog>
      <DialogTrigger render={<Button variant="outline" />}>Editar cliente</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Editar cliente</DialogTitle>
          <DialogDescription>Los cambios se aplican a las facturas nuevas, no a las emitidas.</DialogDescription>
        </DialogHeader>
        <div className="flex flex-col gap-2">
          <Label htmlFor={id}>Razón social</Label>
          <Input defaultValue="Acme S.A." id={id} />
        </div>
        <DialogFooter>
          <DialogClose render={<Button variant="ghost" />}>Cancelar</DialogClose>
          <DialogClose render={<Button variant="accent" />}>Guardar</DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
```

### Controlado, con carga

`open` en el estado de la app: el diálogo se cierra cuando termina la operación.

```tsx
import { Button } from "sebs7n-ui/button"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "sebs7n-ui/dialog"
import { useState } from "react"

function Controlado() {
  const [abierto, setAbierto] = useState(false)
  const [guardando, setGuardando] = useState(false)
  return (
    <Dialog onOpenChange={setAbierto} open={abierto}>
      <DialogTrigger render={<Button />}>Emitir factura</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Emitir la factura 0014</DialogTitle>
          <DialogDescription>Se envía a AFIP y después no se puede editar.</DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose render={<Button variant="ghost" />}>Cancelar</DialogClose>
          <Button
            loading={guardando}
            onClick={() => {
              setGuardando(true)
              setTimeout(() => {
                setGuardando(false)
                setAbierto(false)
              }, 1400)
            }}
            variant="accent"
          >
            Emitir
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
```

## Props

### Dialog

Hereda las props de `Dialog.Root`.

Sin props propias: pasa todo al primitivo.

### DialogClose

Hereda las props de `Dialog.Close`.

Sin props propias: pasa todo al primitivo.

### DialogContent

Hereda las props de `Dialog.Popup`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `showCloseButton` | `boolean` | `true` | El botón X de la esquina. Si lo sacás, tiene que haber otra salida visible. |
| `className` | `string` | — | — |

### DialogDescription

Hereda las props de `Dialog.Description`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### DialogFooter

Hereda las props de `<div>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### DialogHeader

Hereda las props de `<div>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### DialogOverlay

Hereda las props de `Dialog.Backdrop`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### DialogTitle

Hereda las props de `Dialog.Title`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### DialogTrigger

Hereda las props de `Dialog.Trigger`.

Sin props propias: pasa todo al primitivo.

## Teclado

| Tecla | Qué hace |
|---|---|
| Enter · Espacio | Abre desde el trigger. |
| Tab · ⇧Tab | Recorre solo el contenido del diálogo: el foco queda atrapado adentro. |
| Escape | Cierra y devuelve el foco al trigger. |
| Click en el fondo | Cierra. |

## Accesibilidad

- `DialogTitle` no es opcional: es el nombre accesible del diálogo. Si no querés mostrarlo, ocultalo visualmente pero dejalo en el DOM.
- `DialogDescription` se asocia con `aria-describedby` y se lee después del título.
- El foco entra al abrir y vuelve al trigger al cerrar, y el fondo queda inerte.
- El botón X trae su propio nombre accesible; `showCloseButton={false}` obliga a dejar otra salida visible.

## Reglas de uso

- **Los triggers usan `render={<Button … />}`, no `asChild`.**
- Para confirmar algo destructivo, `AlertDialog`: no se cierra con click afuera y exige una respuesta.
- En mobile, un formulario largo no va en Dialog: va en una página o en un `Sheet`.
- El footer va con la acción principal a la derecha y «Cancelar» a su izquierda.

## Relacionados

[alert-dialog](/docs/components/alert-dialog.md) · [sheet](/docs/components/sheet.md) · [popover](/docs/components/popover.md)
