Popover

A popup anchored to a trigger element.

The trigger and popover are linked in two ways: a ref on the trigger is passed to Popover.Content as anchor for positioning, and a shared id ties them together for accessibility via aria-controls.

Show code
Hide code
import { Button, Popover } from '@mylighthouse/prism-react';
import { useId, useRef, useState } from 'react';

export default function BasicExample(): React.JSX.Element {
  const [open, setOpen] = useState(false);
  const triggerRef = useRef<HTMLButtonElement>(null);
  const popupId = useId();

  return (
    <>
      <Button
        aria-controls={popupId}
        aria-expanded={open}
        aria-haspopup="dialog"
        buttonType="secondary"
        onClick={() => setOpen(!open)}
        ref={triggerRef}
      >
        Open popover
      </Button>
      <Popover onOpenChange={setOpen} open={open}>
        <Popover.Content
          anchor={triggerRef}
          aria-label="More information"
          id={popupId}
          side="bottom"
        >
          <div className="flex flex-col gap-300 p-400">
            <p className="text-300--regular">
              This is a popover with arbitrary content. Use it for contextual
              actions or supplementary information.
            </p>
            <div className="flex justify-end">
              <Popover.Close>
                <Button buttonType="secondary" size="small">
                  Dismiss
                </Button>
              </Popover.Close>
            </div>
          </div>
        </Popover.Content>
      </Popover>
    </>
  );
}

Accessibility

The trigger element needs some ARIA attributes to be fully accessible:

  • aria-expanded={open}: communicates the open/closed state
  • aria-haspopup="dialog": indicates the button controls a popup dialog
  • aria-controls: points to the same id you pass to Popover.Content

Also pass aria-label or aria-labelledby to Popover.Content to give the dialog an accessible name.

API Reference

Popover

Name Default Type Description
onOpenChange -- (open: boolean, eventDetails: PopoverRootChangeEventDetails) => void --
open -- boolean --

Popover.Content

Name Default Type Description
anchor * -- Element | VirtualElement | RefObject<Element> | (() => Element | VirtualElement) --
id * -- string --
aria-label -- string --
aria-labelledby -- string --
role -- "dialog" | "menu" | "listbox" | "tooltip" "dialog"` (default) is used for popovers with generic interactive content such as a rich hover-card, a floating form, a date-picker, or a settings flyout. Use `"menu"` for a list of actions or commands (also set `aria-haspopup="menu"` on the trigger). Use `"listbox"` for a dropdown selection list. Use `"tooltip"` for plain, non-interactive text.
side -- Side --
sideOffset -- number --

Popover.Close

No component-specific props