Loading Developer Playground

Loading ...

Skip to main content
ARIA ROLEWindow Roles

alertdialog

A type of dialog that contains an alert message, where initial focus goes to an element within the dialog. Used for important, time-sensitive information that requires user acknowledgment or action.

Implicit Role
None
Required Attributes
aria-labelledby or aria-label
Keyboard Support
Tab, Escape, Enter

Overview

The alertdialog role is used for modal dialogs that interrupt the user's workflow to communicate an important message and require a response. Unlike a standard dialog, an alertdialog conveys urgency and importance.

Alert dialogs are appropriate for error messages, confirmation prompts for destructive actions (like deleting data), or critical system notifications that require immediate attention.

When to Use Alert Dialog

  • • Confirming destructive actions (delete, remove, etc.)
  • • Displaying critical error messages
  • • Warning users about potential data loss
  • • Requiring acknowledgment of important information

Live Demo

Click the button to see an accessible alert dialog in action

Alert Dialog vs Dialog

alertdialog

  • Used for urgent, important messages
  • Requires immediate user response
  • Focus goes to an action button
  • Always modal (blocks background)
  • Screen readers announce with urgency

dialog

  • Used for general interactions
  • User can take time to interact
  • Focus goes to first focusable element
  • Can be modal or non-modal
  • Screen readers announce normally

Required Attributes

aria-labelledbyoraria-label

Every alert dialog must have an accessible name. Use aria-labelledby to reference the alert title, or aria-label to provide a direct label.

aria-describedby(strongly recommended)

Should reference the element containing the alert message. This ensures screen readers announce the full context of the alert.

Supported Attributes

aria-modal

Should be set to "true" for alert dialogs (always modal)

aria-describedby

References element(s) describing the alert message

aria-labelledby

References the element that labels the alert (usually the title)

aria-label

Provides a string label for the alert dialog

Code Examples

Basic Alert Dialog

<!-- Basic Alert Dialog Example -->
<div role="alertdialog" 
     aria-labelledby="alert-title" 
     aria-describedby="alert-desc"
     aria-modal="true">
  <h2 id="alert-title">Confirm Deletion</h2>
  <p id="alert-desc">
    Warning: This will permanently delete all your data. 
    This action cannot be undone.
  </p>
  <div>
    <button autofocus>Cancel</button>
    <button>Delete Permanently</button>
  </div>
</div>

Error Alert Dialog

<!-- Error Alert Dialog -->
<div role="alertdialog" 
     aria-labelledby="error-title" 
     aria-describedby="error-message"
     aria-modal="true">
  <div class="error-icon" aria-hidden="true">⚠️</div>
  <h2 id="error-title">Connection Error</h2>
  <p id="error-message">
    Unable to connect to the server. Please check your 
    internet connection and try again.
  </p>
  <button autofocus>Retry</button>
  <button>Cancel</button>
</div>

Confirmation Alert Dialog

<!-- Confirmation Alert Dialog -->
<div role="alertdialog" 
     aria-labelledby="confirm-title"
     aria-modal="true">
  <h2 id="confirm-title">Discard Changes?</h2>
  <p>
    You have unsaved changes. Are you sure you want to 
    leave this page? Your changes will be lost.
  </p>
  <div class="button-group">
    <button autofocus>Stay on Page</button>
    <button class="danger">Discard Changes</button>
  </div>
</div>

JavaScript Implementation

// JavaScript Alert Dialog Implementation
function showAlertDialog(options) {
  const { title, message, confirmText = 'OK', cancelText = 'Cancel' } = options;
  
  // Create dialog
  const dialog = document.createElement('div');
  dialog.setAttribute('role', 'alertdialog');
  dialog.setAttribute('aria-modal', 'true');
  dialog.setAttribute('aria-labelledby', 'alert-title');
  dialog.setAttribute('aria-describedby', 'alert-desc');
  
  // Store previously focused element
  const previouslyFocused = document.activeElement;
  
  // Build dialog HTML
  dialog.innerHTML = `
    <div class="alert-dialog-content">
      <h2 id="alert-title">${title}</h2>
      <p id="alert-desc">${message}</p>
      <div class="button-group">
        <button class="cancel-btn">${cancelText}</button>
        <button class="confirm-btn" autofocus>${confirmText}</button>
      </div>
    </div>
  `;
  
  // Create backdrop
  const backdrop = document.createElement('div');
  backdrop.className = 'alert-dialog-backdrop';
  backdrop.appendChild(dialog);
  document.body.appendChild(backdrop);
  
  // Prevent body scroll
  document.body.style.overflow = 'hidden';
  
  // Focus the confirm button (or first button with autofocus)
  setTimeout(() => {
    const autofocusBtn = dialog.querySelector('[autofocus]');
    if (autofocusBtn) {
      autofocusBtn.focus();
    }
  }, 0);
  
  // Handle button clicks
  return new Promise((resolve) => {
    const cancelBtn = dialog.querySelector('.cancel-btn');
    const confirmBtn = dialog.querySelector('.confirm-btn');
    
    const close = (confirmed) => {
      backdrop.remove();
      document.body.style.overflow = '';
      previouslyFocused?.focus();
      resolve(confirmed);
    };
    
    cancelBtn?.addEventListener('click', () => close(false));
    confirmBtn?.addEventListener('click', () => close(true));
    
    // Handle escape key
    dialog.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') {
        close(false);
      }
    });
    
    // Trap focus
    const focusableElements = dialog.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    const firstElement = focusableElements[0];
    const lastElement = focusableElements[focusableElements.length - 1];
    
    dialog.addEventListener('keydown', (e) => {
      if (e.key === 'Tab') {
        if (e.shiftKey && document.activeElement === firstElement) {
          e.preventDefault();
          lastElement.focus();
        } else if (!e.shiftKey && document.activeElement === lastElement) {
          e.preventDefault();
          firstElement.focus();
        }
      }
    });
  });
}

