Dialog
Modal dialog with focus trap, scroll lock, restore-on-close, and compound header/body/footer API.
Preview
Switch the framework picker (top-right of the panel) to render the same demo live in React, Vue, or Angular — same class names, ARIA, and visual output across all three.
Installation
Sisyphos UI ships unified packages for React, Vue, and Angular. Pick the one that matches your stack — every framework exports the same component classes, ARIA semantics, and CSS tokens.
$ pnpm add @sisyphos-ui/reactThen import the bundled stylesheet once at app entry: import "@sisyphos-ui/react/styles.css";
Usage
import { useState } from "react";
import { Button, Dialog } from "@sisyphos-ui/react";
export function ConfirmDelete() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)} color="error">Delete</Button>
<Dialog open={open} onOpenChange={setOpen} size="md">
<Dialog.Header>
<Dialog.Title>Delete this item?</Dialog.Title>
<Dialog.Close />
</Dialog.Header>
<Dialog.Body>
<Dialog.Description>This action cannot be undone.</Dialog.Description>
</Dialog.Body>
<Dialog.Footer>
<Button variant="outlined" onClick={() => setOpen(false)}>Cancel</Button>
<Button color="error" onClick={() => setOpen(false)}>Delete</Button>
</Dialog.Footer>
</Dialog>
</>
);
}Anatomy
The Dialog is a compound component. Compose the parts that match your use case.
<Dialog.Root>
<Dialog.Trigger />// Button that opens the dialog.
<Dialog.Overlay />// Scrim behind the dialog; closes on click.
<Dialog.Content />// Focus-trapped panel.required
<Dialog.Header />// Optional titled header slot.
<Dialog.Body />// Scrollable content region.
<Dialog.Footer />// Action buttons row.
<Dialog.Close />// Closes the dialog and restores focus.
</Dialog.Root>Sizes
`size` caps `max-width`. Use `full` to fill the viewport.
With form & initialFocus
`initialFocus` accepts a ref — the dialog focuses that element on open so keyboard users start on the first field.
Destructive confirm
Pair a dialog with a destructive action and a cautious copy — default focus stays on Cancel.
Auto-rendered close button
Set `showCloseButton` to get a close affordance in the top-right without composing `<Dialog.Close />` manually. `closeButtonLabel` overrides the aria-label.
No backdrop
Set `backdrop={false}` + `closeOnBackdropClick={false}` for contextual, in-place sheets.
API
Props table is being written. See the package README for the complete API surface.
The full API including refs, ARIA attributes, and HTML passthroughs lives in the package README on npm.
Accessibility
Adheres to the Dialog (Modal) WAI-ARIA design pattern.
Keyboard interactions
| Key | Action |
|---|---|
| Tab | Moves focus to the next focusable element within the dialog. Focus is trapped. |
| Shift+Tab | Moves focus to the previous focusable element. |
| Esc | Closes the dialog and returns focus to the trigger. |