Passer au contenu principal

ConfirmModal

Implemented

Destructive-confirmation dialog — thin composition over the Modal molecule that owns the cancel/confirm action pair (danger variant by default, primary for archive/apply/clear) while the body (message, warnings, type-to-confirm input) stays consumer-owned. Extracted from 15 dashboard confirm sites (W2).

Categoryorganisms
Sourcecomponents/organisms/ConfirmModal/ConfirmModal.tsx
AI HintUse for delete/detach/cancel/archive confirmations. Danger variant by default; pass confirmVariant="primary" for non-destructive. Body stays yours — warnings, type-to-confirm inputs, error alerts.

Destructive-confirmation dialog — a thin composition over the Modal molecule that owns the cancel/confirm action pair (danger variant by default, primary for archive/apply/clear) while the body (message, warnings, type-to-confirm input) stays consumer-owned. Extracted from 15 dashboard confirm sites (W2).

ConfirmModal

Organism — Account & Admin family

Controlled confirm dialog. The organism owns the action pair — confirm is type="button" so it never submits an outer form — and the Modal molecule keeps the dialog chrome (portal, scrim, focus trap, ESC, scroll lock). Danger variant by default; pass confirmVariant="primary" for non-destructive confirmations. Omit cancelLabel for a single-action dialog (validate/acknowledge) with actionsAlign="center".

This component supports light and dark mode.

Usage

ConfirmModal is a controlled component — pair open with the id/state of the thing being confirmed and always wire onClose. The body stays yours: confirmation message, warning callouts, type-to-confirm inputs, error alerts. All strings are caller-owned (i18n).

import { ConfirmModal } from '@epasslive/design-system'

<ConfirmModal
  open={!!target}
  onClose={close}
  title={t('deleteConfirmTitle')}
  cancelLabel={t('cancel')}
  confirmLabel={t('delete')}
  confirmLoading={deleting}
  onConfirm={confirmDelete}
>
  <p>{t('deleteConfirm')}</p>
</ConfirmModal>

Variant discipline

confirmVariant defaults to "danger" — the canonical delete / detach / cancel-event confirm. Pass confirmVariant={"primary"} for non-destructive confirmations (archive, apply, clear); never pair destructive labels with the primary variant — that mismatches the affordance. For type-to-confirm flows, arm confirmDisabled from your input state and keep closeOnScrimClick={false} while the destructive request is in flight.

Single-action dialogs

Omit cancelLabel for a single-action dialog (validate/acknowledge) and set actionsAlign="center" — the confirm button centers in the footer. The action buttons are type="button", so they never submit an outer form even when the dialog opens from inside one. Use FormModal instead when the dialog needs a real form with submit semantics.

Accessibility

Dialog chrome comes from the Modal molecule — role="dialog", labelled by the title when set, ESC to close (topmost stacked modal only), focus trap with restore, body scroll lock. Pass title or ariaLabel so the dialog is named (WCAG 4.1.2).

Props

Prop
Type
Default
Description
open*
boolean
—

Whether the dialog is visible.

onClose*
() => void
—

Called when the dialog should close (ESC, scrim click).

title
string
—

Heading rendered in the dialog header.

ariaLabel
string
—

Accessible name when no visible heading is used.

size
"sm" | "md" | "lg" | "full"
'sm'

Panel width — sm, the destructive-confirm convention. Pass md/lg for wide confirms (display-info popups).

closeOnScrimClick
boolean
true

Set false for confirms that must be actioned explicitly (e.g. while a destructive request is in flight).

children*
React.ReactNode
—

Dialog body — confirmation message, warning callouts, type-to-confirm inputs, error alerts.

cancelLabel
React.ReactNode
—

Cancel button label (i18n). Omit for a single-action dialog (validate/acknowledge).

onCancel
() => void
onClose

Called when cancel is pressed.

cancelDisabled
boolean
—

Disable the cancel button (e.g. while deleting).

confirmLabel*
React.ReactNode
—

Confirm button label (i18n).

onConfirm*
() => void
—

Called when confirm is pressed.

confirmVariant
"primary" | "secondary" | "ghost" | "danger"
'danger'

Danger by default (delete/detach/cancel-event). Pass primary for non-destructive confirmations (archive, apply, clear).

confirmDisabled
boolean
—

Disable the confirm button (e.g. type-to-confirm not yet armed).

confirmLoading
boolean
—

Async confirm — also disables the button, guarding double-submits.

actionsSize
"sm" | "md" | "lg"
'sm'

Size for both action buttons — sm, the confirm convention.

actionsAlign
"end" | "center"
'end'

Footer alignment — end (cancel + confirm pair) or center (single-action acknowledge/validate rows).

Props

Preview

ConfirmModal

Prop
Type
Required
Default
Description
open
boolean
Required
—

Whether the dialog is visible.

onClose
() => void
Required
—

Called when the dialog should close (ESC, scrim click).

title
string
Optional
—

Heading rendered in the dialog header.

ariaLabel
string
Optional
—

Accessible name when no visible heading is used.

size
"sm" | "md" | "lg" | "full"
Optional
'sm'

Panel width — sm, the destructive-confirm convention. Pass md/lg for wide confirms (display-info popups).

closeOnScrimClick
boolean
Optional
true

Set false for confirms that must be actioned explicitly (e.g. while a destructive request is in flight).

children
React.ReactNode
Required
—

Dialog body — confirmation message, warning callouts, type-to-confirm inputs, error alerts.

cancelLabel
React.ReactNode
Optional
—

Cancel button label (i18n). Omit for a single-action dialog (validate/acknowledge).

onCancel
() => void
Optional
onClose

Called when cancel is pressed.

cancelDisabled
boolean
Optional
—

Disable the cancel button (e.g. while deleting).

confirmLabel
React.ReactNode
Required
—

Confirm button label (i18n).

onConfirm
() => void
Required
—

Called when confirm is pressed.

confirmVariant
"primary" | "secondary" | "ghost" | "danger"
Optional
'danger'

Danger by default (delete/detach/cancel-event). Pass primary for non-destructive confirmations (archive, apply, clear).

confirmDisabled
boolean
Optional
—

Disable the confirm button (e.g. type-to-confirm not yet armed).

confirmLoading
boolean
Optional
—

Async confirm — also disables the button, guarding double-submits.

actionsSize
"sm" | "md" | "lg"
Optional
'sm'

Size for both action buttons — sm, the confirm convention.

actionsAlign
"end" | "center"
Optional
'end'

Footer alignment — end (cancel + confirm pair) or center (single-action acknowledge/validate rows).

Quick use:<ConfirmModal />

Accessibility

ARIA roledialog

Type

1 rule

NASA Rule 5

confirmLabel + onConfirm required (NASA Rule 5); cancel optional for single-action dialogs

ARIA

1 rule

WCAG 4.1.2

Dialog chrome from Modal molecule (role=dialog, labelledby title, ESC + focus trap); action buttons are type=button so they never submit an outer form

Usage

Import

tsxSnippet
import { ConfirmModal } from "@epasslive/design-system"

Example 1

tsxSnippet
<ConfirmModal open={!!target} onClose={close} title={t('deleteConfirmTitle')} cancelLabel={t('cancel')} confirmLabel={t('delete')} confirmLoading={deleting} onConfirm={confirmDelete}><p>{t('deleteConfirm')}</p></ConfirmModal>

Anti-patterns

— Do not use for full form editing — use FormModal (it owns the form + submit semantics)

— Do not pass destructive labels with confirmVariant="primary" — mismatched affordance

Design System v4.1.0 | ePassLive