Marble UI
← Components

Alert Dialog

Preview: Alert

Modal dialog: overlay + modal + dialog in one. Put it inside a DialogTrigger, after the trigger button.

Import

import { Dialog, DialogHeader, DialogBody, DialogFooter, AlertDialog, DialogTrigger } from '@marbleui/ui'

This is a style of dialog; see its examples for all variants.

Props

<Dialog>

PropTypeDefaultDescription
children *requiredReactNode—
isDismissablebooleantrue
overlayPropsOmit<ModalOverlayProps, 'children'>—
size'sm' | 'md' | 'lg''md'

Also accepts React Aria props (81).

<DialogHeader>

PropTypeDefaultDescription
title *requiredReactNode—
classNamestring—
descriptionReactNode—

<DialogBody>

PropTypeDefaultDescription
children *requiredReactNode—
classNamestring—
idstring—

<DialogFooter>

PropTypeDefaultDescription
children *requiredReactNode—
classNamestring—

<AlertDialog>

Confirmation dialog for destructive or important actions (role="alertdialog"). The body describes the dialog (aria-describedby). Focus starts on the action, or on Cancel when `destructive`, so Enter can't confirm by accident.

PropTypeDefaultDescription
actionLabel *requiredstring—
children *requiredReactNode—
title *requiredReactNode—
cancelLabelstring'Cancel'
destructiveboolean—
onAction() => void—

<DialogTrigger>

Re-exported from React Aria DialogTrigger; see its documentation for props.

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Dialog · React Aria DialogTrigger · React Aria Heading · React Aria Modal · React Aria ModalOverlay. Follow the primitive's docs for the full keyboard map.

Usage notes

AlertDialog is the confirmation style of Dialog: a small modal with role="alertdialog", a title, a message, and Cancel plus one action. Put it in a DialogTrigger after the button that opens it.

<DialogTrigger>
  <Button variant="danger">Delete workspace</Button>
  <AlertDialog title="Delete workspace?" actionLabel="Delete" destructive onAction={deleteWorkspace}>
    This permanently removes 12 projects and 340 issues.
  </AlertDialog>
</DialogTrigger>
  • Clicking outside doesn’t close it; Escape and the cancel button (cancelLabel) do, without calling onAction.
  • onAction runs and the dialog closes straight away. There’s no pending or error state, so for a request that can fail build it from Dialog and your own DialogFooter.
  • Focus starts on the action button, so Enter confirms at once, except with destructive, where it starts on Cancel. Label the action with the verb (“Delete”, not “OK”) and put the consequence in the message, which is the dialog’s description (aria-describedby).
  • For lighter, undoable confirmations next to the trigger use Popconfirm.
Example source · show
import { Button } from '../button'
import { Select, SelectItem } from '../select'
import { TextField } from '../text-field'
import { AlertDialog, Dialog, DialogBody, DialogFooter, DialogHeader, DialogTrigger } from './dialog'

export const styles = {
  Form: () => (
    <DialogTrigger>
      <Button>New project</Button>
      <Dialog>
        {({ close }) => (
          <>
            <DialogHeader title="Create project" description="Projects group issues, docs and members." />
            <DialogBody className="flex flex-col gap-4">
              <TextField label="Name" placeholder="Website redesign" autoFocus />
              <Select label="Team" defaultSelectedKey="design">
                <SelectItem id="design">Design</SelectItem>
                <SelectItem id="eng">Engineering</SelectItem>
                <SelectItem id="growth">Growth</SelectItem>
              </Select>
            </DialogBody>
            <DialogFooter>
              <Button variant="outline" onPress={close}>Cancel</Button>
              <Button onPress={close}>Create</Button>
            </DialogFooter>
          </>
        )}
      </Dialog>
    </DialogTrigger>
  ),
  Alert: () => (
    <DialogTrigger>
      <Button variant="danger">Delete workspace</Button>
      <AlertDialog title="Delete workspace?" actionLabel="Delete" destructive>
        This permanently removes 12 projects and 340 issues. This can't be undone.
      </AlertDialog>
    </DialogTrigger>
  ),
  Content: () => (
    <DialogTrigger>
      <Button variant="outline">Terms of service</Button>
      <Dialog size="lg">
        {({ close }) => (
          <>
            <DialogHeader title="Terms of service" description="Last updated October 2026" />
            <DialogBody className="max-h-72 space-y-3 leading-relaxed">
              {Array.from({ length: 6 }, (_, i) => (
                <p key={i}>
                  {i + 1}. You keep ownership of everything you create. We only process it to run the service, and you can
                  export or delete it at any time.
                </p>
              ))}
            </DialogBody>
            <DialogFooter>
              <Button onPress={close}>I agree</Button>
            </DialogFooter>
          </>
        )}
      </Dialog>
    </DialogTrigger>
  ),
}

Source: packages/ui/src/dialog/dialog.tsx

Catalog

Category
overlays
Priority
Core
Primitive
react-aria
React Aria
Dialog (role="alertdialog")
Base UI
Alert Dialog