Skip to content

Dialog

Modal dialog with focus trap, scroll lock, restore-on-close, and compound header/body/footer API.

Overlays & Feedback·Available inReactVueAngular·View as Markdown

Preview

tsx

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/react

Then import the bundled stylesheet once at app entry: import "@sisyphos-ui/react/styles.css";

Usage

Idiomatic usage in each supported framework
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.

Anatomy
<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.

tsx

With form & initialFocus

`initialFocus` accepts a ref — the dialog focuses that element on open so keyboard users start on the first field.

tsx

Destructive confirm

Pair a dialog with a destructive action and a cautious copy — default focus stays on Cancel.

tsx

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.

tsx

No backdrop

Set `backdrop={false}` + `closeOnBackdropClick={false}` for contextual, in-place sheets.

tsx

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

KeyAction
TabMoves focus to the next focusable element within the dialog. Focus is trapped.
Shift+TabMoves focus to the previous focusable element.
EscCloses the dialog and returns focus to the trigger.
Need more?View on npm →
Was this page helpful?