Skip to content

ReferenceDialogs

Dialog

A modal dialog for application content, including players opened from a thumbnail

Import

import { Dialog } from '@videojs/react';

Anatomy

<Dialog.Root>
  <Dialog.Trigger />
  <Dialog.Backdrop />
  <Dialog.Popup>
    <Dialog.Title />
    <Dialog.Description />
    <Dialog.Close />
  </Dialog.Popup>
</Dialog.Root>

Behavior

Dialog provides the modal interaction and accessibility behavior while your application supplies the content and styling. It is the general-purpose replacement for a ModalDialog use case such as opening a player from a thumbnail.

Use Dialog.Trigger to open the dialog. Use open with onOpenChange for controlled state, or defaultOpen for uncontrolled state. Root provides state without rendering an element, while Popup renders only while the dialog is open or closing.

The close part and Escape close the dialog. Other buttons inside the dialog, including player controls, do not close it.

Inside and outside a player

A dialog inside a player is confined to that player. The rest of the player becomes inert, but the page around it stays interactive and aria-modal is omitted. A dialog outside a player is modal for the whole page, with aria-modal="true" and everything outside the popup inert.

The backdrop and popup get data-scope: player inside a player and document outside one. The built-in skin styles use it to switch from position: absolute to position: fixed. In your own styles, give a dialog outside a player position: fixed so it covers the viewport, as with any headless dialog. Inside a skin, give the backdrop and popup a z-index above the controls; the built-in skins use 40 and 50.

Your application decides what opening and closing mean for the media. The example starts playback after opening and pauses it as soon as the dialog closes. Handle the promise returned by play(), since browsers can reject autoplay when it is not allowed.

Use AlertDialog for urgent messages that require acknowledgement. ErrorDialog is the player-error specialization. Both use the same dialog behavior.

Styling

Use the open and transition data attributes to style the modal and its 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
data-scope player inside a player, document outside one

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

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

Accessibility

The popup uses role="dialog", plus aria-modal="true" outside a player. Include Dialog.Title so the dialog always has an accessible name. Dialog.Description is optional. These parts receive generated IDs connected through aria-labelledby and aria-describedby. The trigger receives aria-haspopup, aria-controls, and aria-expanded.

When the dialog opens, focus moves to an element with autofocus, the first focusable element, or the popup itself. Tab and Shift + Tab keep focus within the dialog, and content outside the dialog, within its player or the page, becomes inert. Closing restores focus to the trigger, or to the element that was focused before the dialog opened.

Dialogs inside the same player container share modal coordination. Opening one closes the current dialog and dismisses any open menu, tooltip, or popover before focus moves into the new popup.

Examples

Player modal

Open the video from its thumbnail. Playback starts when the dialog opens and pauses when it closes.

import { Container, createPlayer, Dialog } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';
import { useEffect, useRef, useState } from 'react';

import './BasicUsage.css';

const { Player } = createPlayer({ features: videoFeatures });

export default function BasicUsage() {
  const [open, setOpen] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);

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

    if (open) void video.play().catch(() => {});
    else video.pause();
  }, [open]);

  return (
    <div className="react-dialog-basic">
      <Dialog.Root open={open} onOpenChange={setOpen}>
        <Dialog.Trigger className="react-dialog-basic__trigger">
          <img src="https://image.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/thumbnail.jpg" alt="" />
          <span>Play the video</span>
        </Dialog.Trigger>
        <Dialog.Backdrop className="react-dialog-basic__backdrop" />
        <Dialog.Popup className="react-dialog-basic__dialog">
          <div className="react-dialog-basic__popup">
            <Dialog.Title className="react-dialog-basic__title">Video title</Dialog.Title>
            <Dialog.Description className="react-dialog-basic__description">
              A video opened from a thumbnail.
            </Dialog.Description>
            <Dialog.Close className="react-dialog-basic__close">Close</Dialog.Close>
            <Player>
              <Container>
                <Video ref={videoRef} src="https://stream.mux.com/BV3YZtogl89mg9VcNBhhnHm02Y34zI1nlMuMQfAbl3dM/highest.mp4" controls muted playsInline />
              </Container>
            </Player>
          </div>
        </Dialog.Popup>
      </Dialog.Root>
    </div>
  );
}

API Reference

Root

Manages dialog state and provides it to the compound parts.

Props

PropTypeDefaultDetails
closeOnEscapebooleantrue
defaultOpenbooleanfalse
openbooleanfalse

State

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

PropertyTypeDetails
transitionStartingboolean
transitionEndingboolean
openboolean
status'idle' | 'starting' | 'ending'
titleIdstring | undefined
descriptionIdstring | undefined
scope'player' | 'document'

Data attributes

AttributeTypeDetails
data-open—
data-starting-style—
data-ending-style—
data-scope'player' | 'document'

Backdrop

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

Props

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—

Data attributes

AttributeTypeDetails
data-open—
data-starting-style—
data-ending-style—
data-scope'player' | 'document'

Close

Renders a button that closes the dialog.

Props

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—

Data attributes

AttributeTypeDetails
data-open—
data-starting-style—
data-ending-style—
data-scope'player' | 'document'

Description

Renders the description announced with the dialog.

Props

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—

Renders the modal dialog while it is open.

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—
AttributeTypeDetails
data-open—
data-starting-style—
data-ending-style—
data-scope'player' | 'document'

Title

Renders the heading that labels the dialog.

Props

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—

Trigger

Renders a button that opens the dialog.

Props

PropTypeDefaultDetails
classNamestring | function—
renderReactElement | function—
styleCSSProperties | function—

Data attributes

AttributeTypeDetails
data-open—
data-starting-style—
data-ending-style—
data-scope'player' | 'document'