useDialog

useDialog() is the imperative half of the Dialog API. Call it once in your component to get { confirm, alert }, then fire either helper from any event handler, effect, or callback — no DialogRoot, no Dialog JSX, no open state to thread through. Both helpers render through the app-wide dialog portal mounted by CladdProvider.

Reach for it when the trigger isn't an obvious button — a confirm at the tail of a network flow, an alert when an effect detects a stale tab, a destructive guard fired from a context menu — and writing JSX for the dialog just adds noise. For the compound / controlled JSX forms and the full prop reference, see the Dialog page.

<div className="flex flex-wrap gap-2">
  <Button
    onClick={() =>
      dialog.alert({
        title: 'Build finished',
        text: 'api/v2 deployed in 1.4s. Logs are in the deploy panel.',
      })
    }
  >
    Show alert
  </Button>
  <Button
    color="brand"
    variant="gradient"
    onClick={() =>
      dialog.confirm({
        title: 'Send invite?',
        text: 'jamie@acme.studio will get an email with a join link.',
        confirmButtonText: 'Send invite',
      })
    }
  >
    Confirm action
  </Button>
  <Button
    color="red"
    variant="gradient"
    onClick={() =>
      dialog.confirm({
        title: 'Reset all settings?',
        text: 'This restores defaults across every panel. Your saved presets are kept.',
        confirmButtonText: 'Reset',
        confirmButtonColor: 'red',
        requireConfirmText: 'reset',
      })
    }
  >
    Destructive confirm
  </Button>
</div>

Usage

import { Button, useDialog } from '@cladd-ui/react';
 
function DeleteButton({ name }) {
  const dialog = useDialog();
  return (
    <Button
      color="red"
      onClick={() =>
        dialog.confirm({
          title: `Delete ${name}?`,
          text: 'This cannot be undone.',
          confirmButtonText: 'Delete',
          confirmButtonColor: 'red',
          onConfirm: () => destroy(name),
        })
      }
    >
      Delete
    </Button>
  );
}

confirm() builds the standard cancel + confirm row and accepts the same requireConfirmText guard as the JSX form for irreversible actions. alert() builds a single-button "Ok" dialog for fire-and-forget notices. Both forward the standard Dialog props (title, text, requireConfirmText, confirmButtonColor, callbacks, …).

Signature

function useDialog(options?: UseDialogOptions): {
  confirm: (options: UseDialogConfirmOptions) => void;
  alert: (options: UseDialogAlertOptions) => void;
};

The hook itself is a thin wrapper over the portal queue mounted by CladdProvider — calling it has no per-render cost, and the returned helpers are stable across renders.

API Reference

useDialog options

lazy: booleanfalseSet to true when the dialog is rendered inside a React lazy() + Suspense boundary so it opens on the next tick (after the lazy chunk has resolved and mounted). Default false.

confirm() options

Opens a dialog with the standard cancel + confirm row. Accepts the same requireConfirmText guard as the JSX form for destructive flows.

cancelButtonColor: Color'neutral'Cancel button color. Default 'neutral'.
cancelButtonText: ReactNode'Cancel'Cancel button label. Default 'Cancel'.
confirmButtonColor: ColorConfirm button color. Default: theme accent color.
confirmButtonText: ReactNode'Confirm'Confirm button label. Default 'Confirm'.
onCancel: (cancelled: boolean) => voidFires when the cancel button is pressed. Always called with false.
onClosed: (closed: boolean) => voidFires after the close transition completes — use for unmount cleanup.
onConfirm: (confirmed: boolean) => voidFires when the confirm button is pressed (and the requireConfirmText guard passes). Always called with true.
requireConfirmText: boolean | string | ReactNodeType-to-confirm guard. When set, renders an Input and disables the confirm button until the user types this exact value verbatim — used for irreversible destructive actions.
stopPropagationOnClick: booleanStop click propagation on backdrop and surface. Useful when the dialog is rendered inside a clickable parent.
text: string | ReactNodeDialog body text — auto-wired to aria-describedby.
title: stringDialog title — auto-wired to aria-labelledby.

alert() options

Opens a dialog with a single confirm button — the fire-and-forget "Ok" notice.

confirmButtonText: ReactNode'Ok'Confirm button label. Default 'Ok'.
onClosed: (closed: boolean) => voidFires after the close transition completes — use for unmount cleanup.
onConfirm: (confirmed: boolean) => voidFires when the confirm button is pressed. Always called with true.
stopPropagationOnClick: booleanStop click propagation on backdrop and surface. Useful when the dialog is rendered inside a clickable parent.
text: string | ReactNodeDialog body text — auto-wired to aria-describedby.
title: stringDialog title — auto-wired to aria-labelledby.

Notes

  • Needs CladdProvider. The hook pushes onto the dialog portal mounted by the provider — calling it outside the provider is a no-op.
  • One at a time. The portal renders a single dialog instance. If you fire two confirm()s back-to-back, the second replaces the first; queue them yourself if you really need a chain.
  • For the JSX form, see Dialog. Compound API, controlled mode, the requireConfirmText guard, the buttons slot, custom content — everything that takes more than title + text lives there.