# media-alert-dialog

A modal alert dialog for urgent messages that require acknowledgement

## Import

```ts
import '@videojs/html/ui/alert-dialog';
import '@videojs/html/ui/dialog-backdrop';
import '@videojs/html/ui/dialog-popup';
import '@videojs/html/ui/dialog-title';
import '@videojs/html/ui/dialog-description';
import '@videojs/html/ui/dialog-close';
```

## Anatomy

```html
<media-alert-dialog>
  <media-dialog-backdrop></media-dialog-backdrop>
  <media-dialog-popup>
    <media-dialog-title></media-dialog-title>
    <media-dialog-description></media-dialog-description>
    <media-dialog-close></media-dialog-close>
  </media-dialog-popup>
</media-alert-dialog>
```

## Behavior

Use an alert dialog for an urgent message that interrupts the user and requires acknowledgement. Your application controls when it opens and supplies its content.

`<media-alert-dialog>` adds alert semantics, while the other parts are the same elements [`<media-dialog>`](https://videojs.org/docs/framework/html/reference/components/dialog) uses. For general modal content, including a player opened from a thumbnail, use `<media-dialog>` instead.

Set the root’s `open` property to show the dialog. The root supplies alert state while the shared `media-dialog-backdrop` and `media-dialog-popup` siblings render the visual surfaces and semantics. The root updates the property and dispatches `open-change` when the dialog closes.

The close part and Escape close the dialog. The dialog stays rendered during a closing transition, then restores focus to the element that was focused before it opened.

## Styling

Use the open and transition data attributes to style visibility and animations:

| Attribute | Description |
| --- | --- |
| `data-open` | Present while the dialog is open, including its closing transition |
| `data-starting-style` | Present at the start of the opening transition |
| `data-ending-style` | Present during the closing transition |

```css
media-dialog-backdrop:not([data-open]),
media-dialog-popup:not([data-open]) {
  display: none;
}

media-dialog-backdrop[data-starting-style],
media-dialog-backdrop[data-ending-style],
media-dialog-popup[data-starting-style],
media-dialog-popup[data-ending-style] {
  opacity: 0;
}
```

## Accessibility

The dialog uses `role="alertdialog"` and `aria-modal="true"`. The title and description receive generated IDs that are connected with `aria-labelledby` and `aria-describedby`. Focus moves into the dialog when it opens, stays within it while open, and returns to the previously focused element when it closes. Content outside the dialog is inert while it is open. Pressing Escape closes the dialog.

## Examples

### Basic usage

**index.html**

```html
<div class="html-alert-dialog-basic">
  <button class="html-alert-dialog-basic__trigger" type="button">Open alert dialog</button>
  <media-alert-dialog>
    <media-dialog-backdrop class="html-alert-dialog-basic__backdrop"></media-dialog-backdrop>
    <media-dialog-popup class="html-alert-dialog-basic__dialog">
      <media-dialog-title class="html-alert-dialog-basic__title">Stop playback?</media-dialog-title>
      <media-dialog-description class="html-alert-dialog-basic__description">
        Your current playback position will be lost.
      </media-dialog-description>
      <media-dialog-close class="html-alert-dialog-basic__close">Continue</media-dialog-close>
    </media-dialog-popup>
  </media-alert-dialog>
</div>
```

**index.css**

```css
.html-alert-dialog-basic {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 240px;
  overflow: hidden;
  background: #111827;
  border-radius: 12px;
}

.html-alert-dialog-basic__trigger,
.html-alert-dialog-basic__close {
  padding: 8px 16px;
  color: #111827;
  cursor: pointer;
  background: #fff;
  border: 0;
  border-radius: 9999px;
}

.html-alert-dialog-basic__backdrop {
  position: absolute;
  inset: 0;
  background: rgb(3 7 18 / 92%);
  transition: opacity 150ms ease;
}

.html-alert-dialog-basic__dialog {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  gap: 12px;
  place-content: center;
  padding: 32px;
  color: #fff;
  text-align: center;
  transition: opacity 150ms ease;
}

.html-alert-dialog-basic__backdrop:not([data-open]),
.html-alert-dialog-basic__dialog:not([data-open]) {
  display: none;
}

.html-alert-dialog-basic__backdrop[data-starting-style],
.html-alert-dialog-basic__backdrop[data-ending-style],
.html-alert-dialog-basic__dialog[data-starting-style],
.html-alert-dialog-basic__dialog[data-ending-style] {
  opacity: 0;
}

.html-alert-dialog-basic__title,
.html-alert-dialog-basic__description {
  display: block;
}

.html-alert-dialog-basic__title {
  font-size: 20px;
  font-weight: 600;
}

.html-alert-dialog-basic__description {
  color: #d1d5db;
}

.html-alert-dialog-basic__close {
  justify-self: center;
}
```

**index.ts**

```ts
import '@videojs/html/ui/alert-dialog';
import '@videojs/html/ui/dialog-backdrop';
import '@videojs/html/ui/dialog-popup';
import '@videojs/html/ui/dialog-title';
import '@videojs/html/ui/dialog-description';
import '@videojs/html/ui/dialog-close';

const initializedDemos = new WeakSet<HTMLElement>();

function initializeDemos(): void {
  document.querySelectorAll<HTMLElement>('.html-alert-dialog-basic').forEach((demo) => {
    if (initializedDemos.has(demo)) return;

    initializedDemos.add(demo);

    const trigger = demo.querySelector<HTMLButtonElement>('.html-alert-dialog-basic__trigger');
    const dialog = demo.querySelector('media-alert-dialog');

    trigger?.addEventListener('click', () => {
      if (dialog) dialog.open = true;
    });
  });
}

initializeDemos();
document.addEventListener('astro:page-load', initializeDemos);
```

## API Reference

### media-alert-dialog

A modal dialog with alert semantics.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `closeOnEscape` (attribute `close-on-escape`) | `boolean` | — | Whether pressing Escape closes the dialog. |
| `defaultOpen` (attribute `default-open`) | `boolean` | — | Initial open state for uncontrolled usage. |
| `open` | `boolean` | — | Controlled open state. When set, the consumer is responsible for toggling. |

#### State

State is reflected as data attributes for CSS styling.

| Property | Type | Description |
| --- | --- | --- |
| `transitionStarting` | `boolean` | Whether the open transition is in progress. |
| `transitionEnding` | `boolean` | Whether the close transition is in progress. |
| `open` | `boolean` | Whether the dialog is currently open. |
| `status` | `'idle' \| 'starting' \| 'ending'` | Current phase of the transition lifecycle. |
| `titleId` | `string \| undefined` | Element ID of the dialog title, used for `aria-labelledby`. |
| `descriptionId` | `string \| undefined` | Element ID of the dialog description, used for `aria-describedby`. |

#### Events

| Event | Description |
| --- | --- |
| `open-change` | Fired when the dialog's open state changes. |
| `open-change-complete` | |

### media-dialog-backdrop

Presentational backdrop that reflects its owning dialog's state.

#### Data attributes

| Attribute | Description |
| --- | --- |
| `data-open` | Present when the dialog is open. |
| `data-starting-style` | Present during the open transition. |
| `data-ending-style` | Present during the close transition. |

### media-dialog-close

Button that closes its owning dialog; the element itself takes `role="button"` and keyboard focus.

#### Data attributes

| Attribute | Description |
| --- | --- |
| `data-open` | Present when the dialog is open. |
| `data-starting-style` | Present during the open transition. |
| `data-ending-style` | Present during the close transition. |

### media-dialog-description

Text announced as its owning dialog's description. The element takes the `id` that the popup's `aria-describedby` points to.

### media-dialog-popup

Semantic popup that owns focus management and dialog transition completion.

#### Data attributes

| Attribute | Description |
| --- | --- |
| `data-open` | Present when the dialog is open. |
| `data-starting-style` | Present during the open transition. |
| `data-ending-style` | Present during the close transition. |

### media-dialog-title

Text that labels its owning dialog. The element takes the `id` that the popup's `aria-labelledby` points to.

---

HTML documentation: https://videojs.org/docs/framework/html/llms.txt
All documentation: https://videojs.org/llms.txt
