FrameworkStyle

Popover

A popover component for displaying contextual content anchored to a trigger

Anatomy

<Popover.Root>
  <Popover.Trigger>Open</Popover.Trigger>
  <Popover.Popup>
    <Popover.Arrow />
    Content
  </Popover.Popup>
</Popover.Root>

Behavior

Displays contextual content anchored to a trigger element. By default, opens on click and closes when clicking outside, pressing Escape, or when the trigger loses focus.

Set openOnHover to open on pointer hover instead of click. Use delay and closeDelay to control timing for hover interactions.

The side and align props control popup placement relative to the trigger. The popup repositions automatically to stay within viewport bounds.

In React, the component is composed from four parts: Root manages state, Trigger toggles the popover, Popup contains the content, and Arrow renders a directional arrow.

Styling

Use CSS custom properties for positioning offsets:

media-popover {
  --media-popover-side-offset: 8px;
  --media-popover-align-offset: 0px;
}

Style based on open state and transition phases:

media-popover[data-open] .popup {
  display: block;
}
media-popover[data-starting-style] .popup {
  opacity: 0;
}
media-popover[data-ending-style] .popup {
  opacity: 0;
}

Accessibility

The trigger receives aria-expanded reflecting the open state. When modal is set, the popup receives aria-modal="true". Closing via Escape is enabled by default and can be disabled with closeOnEscape={false}.

Examples

Basic Usage

import { createPlayer, Popover } from '@videojs/react';
import { Video, videoFeatures } from '@videojs/react/video';

import './BasicUsage.css';

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

export default function BasicUsage() {
  return (
    <Player.Provider>
      <Player.Container className="react-popover-basic">
        <Video
          src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
          autoPlay
          muted
          playsInline
          loop
        />
        <div className="react-popover-basic__bar">
          <Popover.Root>
            <Popover.Trigger className="react-popover-basic__trigger">Settings</Popover.Trigger>
            <Popover.Popup className="react-popover-basic__popup">
              <Popover.Arrow className="react-popover-basic__arrow" />
              <div className="react-popover-basic__content">Popover content</div>
            </Popover.Popup>
          </Popover.Root>
        </div>
      </Player.Container>
    </Player.Provider>
  );
}

API Reference

Root

Props

Prop Type Default
align 'start' | 'center' | 'end' 'center'
closeDelay number 0
closeOnEscape boolean true
closeOnOutsideClick boolean true
defaultOpen boolean false
delay number 300
modal boolean | 'trap-focus' false
open boolean false
openOnHover boolean false
side 'top' | 'bottom' | 'left' | 'right' 'top'

State

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

Property Type
open boolean
status 'idle' | 'starting' | 'ending'
side 'top' | 'bottom' | 'left' | 'right'
align 'start' | 'center' | 'end'
modal boolean | 'trap-focus'
transitionStarting boolean
transitionEnding boolean

Data attributes

Attribute Type
data-open
data-side 'top' | 'bottom' | 'left' | 'right'
data-align 'start' | 'center' | 'end'
data-starting-style
data-ending-style

CSS custom properties

Variable
--media-popover-side-offset
--media-popover-align-offset
--media-popover-anchor-width
--media-popover-anchor-height
--media-popover-available-width
--media-popover-available-height

Arrow

Decorative arrow pointing from the popup toward the trigger. Hidden from assistive technology.

Container for the popover content. Positioned relative to the trigger using CSS anchor positioning with a JavaScript fallback.

Attribute Type
data-open
data-side 'top' | 'bottom' | 'left' | 'right'
data-align 'start' | 'center' | 'end'
data-starting-style
data-ending-style

Trigger

Button that toggles the popover visibility. Renders a <button> element.

Data attributes

Attribute Type
data-open
data-side 'top' | 'bottom' | 'left' | 'right'
data-align 'start' | 'center' | 'end'
data-starting-style
data-ending-style
VideoJS