GitHub

Confirm Dialog

Confirmation modal driven by attributes. Resolves a boolean through confirm / cancel / resolved events. Esc cancels.

Stable wc import '@esa/ecology/esa-confirm-dialog';

Preview

<button data-target="cd-default">Save changes</button>

<esa-confirm-dialog
  id="cd-default"
  heading="Save changes?"
  message="Your changes will be applied immediately."
  confirm-label="Save"
></esa-confirm-dialog>

Variants

Use warning for reversible-but-risky actions and danger for destructive ones.

<esa-confirm-dialog variant="warning" heading="Unsaved changes"
  message="You have unsaved changes that will be lost." confirm-label="Discard"></esa-confirm-dialog>
<esa-confirm-dialog variant="danger" heading="Delete project?"
  message="This action cannot be undone." confirm-label="Delete"></esa-confirm-dialog>

API

PropTypeDefaultDescription
open boolean false Reflected attribute that drives visibility. Open imperatively via show().
heading string '' Title of the confirmation.
message string '' Supporting body text.
variant 'default' | 'warning' | 'danger' 'default' Icon and confirm-button color theme.
confirm-label string 'Confirm' Label of the confirm button.
cancel-label string 'Cancel' Label of the cancel button.
show-icon boolean true Renders the variant icon above the heading.

Methods

PropTypeDefaultDescription
show() method Opens the dialog and focuses the confirm button.
confirm() method Resolves true and closes.
cancel() method Resolves false and closes.

Events

EventTypeDefaultDescription
confirm CustomEvent Fired when the user confirms.
cancel CustomEvent Fired when the user cancels (button, backdrop, or Esc).
resolved CustomEvent<{ confirmed: boolean }> Fired on either outcome with the boolean result.

Accessibility

  • The panel is role="alertdialog" with aria-modal="true"; heading is the accessible name.
  • The confirm button receives focus on open; Tab and Shift+Tab cycle between the two buttons.
  • Escape and backdrop click both resolve as cancel; focus is restored on close.

Theming surface

Every public token this component reads, extracted from its source at build time. The Resolves to column walks each token's real lineage — component → semantic → primitive → raw value — so you can see exactly where re-pointing it lands. A spoke re-skins by overriding these in its theme-<slug>.css; component internals are never edited. No hook for what you need? File it with /request-lego.

TokenTierResolves to
--confirm-dialog-bg component #fcfcfc via --color-surface-elevated--color-gray-1
--confirm-dialog-border-color component #d9d9d9 via --color-border-light--color-gray-6
--confirm-dialog-radius component 0.75rem via --radius-400
--confirm-dialog-width component 360px
--focus-ring-color component #65ba74 via --color-border-focus--color-grass-8
--focus-ring-width component 2px
--confirm-dialog-color ad-hoc #202020 via --color-text-primary--color-gray-12
--color-backdrop semantic rgba(0, 0, 0, 0.5) via --color-black-a-7
--color-border-strong semantic #bbbbbb via --color-gray-8
--color-danger semantic #e5484d via --color-red-9
--color-danger-subtle semantic #fff7f7 via --color-red-2
--color-info semantic #0090ff via --color-status-info--color-blue-9
--color-info-subtle semantic #f4faff via --color-status-info-subtle--color-blue-2
--color-primary semantic #46a758 via --color-grass-9
--color-primary-hover semantic #3e9b4f via --color-grass-10
--color-surface-sunken semantic #f0f0f0 via --color-gray-3
--color-text-inverse semantic #fcfcfc via --color-gray-1
--color-text-muted semantic #838383 via --color-gray-10
--color-text-primary semantic #202020 via --color-gray-12
--color-warning semantic #ffc53d via --color-status-warning--color-yellow-9
--color-warning-subtle semantic #fefbe9 via --color-status-warning-subtle--color-yellow-2
--focus-ring-offset semantic 2px
--font-sans semantic 'DM Sans', sans-serif
--line-height-normal semantic 1.6
--transition-fast semantic 150ms ease
--type-size-200 semantic clamp(0.75rem, 0.66rem + 0.44vw, 0.9375rem)
--type-size-400 semantic clamp(1rem, 0.88rem + 0.6vw, 1.25rem)
--font-weight-medium primitive 500
--font-weight-semibold primitive 550
--radius-200 primitive 0.5rem
--radius-full primitive 9999px
--spacing-150 primitive 0.375rem
--spacing-200 primitive 0.5rem
--spacing-300 primitive 0.75rem
--spacing-400 primitive 1rem
--spacing-500 primitive 1.5rem
--z-modal primitive 400
--z-modal-backdrop primitive 300