// Usage
const confirmed = await showAlertDialog({
  title: 'Delete File',
  message: 'Are you sure you want to delete this file? This cannot be undone.',
  confirmText: 'Delete',
  cancelText: 'Cancel'
});

if (confirmed) {
  // User confirmed
  deleteFile();
}

React Component

// React Alert Dialog Component
import { useEffect, useRef } from 'react';

function AlertDialog({ isOpen, onClose, onConfirm, title, message, confirmText = 'OK', cancelText = 'Cancel' }) {
  const dialogRef = useRef(null);
  const confirmBtnRef = useRef(null);
  const previousFocusRef = useRef(null);
  
  useEffect(() => {
    if (isOpen) {
      // Store previous focus
      previousFocusRef.current = document.activeElement;
      
      // Focus the confirm button
      setTimeout(() => {
        confirmBtnRef.current?.focus();
      }, 0);
      
      // Prevent body scroll
      document.body.style.overflow = 'hidden';
    } else {
      // Restore focus
      if (previousFocusRef.current) {
        previousFocusRef.current.focus();
      }
      
      // Restore body scroll
      document.body.style.overflow = '';
    }
    
    return () => {
      document.body.style.overflow = '';
    };
  }, [isOpen]);
  
  if (!isOpen) return null;
  
  const handleConfirm = () => {
    onConfirm?.();
    onClose();
  };
  
  return (
    <div
      className="alert-dialog-backdrop"
      onClick={(e) => {
        if (e.target === e.currentTarget) {
          onClose();
        }
      }}
    >
      <div
        ref={dialogRef}
        role="alertdialog"
        aria-labelledby="alert-dialog-title"
        aria-describedby="alert-dialog-desc"
        aria-modal="true"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="alert-icon" aria-hidden="true">⚠️</div>
        <h2 id="alert-dialog-title">{title}</h2>
        <p id="alert-dialog-desc">{message}</p>
        <div className="button-group">
          <button onClick={onClose}>
            {cancelText}
          </button>
          <button
            ref={confirmBtnRef}
            onClick={handleConfirm}
            className="primary"
          >
            {confirmText}
          </button>
        </div>
      </div>
    </div>
  );
}

// Usage
function App() {
  const [showAlert, setShowAlert] = useState(false);
  
  const handleDelete = () => {
    setShowAlert(true);
  };
  
  const confirmDelete = () => {
    // Perform deletion
    console.log('File deleted');
  };
  
  return (
    <>
      <button onClick={handleDelete}>Delete File</button>
      
      <AlertDialog
        isOpen={showAlert}
        onClose={() => setShowAlert(false)}
        onConfirm={confirmDelete}
        title="Confirm Deletion"
        message="Are you sure you want to delete this file? This action cannot be undone."
        confirmText="Delete"
        cancelText="Cancel"
      />
    </>
  );
}

Keyboard Support

Tab

Moves focus to the next focusable element inside the alert dialog.

Shift + Tab

Moves focus to the previous focusable element inside the alert dialog.

Escape

Closes the alert dialog (typically triggers cancel action).

Enter

Activates the focused button (confirm or cancel).

Best Practices

Always use alertdialog for critical messages requiring immediate action

Include both aria-labelledby and aria-describedby for context

Focus should go to the least destructive action (e.g., Cancel button)

Set aria-modal="true" to indicate background is inert

Provide clear, concise alert messages

Use distinct visual styling (warning colors, icons)

Keep the number of actions minimal (typically 2 buttons)

Trap focus within the alert dialog

×

Don't use alertdialog for non-urgent information

×

Don't overuse alertdialogs - they interrupt workflow

×

Don't focus on destructive actions by default

×

Don't use vague messages like "Are you sure?"

Accessibility Notes

Screen Reader Announcements

When an alert dialog opens, screen readers will announce it with higher priority than a standard dialog. The role, label, and description are announced immediately, alerting the user to the urgency of the message. This is why alertdialog should only be used for truly important messages.

Initial Focus Placement

For alert dialogs, focus should typically go to the least destructive action (usually the Cancel or Close button). This prevents accidental confirmation of destructive actions. Use the autofocus attribute or JavaScript to set initial focus appropriately.

Visual Indicators

Alert dialogs should have distinctive visual styling to convey urgency. Use warning colors (yellow, orange, red), prominent icons (⚠️, ⛔), and clear typography. This benefits all users, not just those using assistive technologies.

Modal Behavior

Alert dialogs are always modal and must block interaction with background content. Use aria-modal="true" and JavaScript to make background content inert. This ensures keyboard and screen reader users cannot accidentally interact with hidden content.

Related Roles

Specifications & Resources