# ErrorDialog

An alert dialog that presents and dismisses playback errors

## Import

```tsx
import { ErrorDialog } from '@videojs/react';
```

## Anatomy

```tsx
<ErrorDialog.Root>
  <ErrorDialog.Backdrop />
  <ErrorDialog.Popup>
    <ErrorDialog.Title />
    <ErrorDialog.Description />
    <ErrorDialog.Close />
  </ErrorDialog.Popup>
</ErrorDialog.Root>
```

## Behavior

`ErrorDialog` is a specialized root driven by the player’s [error feature](https://videojs.org/docs/framework/react/reference/api/feature-error). It uses alert semantics and reuses the backdrop, popup, title, description, and close parts from [`Dialog`](https://videojs.org/docs/framework/react/reference/components/dialog); it is not nested inside `AlertDialog`. It opens when the attached media reports an error and stays hidden otherwise. Closing it dismisses the current error in the player store.

The title, description, and close label use localized default text. Provide children to any of those parts to replace its default content. Known media error codes use the matching translated message, while custom error messages are shown as written.

The included player skins already render an error dialog. Compose this component directly when building a custom skin.

## Styling

Use `data-open`, `data-starting-style`, and `data-ending-style` to style visibility and transitions.

React renders the backdrop and popup as separate DOM elements. Add a `className` to each part and style their transitions independently:

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

## Accessibility

The popup uses `role="alertdialog"`. Its title and description are connected with `aria-labelledby` and `aria-describedby`.

Modality is scoped to the player container rather than the page. While the error is open, the rest of the container is inert and focus that lands elsewhere inside it returns to the popup, but content outside the player stays interactive and `aria-modal` is omitted. Only when the popup renders outside the container does the dialog fall back to document-wide modality: `aria-modal="true"`, Tab cycling within the popup, and everything outside it inert.

Pressing Escape or activating the close part dismisses the error.

## Examples

The example replaces the video source with invalid local data so the media element reports an error without making a failing network request.

### Basic usage

**App.tsx**

```tsx
import { Container, createPlayer, ErrorDialog } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';
import { useRef } from 'react';

const { Player } = createPlayer({ features: videoFeatures });
const brokenSource = 'data:video/mp4;base64,AAAA';

export default function BasicUsage() {
  const videoRef = useRef<HTMLVideoElement>(null);

  const triggerError = () => {
    const video = videoRef.current;
    if (!video) return;

    video.src = brokenSource;
    video.load();
  };

  return (
    <Player>
      <Container className="react-error-dialog-basic">
        <Video
          ref={videoRef}
          className="react-error-dialog-basic__video"
          src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <button className="react-error-dialog-basic__trigger" type="button" onClick={triggerError}>
          Trigger a playback error
        </button>
        <ErrorDialog.Root>
          <ErrorDialog.Backdrop className="react-error-dialog-basic__backdrop" />
          <ErrorDialog.Popup className="react-error-dialog-basic__dialog">
            <ErrorDialog.Title className="react-error-dialog-basic__title" />
            <ErrorDialog.Description className="react-error-dialog-basic__description" />
            <ErrorDialog.Close className="react-error-dialog-basic__close" />
          </ErrorDialog.Popup>
        </ErrorDialog.Root>
      </Container>
    </Player>
  );
}
```

**App.css**

```css
.react-error-dialog-basic {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 12px;
}

.react-error-dialog-basic__video {
  display: block;
  width: 100%;
}

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

.react-error-dialog-basic__trigger {
  position: absolute;
  bottom: 16px;
  left: 16px;
}

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

.react-error-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;
}

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

.react-error-dialog-basic__title {
  font-size: 20px;
  font-weight: 600;
}

.react-error-dialog-basic__description {
  color: #d1d5db;
}

.react-error-dialog-basic__close {
  justify-self: center;
}
```

## API Reference

### Root

Opens from player error state and provides it to the shared dialog parts.

#### State

State is accessible via the `render`, `className`, and `style` props.

| 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`. |

### Close

Renders a localized button that closes the dialog and dismisses the player error.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string \| ((state: DialogState) => string \| undefined)` | — | Class name or function returning class name from state. |
| `render` | `ReactElement \| ((props: HTMLProps, state: DialogState) => ReactElement \| null)` | — | Render prop for custom element. |
| `style` | `CSSProperties \| ((state: DialogState) => CSSProperties \| undefined)` | — | Style or function returning style from state. |

### Description

Renders the localized playback error message, or authored children when provided.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string \| ((state: DialogState) => string \| undefined)` | — | Class name or function returning class name from state. |
| `render` | `ReactElement \| ((props: HTMLProps, state: DialogState) => ReactElement \| null)` | — | Render prop for custom element. |
| `style` | `CSSProperties \| ((state: DialogState) => CSSProperties \| undefined)` | — | Style or function returning style from state. |

### Title

Renders the localized error dialog heading, or authored children when provided.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string \| ((state: DialogState) => string \| undefined)` | — | Class name or function returning class name from state. |
| `render` | `ReactElement \| ((props: HTMLProps, state: DialogState) => ReactElement \| null)` | — | Render prop for custom element. |
| `style` | `CSSProperties \| ((state: DialogState) => CSSProperties \| undefined)` | — | Style or function returning style from state. |

### Backdrop

Presentational layer behind a dialog while it is rendered, including its exit transition.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string \| ((state: DialogState) => string \| undefined)` | — | Class name or function returning class name from state. |
| `render` | `ReactElement \| ((props: HTMLProps, state: DialogState) => ReactElement \| null)` | — | Render prop for custom element. |
| `style` | `CSSProperties \| ((state: DialogState) => CSSProperties \| undefined)` | — | Style or function returning style from 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. |

### Popup

Renders the modal dialog while it is open.

#### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string \| ((state: DialogState) => string \| undefined)` | — | Class name or function returning class name from state. |
| `render` | `ReactElement \| ((props: HTMLProps, state: DialogState) => ReactElement \| null)` | — | Render prop for custom element. |
| `style` | `CSSProperties \| ((state: DialogState) => CSSProperties \| undefined)` | — | Style or function returning style from 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. |

---

React documentation: https://videojs.org/docs/framework/react/llms.txt
All documentation: https://videojs.org/llms.txt
