fix(react): set anchor-name and position-anchor imperatively in popover (#715)

This commit is contained in:
rahim
2026-03-04 13:18:36 -08:00
committed by GitHub
parent 853585b2d0
commit 070d094444
2 changed files with 14 additions and 10 deletions
@@ -26,8 +26,11 @@ export const PopoverPopup = forwardRef<HTMLDivElement, PopoverPopupProps>(functi
const popupRef = useCallback(
(el: HTMLDivElement | null) => {
popover.setPopupElement(el);
if (el && supportsAnchorPositioning()) {
el.style.setProperty('position-anchor', `--${anchorName}`);
}
},
[popover]
[popover, anchorName]
);
const composedRef = useComposedRefs(forwardedRef, popupRef, internalRef);
@@ -37,11 +40,12 @@ export const PopoverPopup = forwardRef<HTMLDivElement, PopoverPopupProps>(functi
const posOpts = useMemo(() => ({ side: state.side, align: state.align }), [state.side, state.align]);
// CSS Anchor Positioning — computed from state, no measurement needed.
// getAnchorPositionStyle returns camelCase keys, directly compatible
// with React's style prop.
// `position-anchor` is set imperatively in the ref callback above
// because React's style prop silently drops unrecognised CSS properties.
const anchorStyle = useMemo(() => {
if (!supportsAnchorPositioning()) return null;
return getAnchorPositionStyle(anchorName, posOpts) as CSSProperties;
const { positionAnchor: _, ...rest } = getAnchorPositionStyle(anchorName, posOpts);
return rest as CSSProperties;
}, [anchorName, posOpts]);
// Manual fallback — measure rects after layout, before paint.
@@ -1,8 +1,8 @@
'use client';
import type { PopoverState } from '@videojs/core';
import { getAnchorNameStyle } from '@videojs/core/dom';
import { forwardRef, useCallback, useMemo } from 'react';
import { supportsAnchorPositioning } from '@videojs/utils/dom';
import { forwardRef, useCallback } from 'react';
import type { UIComponentProps } from '../../utils/types';
import { renderElement } from '../../utils/use-render';
@@ -20,12 +20,13 @@ export const PopoverTrigger = forwardRef<HTMLButtonElement, PopoverTriggerProps>
const triggerRef = useCallback(
(el: HTMLButtonElement | null) => {
popover.setTriggerElement(el);
if (el && supportsAnchorPositioning()) {
el.style.setProperty('anchor-name', `--${anchorName}`);
}
},
[popover]
[popover, anchorName]
);
const anchorStyle = useMemo(() => getAnchorNameStyle(anchorName), [anchorName]);
// Remap DOM focus events to React synthetic event names.
// createPopover() uses onFocusIn/onFocusOut (matching DOM focusin/focusout),
// but React maps those to onFocus/onBlur.
@@ -41,7 +42,6 @@ export const PopoverTrigger = forwardRef<HTMLButtonElement, PopoverTriggerProps>
props: [
{
type: 'button' as const,
style: anchorStyle,
...core.getTriggerAttrs(state, popupId),
},
{ ...restTriggerProps, onFocus: onFocusIn, onBlur: onFocusOut },