ErrorDialog
An alert dialog that presents and dismisses playback errors
Import
import { ErrorDialog } from '@videojs/react';import '@videojs/html/ui/error-dialog';Anatomy
<ErrorDialog.Root>
<ErrorDialog.Backdrop />
<ErrorDialog.Popup>
<ErrorDialog.Title />
<ErrorDialog.Description />
<ErrorDialog.Close />
</ErrorDialog.Popup>
</ErrorDialog.Root><media-error-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-error-dialog>Behavior
ErrorDialog is a specialized root driven by the player’s error feature. It uses alert semantics and reuses the backdrop, popup, title, description, and close parts from 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.
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;
}React renders the backdrop and popup as separate DOM elements. Add a className to each part and style their transitions independently:
.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" and aria-modal="true". Its title and description are connected with aria-labelledby and aria-describedby. Focus stays within the popup and content outside it is inert while the error is open. 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
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>
);
}
.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;
}
<video-player class="html-error-dialog-basic">
<media-container class="html-error-dialog-basic__container">
<video
class="html-error-dialog-basic__video"
src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4"
autoplay
muted
playsinline
loop
></video>
<button class="html-error-dialog-basic__trigger" type="button">Trigger a playback error</button>
<media-error-dialog>
<media-dialog-backdrop class="html-error-dialog-basic__backdrop"></media-dialog-backdrop>
<media-dialog-popup class="html-error-dialog-basic__dialog">
<media-dialog-title class="html-error-dialog-basic__title"></media-dialog-title>
<media-dialog-description class="html-error-dialog-basic__description"></media-dialog-description>
<media-dialog-close class="html-error-dialog-basic__close"></media-dialog-close>
</media-dialog-popup>
</media-error-dialog>
</media-container>
</video-player>
.html-error-dialog-basic__container {
position: relative;
display: block;
overflow: hidden;
border-radius: 12px;
}
.html-error-dialog-basic__video {
display: block;
width: 100%;
}
.html-error-dialog-basic__trigger,
.html-error-dialog-basic__close {
padding: 8px 16px;
color: #111827;
cursor: pointer;
background: #fff;
border: 0;
border-radius: 9999px;
}
.html-error-dialog-basic__trigger {
position: absolute;
bottom: 16px;
left: 16px;
}
.html-error-dialog-basic__backdrop {
position: absolute;
inset: 0;
background: rgb(3 7 18 / 92%);
transition: opacity 150ms ease;
}
.html-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;
}
.html-error-dialog-basic__backdrop:not([data-open]),
.html-error-dialog-basic__dialog:not([data-open]) {
display: none;
}
.html-error-dialog-basic__backdrop[data-starting-style],
.html-error-dialog-basic__backdrop[data-ending-style],
.html-error-dialog-basic__dialog[data-starting-style],
.html-error-dialog-basic__dialog[data-ending-style] {
opacity: 0;
}
.html-error-dialog-basic__title,
.html-error-dialog-basic__description {
display: block;
}
.html-error-dialog-basic__title {
font-size: 20px;
font-weight: 600;
}
.html-error-dialog-basic__description {
color: #d1d5db;
}
.html-error-dialog-basic__close {
justify-self: center;
}
import '@videojs/html/video/player';
import '@videojs/html/ui/error-dialog';
const brokenSource = 'data:video/mp4;base64,AAAA';
document.querySelectorAll<HTMLElement>('.html-error-dialog-basic').forEach((demo) => {
const video = demo.querySelector('video');
const trigger = demo.querySelector<HTMLButtonElement>('.html-error-dialog-basic__trigger');
trigger?.addEventListener('click', () => {
if (!video) return;
video.src = brokenSource;
video.load();
});
});
API Reference
Rootmedia-error-dialog
Opens from player error state and provides it to the shared dialog parts.
State
render, className, and style props.| Property | Type | Details |
|---|---|---|
transitionStarting | boolean | |
| ||
transitionEnding | boolean | |
| ||
open | boolean | |
| ||
status | 'idle' | 'starting' | 'ending' | |
| ||
titleId | string | undefined | |
| ||
descriptionId | string | undefined | |
| ||
CloseClose
Renders a localized button that closes the dialog and dismisses the player error.
Props
| Prop | Type | Default | Details |
|---|---|---|---|
className | string | ((state: DialogCore.State) => string | undefined) | — | |
| |||
render | ReactElement | ((props: HTMLProps, state: DialogCore.State) => ReactElement | null) | — | |
| |||
style | CSSProperties | ((state: DialogCore.State) => CSSProperties | undefined) | — | |
| |||
DescriptionDescription
Renders the localized playback error message, or authored children when provided.
Props
| Prop | Type | Default | Details |
|---|---|---|---|
className | string | ((state: DialogCore.State) => string | undefined) | — | |
| |||
render | ReactElement | ((props: HTMLProps, state: DialogCore.State) => ReactElement | null) | — | |
| |||
style | CSSProperties | ((state: DialogCore.State) => CSSProperties | undefined) | — | |
| |||
TitleTitle
Renders the localized error dialog heading, or authored children when provided.
Props
| Prop | Type | Default | Details |
|---|---|---|---|
className | string | ((state: DialogCore.State) => string | undefined) | — | |
| |||
render | ReactElement | ((props: HTMLProps, state: DialogCore.State) => ReactElement | null) | — | |
| |||
style | CSSProperties | ((state: DialogCore.State) => CSSProperties | undefined) | — | |
| |||
Backdropmedia-dialog-backdrop
Presentational layer behind a dialog while it is rendered, including its exit transition.
Props
| Prop | Type | Default | Details |
|---|---|---|---|
className | string | ((state: DialogCore.State) => string | undefined) | — | |
| |||
render | ReactElement | ((props: HTMLProps, state: DialogCore.State) => ReactElement | null) | — | |
| |||
style | CSSProperties | ((state: DialogCore.State) => CSSProperties | undefined) | — | |
| |||
Data attributes
| Attribute | Type | Details |
|---|---|---|
data-open | ||
| ||
data-starting-style | ||
| ||
data-ending-style | ||
| ||
Popupmedia-dialog-popup
Renders the modal dialog while it is open.
Props
| Prop | Type | Default | Details |
|---|---|---|---|
className | string | ((state: DialogCore.State) => string | undefined) | — | |
| |||
render | ReactElement | ((props: HTMLProps, state: DialogCore.State) => ReactElement | null) | — | |
| |||
style | CSSProperties | ((state: DialogCore.State) => CSSProperties | undefined) | — | |
| |||
Data attributes
| Attribute | Type | Details |
|---|---|---|
data-open | ||
| ||
data-starting-style | ||
| ||
data-ending-style | ||
| ||