Popover
The Popover component provides a way to create floating overlays that display rich content in a popup. It’s suited to menus, forms, or any content that needs to appear above other elements without disrupting the page flow.
It can be composed with subcomponents — Popover.Root, Popover.Trigger, Popover.Content, and Popover.Anchor — for a structured, customizable interface. Popover.Content supports built-in title, description, and linkProps for common patterns, while also allowing custom content through children.
Variations
Basic popover
The simplest form of a popover with just title and description.
Popover with custom content
You can include any custom content inside the popover by using children.
Hover trigger popover
Set triggerType to hover on the shorthand Popover to open on hover instead of click. You can also customize the hover delay and close delay.
Popover with link
The popover supports an integrated link using the linkProps prop.
Positioning
The popover can be positioned relative to its trigger using the side and align props.
Controlled popover
You can control the open state of the popover programmatically.
Using anchor
The Popover.Anchor component allows you to position the popover relative to a different element than the trigger.
Installation
import { Popover } from "@harnessio/ui/components";
//...
return ( <Popover.Root> <Popover.Trigger asChild> <Button>Show Info</Button> </Popover.Trigger>
<Popover.Content title="Information" description="This is additional information about the feature." /> </Popover.Root>
// --- or, using the shorthand component ---
<Popover title="Popover Title" description="Popover description" content="Popover content"> <Button>Show Info</Button> </Popover>)Anatomy
Popover offers two APIs. Compose the parts for full control, or use the shorthand Popover component for the common case.
<Popover.Root> <Popover.Trigger /> <Popover.Anchor /> <Popover.Content /></Popover.Root>
// or the shorthand
<Popover title="Popover Title" description="Popover description" content="Popover content"> <Button>Trigger</Button></Popover>Popover.Root— the container; controls open state (open/defaultOpen/onOpenChange) and modality (modal). Built directly on Radix Popover.Popover.Trigger— the element that opens the popover; useasChildto render your own button.Popover.Anchor— optional; positions the popover against a different element than the trigger.Popover.Content— the floating panel, with built-intitle,description, andlinkProps, plus positioning props (side,align,sideOffset,alignOffset) and children for custom content.Popover(shorthand) — a single component that wraps your children as the trigger and takescontentplus the content props. This is the only API that offers hover triggering (triggerType,hoverDelay,closeDelay); it does not acceptmodal.
Best practices
Do
- Use the shorthand
Popoverfor simple title/description/link popovers; reach for the composed parts when you need custom content or an anchor. - Keep popover content concise — it’s a supplement, not a page.
- Set
modalonPopover.Rootwhen the popover requires the user’s full attention before returning to the page.
Don’t
- Don’t put critical, non-recoverable actions inside a popover that dismisses on outside click.
- Don’t rely on hover triggering for essential content — it isn’t available on touch devices and is harder to reach.
Content
- Write the
titleas a short noun phrase and thedescriptionas one or two supporting sentences. - Give
linkProps.texta descriptive label (“View documentation”), not “click here”.
Accessibility
Keyboard
- Built on Radix Popover: the trigger opens on Enter / Space, Escape closes the popover, and focus behavior follows Radix conventions.
Labeling
- The content renders with
role="dialog"and the trigger exposesaria-expanded/aria-haspopup.
Focus & states
- Set
modalonPopover.Rootto trap focus and hide outside content from screen readers while the popover is open. The shorthandPopoveris always non-modal (it doesn’t acceptmodal) and deliberately keeps focus on the trigger rather than moving it into the content on open.
Properties
Popover (shorthand)
The single-component API. Wraps its children as the trigger, takes content, and forwards the remaining content props.
Prop | Required | Default | Type |
|---|---|---|---|
| children | true | ReactNode | |
| content | true | ReactNode | |
| triggerType | false | 'click' | 'click' | 'hover' |
| hoverDelay | false | 200 | number |
| closeDelay | false | 300 | number |
| open / defaultOpen / onOpenChange | false | boolean / boolean / (open: boolean) => void | |
| title, description, linkProps, side, align, … | false | PopoverContentProps |
Popover.Root
A direct re-export of the Radix Popover root.
Prop | Required | Default | Type |
|---|---|---|---|
| open | false | false | boolean |
| onOpenChange | false | (open: boolean) => void | |
| defaultOpen | false | false | boolean |
| modal | false | false | boolean |
| children | true | ReactNode |
Popover.Trigger
Prop | Required | Default | Type |
|---|---|---|---|
| asChild | false | false | boolean |
| disabled | false | false | boolean |
| className | false | string | |
| children | true | ReactNode |
Popover.Content
Prop | Required | Default | Type |
|---|---|---|---|
| title | false | string | |
| description | false | string | |
| linkProps | false | Omit<LinkProps, 'children'> & { text: string } | |
| theme | false | 'themed' | 'default' | 'themed' |
| custom | false | false | boolean |
| noMaxWidth | false | false | boolean |
| hideArrow | false | false | boolean |
| side | false | 'bottom' | 'top' | 'right' | 'bottom' | 'left' |
| sideOffset | false | 4 | number |
| align | false | 'center' | 'start' | 'center' | 'end' |
| alignOffset | false | 0 | number |
| children | false | ReactNode |
Popover.Anchor
Prop | Required | Default | Type |
|---|---|---|---|
| className | false | string | |
| children | false | ReactNode |