Popover

Popover renders its content in a floating modal. If no explicit anchor is passed via props, it anchors to its parent element by default.

import { Popover } from '@wordpress/components';

View on Storybook

View source on GitHub

PropsPermalink to this section

NameDefaultDescription
animatetrue

boolean

Whether the popover should animate when opening.

children Required

ReactNode

The children elements rendered as the popover’s content.

variantundefined

"toolbar" | "unstyled"

Specifies the popover’s style.

Leave undefined for the default style. Other values are:

  • ‘unstyled’: The popover is essentially without any visible style, it has no background, border, outline or drop shadow, but the popover contents are still displayed.
  • ‘toolbar’: A style that has no elevation, but a high contrast with other elements. This is matches the style of the Toolbar component.
anchor

Element | VirtualElement | null | undefined

The element that should be used by the popover as its anchor. It can either be an Element or, alternatively, a VirtualElement — ie. an object with the getBoundingClientRect() and the ownerDocument properties defined.

The anchor element should be stored in local state rather than a plain React ref to ensure reactive updating when it changes.

inlinefalse

boolean

Whether to render the popover inline or within the slot.

position

"top" | "middle" | "bottom" | "top center" | "top left" | "top right" | "middle center" | "middle left" | "middle right" | "bottom center" | "bottom left" | "bottom right" | "top center left" | "top center right" | "top center top" | "top center bottom" | "top left left" | "top left right" | "top left top" | "top left bottom" | "top right left" | "top right right" | "top right top" | "top right bottom" | "middle center left" | "middle center right" | "middle center top" | "middle center bottom" | "middle left left" | "middle left right" | "middle left top" | "middle left bottom" | "middle right left" | "middle right right" | "middle right top" | "middle right bottom" | "bottom center left" | "bottom center right" | "bottom center top" | "bottom center bottom" | "bottom left left" | "bottom left right" | "bottom left top" | "bottom left bottom" | "bottom right left" | "bottom right right" | "bottom right top" | "bottom right bottom"

Legacy way to specify the popover’s position with respect to its anchor. Note: this prop is deprecated. Use the placement prop instead.

offset0

number | { mainAxis?: number | undefined; crossAxis?: number | undefined; } | undefined

The distance (in px) between the anchor and the popover. Pass an object to also displace the popover along its cross axis.

onClose

() => void

A callback invoked when the popover should be closed.

resizetrue

boolean

Adjusts the size of the popover to prevent its contents from going out of view when meeting the viewport edges. Note: The resize and shift props are not intended to be used together. Enabling both can cause unexpected behavior.

shiftfalse

boolean

Enables the Popover to shift in order to stay in view when meeting the viewport edges. Note: The resize and shift props are not intended to be used together. Enabling both can cause unexpected behavior.

fliptrue

boolean

