diff --git a/packages/core/src/dom/ui/popover/popover.ts b/packages/core/src/dom/ui/popover/popover.ts index 7f78bfb1..d625cc14 100644 --- a/packages/core/src/dom/ui/popover/popover.ts +++ b/packages/core/src/dom/ui/popover/popover.ts @@ -1,5 +1,5 @@ import type { State } from '@videojs/store'; -import { listen } from '@videojs/utils/dom'; +import { listen, tryHidePopover, tryShowPopover } from '@videojs/utils/dom'; import type { PopoverInput } from '../../../core/ui/popover/popover-core'; import { createDismissLayer } from '../dismiss-layer'; import type { UIFocusEvent, UIPointerEvent } from '../event'; @@ -105,8 +105,6 @@ export function createPopover(options: PopoverOptions): PopoverApi { const opening = layer.open(); if (!opening) return; - tryShowPopover(popupEl); - const details: PopoverChangeDetails = event ? { reason, event } : { reason }; onOpenChange(true, details); @@ -287,21 +285,3 @@ export function createPopover(options: PopoverOptions): PopoverApi { destroy: layer.destroy, }; } - -// --- Popover API helpers --- - -function tryShowPopover(el: HTMLElement | null): void { - try { - el?.showPopover?.(); - } catch { - // Element may not support popover API - } -} - -function tryHidePopover(el: HTMLElement | null): void { - try { - el?.hidePopover?.(); - } catch { - // Element may not support popover API or may already be hidden - } -} diff --git a/packages/html/src/ui/popover/popover-element.ts b/packages/html/src/ui/popover/popover-element.ts index 98314c03..1ffb7191 100644 --- a/packages/html/src/ui/popover/popover-element.ts +++ b/packages/html/src/ui/popover/popover-element.ts @@ -12,7 +12,7 @@ import { } from '@videojs/core/dom'; import type { PropertyDeclarationMap, PropertyValues } from '@videojs/element'; import { SnapshotController } from '@videojs/store/html'; -import { applyStyles, supportsAnchorPositioning } from '@videojs/utils/dom'; +import { applyStyles, supportsAnchorPositioning, tryHidePopover, tryShowPopover } from '@videojs/utils/dom'; import { MediaElement } from '../media-element'; @@ -143,6 +143,14 @@ export class PopoverElement extends MediaElement { applyElementProps(this, this.#core.getPopupAttrs(state)); applyStateDataAttrs(this, state, PopoverDataAttrs); + // Show/hide via Popover API AFTER data attributes are applied so + // `data-starting-style` is present before the first visible frame. + if (state.open) { + tryShowPopover(this); + } else { + tryHidePopover(this); + } + // Apply trigger ARIA and anchor-name to the discovered trigger. if (this.#currentTrigger) { applyElementProps(this.#currentTrigger, this.#core.getTriggerAttrs(state, this.id)); diff --git a/packages/utils/src/dom/index.ts b/packages/utils/src/dom/index.ts index 4841958f..51c9836d 100644 --- a/packages/utils/src/dom/index.ts +++ b/packages/utils/src/dom/index.ts @@ -4,16 +4,12 @@ export { isRTL } from './direction'; export { type OnEventOptions, onEvent } from './event'; export { idleCallback } from './idle-callback'; export { listen } from './listen'; +export { tryHidePopover, tryShowPopover } from './popover'; export { isHTMLAudioElement, isHTMLMediaElement, isHTMLVideoElement } from './predicates'; export { type RafThrottled, rafThrottle } from './raf-throttle'; export { getSlottedElement, querySlot } from './slotted'; export { applyStyles } from './style'; -export { - supportsAnchorPositioning, - supportsAnimationFrame, - supportsIdleCallback, - supportsPopoverAPI, -} from './supports'; +export { supportsAnchorPositioning, supportsAnimationFrame, supportsIdleCallback } from './supports'; export { findTrackElement, getTextTrackList } from './text-track'; export { serializeTimeRanges } from './time-ranges'; export type { CustomElement, CustomElementCallbacks } from './types'; diff --git a/packages/utils/src/dom/popover.ts b/packages/utils/src/dom/popover.ts new file mode 100644 index 00000000..f321c187 --- /dev/null +++ b/packages/utils/src/dom/popover.ts @@ -0,0 +1,15 @@ +export function tryShowPopover(el: HTMLElement | null): void { + try { + el?.showPopover?.(); + } catch { + // Element may not support popover API or may already be shown + } +} + +export function tryHidePopover(el: HTMLElement | null): void { + try { + el?.hidePopover?.(); + } catch { + // Element may not support popover API or may already be hidden + } +} diff --git a/packages/utils/src/dom/supports.ts b/packages/utils/src/dom/supports.ts index 46d63d6e..a57a788e 100644 --- a/packages/utils/src/dom/supports.ts +++ b/packages/utils/src/dom/supports.ts @@ -6,10 +6,10 @@ export function supportsAnimationFrame(): boolean { return typeof requestAnimationFrame === 'function'; } -export function supportsPopoverAPI(): boolean { - return typeof HTMLElement !== 'undefined' && 'popover' in HTMLElement.prototype; -} - export function supportsAnchorPositioning(): boolean { return typeof CSS !== 'undefined' && CSS.supports('anchor-name: --a'); } + +export function supportsPopoverAPI(): boolean { + return typeof HTMLElement !== 'undefined' && 'popover' in HTMLElement.prototype; +}