Dialog
Tareas cortas que no justifican una página (crear acción, invitar). Esc cierra, Tab queda adentro.
Modal sobre @base-ui/react/dialog para tareas cortas que no justifican una página, como crear un equipo o invitar a alguien. Las confirmaciones destructivas de la app usan ConfirmDialog.
Instalación
shadcn
npx shadcn@latest add https://design.moodinary.com/r/dialog.jsonimport
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@moodinary/ui/components/dialog";Ejemplos
Nuevo equipo
Título, una línea de contexto, los campos justos y el footer con Cancelar y el primario a la derecha.
Código
new-action.tsx
import { Button } from "@moodinary/ui/components/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@moodinary/ui/components/dialog";
import { Input } from "@moodinary/ui/components/input";
import { Label } from "@moodinary/ui/components/label";
import { useCallback, useState } from "react";
export default function CreateTeam() {
const [open, setOpen] = useState(false);
const [name, setName] = useState("");
const close = useCallback(() => setOpen(false), []);
const show = useCallback(() => setOpen(true), []);
const submit = useCallback(
(event: React.FormEvent) => {
event.preventDefault();
setName("");
close();
},
[close]
);
return (
<>
<Button onClick={show}>Nuevo equipo</Button>
<Dialog onOpenChange={setOpen} open={open}>
<DialogContent>
<DialogHeader>
<DialogTitle>Nuevo equipo</DialogTitle>
<DialogDescription>
Los equipos agrupan miembros para capturar pulsos con contexto
(área, proyecto, sede).
</DialogDescription>
</DialogHeader>
<form className="space-y-4" onSubmit={submit}>
<div className="space-y-2">
<Label htmlFor="team-name">Nombre</Label>
<Input
autoFocus
id="team-name"
maxLength={80}
onChange={(event) => setName(event.target.value)}
placeholder="Equipo A"
required
value={name}
/>
</div>
<DialogFooter>
<Button onClick={close} type="button" variant="secondary">
Cancelar
</Button>
<Button disabled={!name.trim()} type="submit">
Crear equipo
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</>
);
}Props
Dialog
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| open | boolean | - | Estado controlado. |
| defaultOpen | boolean | false | Estado inicial sin controlar. |
| onOpenChange | (open: boolean) => void | - | Se llama al abrir o cerrar. |
| modal | boolean | "trap-focus" | true | Bloquea el resto de la página. |
DialogContent
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| showCloseButton | boolean | true | Muestra la X arriba a la derecha. |
| className | string | - | Clases extra. El ancho máximo es 440 px. |
Cuándo sí y cuándo no
Hacé
- Usá un título que diga la tarea: Nueva acción.
- Mantené el formulario en dos o tres campos.
- Poné el primario a la derecha del footer.
Evitá
- No abras un dialog desde otro dialog.
- No lo uses para confirmar borrados; la app usa ConfirmDialog.
- No metas tablas largas ni flujos de varios pasos.
Accesibilidad
- Esc cierra y el foco queda atrapado adentro mientras está abierto.
- Al cerrar, el foco vuelve al botón que lo abrió.
- El título se conecta con
aria-labelledbysolo.