Specifies whether the popover should flip across its axis if there isn’t space for it in the normal placement. When the using a ‘top’ placement, the popover will switch to a ‘bottom’ placement. When using a ‘left’ placement, the popover will switch to a `right’ placement. The popover will retain its alignment of ‘start’ or ‘end’ when flipping.

expandOnMobile

boolean

Show the popover fullscreen on mobile viewports.

focusOnMount'firstElement'

Mode | undefined

Determines focus behavior when the popover mounts.

  • "firstElement" focuses the first tabbable element within.
  • "firstInputElement" focuses the first value control within.
  • true focuses the element itself.
  • false does nothing and should not be used unless an accessible substitute behavior is implemented.
headerTitle

string

Used to customize the header text shown when the popover is toggled to fullscreen on mobile viewports (see the expandOnMobile prop).

__unstableSlotName'Popover'

string

The name of the Slot in which the popover should be rendered. It should be also passed to the corresponding PopoverSlot component.

constrainTabbing`focusOnMount` !== false

boolean

Determines whether tabbing is constrained to within the popover, preventing keyboard focus from leaving the popover content without explicit focus elsewhere, or whether the popover remains part of the wider tab order. If no value is passed, it will be derived from focusOnMount.

onFocusOutside

(event: SyntheticEvent<Element, Event>) => void

A callback invoked when the focus leaves the opened popover. This should only be provided in advanced use-cases when a popover should close under specific circumstances (for example, if the new document.activeElement is content of or otherwise controlling popover visibility).

When not provided, the onClose callback will be called instead.

noArrowtrue

boolean

Used to show/hide the arrow that points at the popover’s anchor.

placement'bottom-start'

"left" | "right" | "top" | "bottom" | "overlay" | "left-end" | "left-start" | "right-end" | "right-start" | "top-end" | "top-start" | "bottom-end" | "bottom-start"

Used to specify the popover’s position with respect to its anchor.

__unstableForcePosition

boolean

Prevent the popover from flipping and resizing when meeting the viewport edges. Note: this prop is deprecated. Instead, provide use the individual flip and resize props.

anchorRect

DomRectWithOwnerDocument

An object extending a DOMRect with an additional optional ownerDocument property, used to specify a fixed popover position.

anchorRef

Element | PopoverAnchorRefReference | PopoverAnchorRefTopBottom | Range | undefined

Used to specify a fixed popover position. It can be an Element, a React reference to an element, an object with a top and a bottom properties (both pointing to elements), or a range.

getAnchorRect

(fallbackReferenceElement: Element | null) => DomRectWithOwnerDocument

A function returning the same value as the one expected by the anchorRect prop, used to specify a dynamic popover position.

isAlternate

boolean

Used to enable a different visual style for the popover. Note: this prop is deprecated. Use the variant prop with the ‘toolbar’ value instead.

as

"symbol" | "object" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 164 more ... | undefined

The HTML element or React component to render the component as.

ExamplesPermalink to this section

DefaultPermalink to this section

const Default = () => <Popover>(<div style={ { width: '280px', whiteSpace: 'normal' } }>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
                        eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
                        enim ad minim veniam, quis nostrud exercitation ullamco laboris
                        nisi ut aliquip ex ea commodo consequat.
                    </div>)</Popover>;

UnstyledPermalink to this section

const Unstyled = () => <Popover variant="unstyled" />;

All PlacementsPermalink to this section

const AllPlacements = ( { children, ...args } ) => (
    <div
        style={ {
            minWidth: '600px',
            marginLeft: 'auto',
            marginRight: 'auto',
        } }
    >
        <h2>
            Resize / scroll the viewport to test the behavior of the
            popovers when they reach the viewport boundaries.
        </h2>
        <div>
            { AVAILABLE_PLACEMENTS.map( ( p ) => (
                <PopoverWithAnchor
                    key={ p }
                    placement={ p }
                    { ...args }
                    resize={ p === 'overlay' ? true : args.resize }
                >
                    { children }
                    <div>
                        <small>(placement: { p })</small>
                    </div>
                </PopoverWithAnchor>
            ) ) }
        </div>
    </div>
);

Dynamic HeightPermalink to this section

const DynamicHeight = () => <Popover animate={false}>(<div
        style={ {
            height: 'var(--dynamic-height)',
            background: '#eee',
            padding: '20px',
        } }
    >Content with dynamic height
                    </div>)</Popover>;

With Slot Outside IframePermalink to this section

const WithSlotOutsideIframe = () => <PopoverInsideIframeRenderedInExternalSlot />;

With Close HandlersPermalink to this section

const WithCloseHandlers = function WithCloseHandlersStory( args ) {
    const [ isVisible, setIsVisible ] = useState( false );
    const buttonRef = useRef< HTMLButtonElement >( null );

    const toggleVisible = ( event: React.MouseEvent ) => {
        if ( buttonRef.current && event.target !== buttonRef.current ) {
            return;
        }
        setIsVisible( ( prev ) => ! prev );
    };

    const handleClose = () => {
        args.onClose?.();
        setIsVisible( false );
    };

    const handleFocusOutside = ( e: React.SyntheticEvent ) => {
        args.onFocusOutside?.( e );
        setIsVisible( false );
    };

    useEffect( () => {
        buttonRef.current?.scrollIntoView( {
            block: 'center',
            inline: 'center',
        } );
    }, [] );

    return (
        <div
            style={ {
                width: '300vw',
                height: '300vh',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
            } }
        >
            <Button
                __next40pxDefaultSize
                variant="secondary"
                onClick={ toggleVisible }
                ref={ buttonRef }
            >
                Toggle Popover
                { isVisible && (
                    <Popover
                        { ...args }
                        onClose={ handleClose }
                        onFocusOutside={ handleFocusOutside }
                    >
                        { args.children }
                    </Popover>
                ) }
            </Button>
        </div>
    );
};