Popover
A Popover is essentially an interactive
Tooltip for displaying an overlay anchored to a
particular element. It can set up to open automatically using a trigger
element that also serves as its anchor point, or it can be opened manually
positioned relative to an anchor element.
React
import { Popover } from '@hoverinc/design-system-react-web';
Basic usage
It is used to display contextual information to the user, and should be paired with a clickable trigger element.
When Popover opens, focus is sent to the popover content. When it closes, focus is returned to the trigger.
Close button
Pass isClosable to enable the built-in close button.
Action
When there is a single action associated with the popover, render a
PopoverButton in the footer.
Hover
Pass isHover to open the popover when the trigger is hovered instead of
clicked.
Color mode
By default, Popover uses the color mode context to determine whether to
display a dark or light placeholder animation. Pass colorMode to manually
force a color mode.
Variant
By default, Popover uses a solid background. Use the glass variant when
displaying popovers over media, such as images.
Rendering the Popover in a Portal
To render a popover in a Portal, pass the
inPortal prop.
Initial focus
By default, focus is to sent to the popover content when it opens. Pass the
initialFocusRef prop to send focus to a specific element instead.
Controlled usage
You can control the opening and closing of the popover by passing the isOpen,
and onClose props.
Sometimes you might need to set the returnFocusOnClose prop to false to
prevent popover from returning focus to PopoverTrigger's children.
Anchor
Pass anchor instead of trigger to prevent trigger any action. The wrapped
component will become a position reference.
When passing an anchor instead of a trigger, the state of the Popover must
be controlled with external state (controlled mode).
Anchor must accept a ref
As with trigger, if you pass a custom component inside
anchor ensure that it uses forwardRef so the popover is triggered
successfully.
Accessing internal state
All Popover elements have access to the internal popover state (isOpen and
onClose). Use the render prop pattern to gain access to them.
Placement
Since popover is powered by Popper, you can change the
placement of the popover by passing the placement prop.
The possible values are:
| Start | Center | End |
|---|---|---|
bottom-start | bottom (default) | bottom-end |
auto-start | auto | auto-end |
top-start | top | top-end |
left-start | left | left-end |
right-start | right | right-end |
Lazily mounting Popover
By default, the Popover component renders its content to the DOM, meaning that
invisible popover contents are still rendered but are hidden by styles.
If you want to defer rendering of popover content until that Popover is
opened, you can use the isLazy prop. This is useful if your content needs to
be extra performant, or make network calls on mount that should only happen when
the component is displayed.
Accessibility
Keyboard and Focus
- When the popover is opened, focus is moved to the
PopoverContent. If theinitialFocusRefis set, then focus moves to the element with thatref. - When the popover is closed, focus returns to the trigger. If you set
returnFocusOnClosetofalse, focus will not return. - If trigger is set to
hover:- Focusing on or mousing over the trigger will open the popover.
- Blurring or mousing out of the trigger will close the popover. If you move
your mouse into the
PopoverContent, it'll remain visible.
- If trigger is set to
click:- Clicking the trigger or using the
SpaceorEnterwhen focus is on the trigger will open the popover. - Clicking the trigger again will close the popover.
- Clicking the trigger or using the
- Hitting the
Esckey while the popover is open and focus is within thePopoverContent, will close the popover. If you setcloseOnEsctofalse, it will not close. - Clicking outside or blurring out of the
PopoverContentcloses the popover. If you setcloseOnBlurtofalse, it will not close.
ARIA Attributes
- If the trigger is set to
click, thePopoverContentelement has role set todialog. If the trigger is set tohover, thePopoverContenthasroleset totooltip. - The
PopoverContenthasaria-labelledbyset to theidof thePopoverHeader. - The
PopoverContenthasaria-describedbyset to theidof thePopoverBody. - The
PopoverContenthasaria-hiddenset totrueorfalsedepending on the open/closed state of the popover. - The trigger has
aria-haspopupset totrueto denote that it triggers a popover. - The trigger has
aria-controlsset to theidof thePopoverContentto associate the popover and the trigger. - The trigger has
aria-expandedset totrueorfalsedepending on the open/closed state of the popover.
React Native
Popover is built with Tamagui and provides a non-modal dialog that floats around a trigger for iOS and Android platforms.
Usage
import { iconInfo } from '@hoverinc/icons/native';import { XStack, YStack } from '@tamagui/stacks';import React from 'react';import { Body } from '@hoverinc/design-system-react-native';import { Heading } from '@hoverinc/design-system-react-native';import { Icon } from '@hoverinc/design-system-react-native';import { Popover } from '@hoverinc/design-system-react-native';const App = () => { return ( <Popover> <Popover.Trigger asChild> <XStack alignItems="center" backgroundColor="$backgroundGlass" borderRadius="$full" gap="$100" hitSlop={20} padding="$300" pressStyle={{ backgroundColor: '$interactiveGlass' }} > <Icon icon={iconInfo} size="small" /> </XStack> </Popover.Trigger> <Popover.Content> <YStack gap="$200" paddingBottom="$500"> <Heading size="xs">Estimates</Heading> <Body dimmed size="small"> Calculate material and labor costs for accurate takeoffs. </Body> </YStack> <Popover.Close asChild> <Stack> <Heading size="xs">Got it</Heading> </Stack> </Popover.Close> </Popover.Content> </Popover> );};
Components
The Popover component exports the following sub-components:
Popoverโ The main wrapper component that provides context and state managementPopover.Triggerโ The trigger element that opens the popover (supports scope prop)Popover.Contentโ The container for popover content with custom stylingPopover.Closeโ The close button component
Placement
The popover can be positioned relative to its trigger using the placement
prop:
<Popover placement="bottom">...</Popover><Popover placement="top">...</Popover><Popover placement="left">...</Popover><Popover placement="right">...</Popover>
Controlled vs Uncontrolled
The Popover component supports both controlled and uncontrolled usage:
// Controlledconst [open, setOpen] = useState(false);<Popover open={open} onOpenChange={setOpen}>...</Popover>// Uncontrolled<Popover defaultOpen={false}>...</Popover>
Scoped Popovers
For complex applications with multiple popovers, you can use scoped popovers to isolate popover behavior:
<Popover scope="myScope"> <Popover.Trigger scope="myScope"> <XStack alignItems="center" gap="$100"> <Icon icon={iconInfo} size="small" /> </XStack> </Popover.Trigger> <Popover.Content> <Text>Scoped Content</Text> </Popover.Content></Popover>
Custom Offset
You can customize the offset distance from the trigger:
<Popover offset={-50}>...</Popover>