Confirm Modal

Modal dialog for confirming potentially destructive or important actions. Provides a clear title, message, and two action buttons (primary and secondary). Used for delete confirmations, cancellations, and other user confirmations in CRUD workflows.

Default Confirmation Destructive Confirmation

📐 Context vs. Theme

Context = Physical placement in the layout (standard page vs. glassy overlay/hero).
Theme = Site-wide user preference (light/dark mode toggle 🌙).

The signed-in app uses GLASSY context for modals. Below previews show both Standard and Glassy contexts. Use the 🌙 toggle (top-right) to test how modals look in both themes. Modals should work correctly in all 4 combinations: Light+Standard, Light+Glassy, Dark+Standard, Dark+Glassy.

🎯 Design Intent

Confirm Modal ensures users explicitly confirm important or destructive actions before proceeding.

1. Default Confirmation

Neutral confirmation modal for non-destructive actions. Use when confirming standard operations (e.g., "Are you sure you want to proceed?"). Primary button uses standard green styling.

1.1 Standard Layout Preview

Standard Context

For use on normal app pages and content areas

1.2 Standard Layout HTML Snippet

HTML
<!-- Modal backdrop with overlay -->
<div class="modal-backdrop">
  <!-- Confirm modal dialog -->
  <div
    class="confirm-modal"
    role="dialog"
    aria-modal="true"
    aria-labelledby="confirm-modal-title"
    aria-describedby="confirm-modal-message">

    <!-- Header with title and close button -->
    <div class="confirm-modal-header">
      <h2 class="confirm-modal-title" id="confirm-modal-title">Confirm Action</h2>
      <button class="confirm-modal-close" aria-label="Close dialog">
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
    </div>

    <!-- Message body -->
    <p class="confirm-modal-message" id="confirm-modal-message">
      Are you sure you want to proceed with this action? This cannot be undone.
    </p>

    <!-- Action buttons -->
    <div class="confirm-modal-actions">
      <button class="btn btn--secondary">Cancel</button>
      <button class="btn btn--primary">Confirm</button>
    </div>
  </div>
</div>

1.3 Glassy Layout Preview

Glassy Context

For use on dark overlays and app content containers (signed-in pages)

1.4 Glassy Layout HTML Snippet

HTML
<!-- Modal backdrop with glassy overlay -->
<div class="modal-backdrop is-glassy">
  <!-- Confirm modal dialog with glassy styling -->
  <div
    class="confirm-modal is-glassy"
    role="dialog"
    aria-modal="true"
    aria-labelledby="confirm-modal-title"
    aria-describedby="confirm-modal-message">

    <!-- Header with title and close button -->
    <div class="confirm-modal-header">
      <h2 class="confirm-modal-title" id="confirm-modal-title">Confirm Action</h2>
      <button class="confirm-modal-close" aria-label="Close dialog">
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
    </div>

    <!-- Message body -->
    <p class="confirm-modal-message" id="confirm-modal-message">
      Are you sure you want to proceed with this action? This cannot be undone.
    </p>

    <!-- Action buttons: use glass variants for glassy context -->
    <div class="confirm-modal-actions">
      <button class="btn btn--secondary-glass">Cancel</button>
      <button class="btn btn--glass">Confirm</button>
    </div>
  </div>
</div>

2. Destructive Confirmation

Destructive confirmation modal for delete and other destructive actions. Use red/danger button styling to emphasize the destructive nature. Example: "Are you sure you want to delete this record? This action cannot be undone."

2.1 Standard Layout Preview

Standard Context

For use on normal app pages and content areas

2.2 Standard Layout HTML Snippet

HTML
<!-- Modal backdrop with overlay -->
<div class="modal-backdrop">
  <!-- Destructive confirmation modal -->
  <div
    class="confirm-modal"
    role="dialog"
    aria-modal="true"
    aria-labelledby="confirm-modal-title"
    aria-describedby="confirm-modal-message">

    <!-- Header with title and close button -->
    <div class="confirm-modal-header">
      <h2 class="confirm-modal-title" id="confirm-modal-title">Delete Record</h2>
      <button class="confirm-modal-close" aria-label="Close dialog">
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
    </div>

    <!-- Message body -->
    <p class="confirm-modal-message" id="confirm-modal-message">
      Are you sure you want to delete this record? This action cannot be undone and will permanently remove all associated data.
    </p>

    <!-- Action buttons: primary is now danger/delete -->
    <div class="confirm-modal-actions">
      <button class="btn btn--secondary">Cancel</button>
      <button class="btn btn--danger">Delete</button>
    </div>
  </div>
