Overlays

Popover

The interactive half of Tooltip, and the reason the two are separate components rather than one with a flag. A tooltip DESCRIBES its trigger, so a screen reader flattens its contents into the trigger's description; a popover is a thing the trigger opens, so a button inside it stays a button. New in v2, React first.

data-scope="popover"

What you get for free

  • A title and a body, both of which may hold real controls
  • role=dialog rather than tooltip, so what is inside stays reachable
  • Hovering the popup keeps it open, so a link in it can be reached
  • The same twelve placements, collision handling and arrow as Tooltip

Usage

<Popover
  title="Delete this record?"
  content={<Button type="primary" size="small">Yes</Button>}
  trigger="click"
>
  <Button>Delete</Button>
</Popover>
// Vue lands in the next phase.
// Svelte lands in the next phase.
// Angular lands in the next phase.

Props

PropTypeDefaultNotes
contentReactNodeReact firstThe body. Unlike a tooltip's, it may contain interactive elements.
titleReactNodeReact firstAn optional heading. The part is omitted entirely when absent.
placementPlacement | PlacementAlias"top"React firstThe same twelve names Tooltip takes.
trigger"hover" | "focus" | "click" | Array<…>["hover", "click"]React first`click` is in the default because it is the only way a keyboard reaches this one — activating the trigger with Enter or Space dispatches one. A tap toggles it too.
open, defaultOpen, onOpenChangeboolean / (d: { open }) => voidReact firstControlled or uncontrolled, the same pair every overlay takes.
mouseEnterDelay, mouseLeaveDelaynumber0.1React firstSECONDS. The leave delay is also the window in which moving onto the popup keeps it open.
disabledbooleanReact firstNever opens, and closes if it already was.
arrowbooleantrueReact firstHidden automatically when it can no longer reach the anchor.
classNamestringReact firstLands on the trigger wrapper, which is the root rendered in place.
overlayClassNamestringReact firstLands on the popup instead.

Prop names are identical in all four frameworks. Only two-way binding differs, and each framework uses its own idiom over the same underlying prop. The marked rows are the exception, and a temporary one, in both directions: React first exists in React while the other three adapters catch up, and Not in React is the prop it replaced, still live everywhere else.

Parts

data-partDescription
triggerThe wrapper around your element. A real inline-flex box.
positionerPortalled to the body and given viewport coordinates.
contentThe popup box.
titleRendered only when a title is given.
bodyWraps `content`.
arrowA sibling of the content, so a scrolling box cannot clip it.