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><media-popover>
<button>Open</button>
<div>Content</div>
</media-popover>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.
In HTML, the media-popover element wraps a trigger (first child button) and
popup content (second child). The element manages open/close state and
positioning automatically.
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>
);
}
.react-popover-basic {
position: relative;
}
.react-popover-basic video {
width: 100%;
}
.react-popover-basic__bar {
position: absolute;
bottom: 10px;
left: 10px;
}
.react-popover-basic__trigger {
padding: 6px 16px;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
color: black;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 9999px;
cursor: pointer;
}
.react-popover-basic__popup {
/* Reset UA [popover] defaults */
margin: 0;
border: 0;
--media-popover-side-offset: 8px;
background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(10px);
color: white;
border-radius: 8px;
padding: 12px 16px;
font-size: 14px;
}
.react-popover-basic__arrow {
fill: rgba(0, 0, 0, 0.85);
}
.react-popover-basic__content {
white-space: nowrap;
}
<video-player class="html-popover-basic">
<media-container>
<video
src="https://stream.mux.com/lhnU49l1VGi3zrTAZhDm9LUUxSjpaPW9BL4jY25Kwo4/highest.mp4"
autoplay
muted
playsinline
loop
></video>
<div class="html-popover-basic__bar">
<button type="button" commandfor="popover-demo" class="html-popover-basic__trigger">Settings</button>
<media-popover id="popover-demo" class="html-popover-basic__popover">
<div class="html-popover-basic__popup">
Popover content
</div>
</media-popover>
</div>
</media-container>
</video-player>
.html-popover-basic,
.html-popover-basic media-container {
display: block;
position: relative;
}
.html-popover-basic video {
width: 100%;
}
.html-popover-basic__bar {
position: absolute;
bottom: 10px;
left: 10px;
}
.html-popover-basic__trigger {
padding: 6px 16px;
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
color: black;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 9999px;
cursor: pointer;
}
.html-popover-basic__popover {
background: rgba(0, 0, 0, 0.85);
backdrop-filter: blur(10px);
color: white;
border-radius: 8px;
padding: 12px 16px;
font-size: 14px;
white-space: nowrap;
}
import '@videojs/html/video/player';
import '@videojs/html/ui/popover';
API Reference
Root media-popover
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
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 Arrow
Decorative arrow pointing from the popup toward the trigger. Hidden from assistive technology.
Popup Popup
Container for the popover content. Positioned relative to the trigger using CSS anchor positioning with a JavaScript fallback.
Data attributes
| Attribute | Type | |
|---|---|---|
data-open | ||
| ||
data-side | 'top' | 'bottom' | 'left' | 'right' | |
| ||
data-align | 'start' | 'center' | 'end' | |
| ||
data-starting-style | ||
| ||
data-ending-style | ||
| ||
Trigger 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 | ||
| ||