</div>

2.3 Glassy Layout Preview

Glassy Context

For use on dark overlays and app content containers (signed-in pages)

2.4 Glassy Layout HTML Snippet

HTML
<!-- Modal backdrop with glassy overlay -->
<div class="modal-backdrop is-glassy">
  <!-- Destructive confirmation modal with glassy styling -->
  <div
    class="confirm-modal is-glassy"
    role="dialog"
    aria-modal="true"
    aria-labelledby="confirm-modal-title"
    aria-describedby="confirm-modal-message">

    <!-- Header with title and close button -->
    <div class="confirm-modal-header">
      <h2 class="confirm-modal-title" id="confirm-modal-title">Delete Record</h2>
      <button class="confirm-modal-close" aria-label="Close dialog">
        <svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
        </svg>
      </button>
    </div>

    <!-- Message body -->
    <p class="confirm-modal-message" id="confirm-modal-message">
      Are you sure you want to delete this record? This action cannot be undone and will permanently remove all associated data.
    </p>

    <!-- Action buttons: secondary glass, danger primary (works on glass) -->
    <div class="confirm-modal-actions">
      <button class="btn btn--secondary-glass">Cancel</button>
      <button class="btn btn--danger">Delete</button>
    </div>
  </div>
</div>

Usage Guidelines

✅ Do

  • • Use for actions with significant consequences (delete, cancel, publish)
  • • Always provide a clear title describing the action
  • • Write descriptive message text explaining consequences
  • • Use btn--danger for destructive primary actions
  • • Use btn--secondary or btn--secondary-glass for cancel
  • • Ensure proper focus management (focus enters modal, returns on close)
  • • Support ESC key to close (expected by users)
  • • Use aria-labelledby and aria-describedby

❌ Don't

  • • Don't show confirmation for reversible actions
  • • Don't use confusing or vague titles
  • • Don't make the message longer than 3 lines (keep it concise)
  • • Don't swap button positions (primary on right always)
  • • Don't auto-focus on dangerous action; focus on cancel/safe option
  • • Don't overlay multiple modals (one at a time)
  • • Don't hardcode button labels (use translation keys for i18n)
  • • Don't apply inline styles; use DS classes only

♿ Accessibility Requirements

  • role="dialog" on modal container
  • aria-modal="true" to indicate modal behavior
  • aria-labelledby="[title-id]" references the title element
  • aria-describedby="[message-id]" references the message element
  • Focus trap: Keyboard focus should stay within the modal until closed
  • Focus restoration: When modal closes, focus returns to the element that triggered it
  • ESC key: Pressing ESC should close the modal (implement in JavaScript)
  • Keyboard navigation: Tab through buttons; Enter/Space to activate
  • Button labels: Make labels clear (e.g., "Delete" vs. "Confirm")

🎨 Standard vs. Glassy Rules

  • Standard context: Use .btn--primary and .btn--secondary
  • Glassy context: Use .btn--glass and .btn--secondary-glass
  • Destructive always: Use .btn--danger in both contexts (red is universal for danger)
  • Backdrop color: Use semi-transparent dark (standard) or dark radial gradient (glassy)
  • Modal backdrop: Add .is-glassy class to backdrop in glassy context

Implementation Notes

CSS Location

Modal CSS is defined inline in this documentation page for preview purposes. In production, move .confirm-modal, .confirm-modal-*, and .modal-backdrop styles to a dedicated confirm-modal.css file if reusing across multiple pages.

JavaScript Requirements

  • • Show/hide modal: Bind to button click events
  • • Close on backdrop click: (optional) Dismiss if user clicks outside modal
  • • Close on ESC key: Essential for accessibility
  • • Focus management: Move focus into modal on open, restore on close
  • • Focus trap (optional): Prevent focus from leaving modal via Tab key