Popover
Displays a floating content panel anchored to a trigger element with placement and alignment options.
Import
import { Popover } from 'heroui-native';Anatomy
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content>
<Popover.Arrow />
<Popover.Close />
<Popover.Title>...</Popover.Title>
<Popover.Description>...</Popover.Description>
</Popover.Content>
</Popover.Portal>
</Popover>- Popover: Main container that manages open/close state, positioning, and provides context to child components.
- Popover.Trigger: Clickable element that toggles popover visibility. Wraps any child element with press handlers.
- Popover.Portal: Renders popover content in a portal layer above other content. Ensures proper stacking and positioning.
- Popover.Overlay: Optional background overlay. Can be transparent or semi-transparent to capture outside clicks.
- Popover.Content: Container for popover content with positioning, styling, and collision detection. Supports both popover and bottom-sheet presentations.
- Popover.Arrow: Optional arrow element pointing to the trigger. Automatically positioned based on placement.
- Popover.Close: Close button that dismisses the popover when pressed. Renders a default X icon if no children provided.
- Popover.Title: Optional title text with pre-styled typography.
- Popover.Description: Optional description text with muted styling.
Usage
Basic Usage
The Popover component uses compound parts to create floating content panels.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content>...</Popover.Content>
</Popover.Portal>
</Popover>With Title and Description
Structure popover content with title and description for better information hierarchy.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content>
<Popover.Close />
<Popover.Title>...</Popover.Title>
<Popover.Description>...</Popover.Description>
</Popover.Content>
</Popover.Portal>
</Popover>With Arrow
Add an arrow pointing to the trigger element for better visual connection.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content placement="top">
<Popover.Arrow />
...
</Popover.Content>
</Popover.Portal>
</Popover>Width Control
Control the width of the popover content using the width prop.
{
/* Fixed width in pixels */
}
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content width={320}>...</Popover.Content>
</Popover.Portal>
</Popover>;
{
/* Match trigger width */
}
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content width="trigger">...</Popover.Content>
</Popover.Portal>
</Popover>;
{
/* Full width (100%) */
}
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content width="full">...</Popover.Content>
</Popover.Portal>
</Popover>;
{
/* Auto-size to content (default) */
}
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content width="content-fit">...</Popover.Content>
</Popover.Portal>
</Popover>;Bottom Sheet Presentation
Use bottom sheet presentation for mobile-optimized interaction patterns.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content presentation="bottom-sheet">
<Popover.Title>...</Popover.Title>
<Popover.Description>...</Popover.Description>
<Popover.Close asChild>
<Button>Close</Button>
</Popover.Close>
</Popover.Content>
</Popover.Portal>
</Popover>Placement Options
Control where the popover appears relative to the trigger element.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Content placement="left">...</Popover.Content>
</Popover.Portal>
</Popover>Alignment Options
Fine-tune content alignment along the placement axis.
<Popover>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Content placement="top" align="start">
...
</Popover.Content>
</Popover.Portal>
</Popover>Custom Animation
Configure custom animations for open and close transitions using the animation prop on Popover.Root.
<Popover
animation={{
entering: {
type: 'spring',
config: { damping: 15, stiffness: 300 },
},
exiting: {
type: 'timing',
config: { duration: 200 },
},
}}
>
<Popover.Trigger>...</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content>...</Popover.Content>
</Popover.Portal>
</Popover>Programmatic control
// Open or close popover programmatically using ref
const popoverRef = useRef<PopoverTriggerRef>(null);
// Open programmatically
popoverRef.current?.open();
// Close programmatically
popoverRef.current?.close();
// Full example
<Popover>
<Popover.Trigger ref={popoverRef} asChild>
<Button>Trigger</Button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content>
<Text>Content</Text>
<Button onPress={() => popoverRef.current?.close()}>Close</Button>
</Popover.Content>
</Popover.Portal>
</Popover>;Example
import { Ionicons } from '@expo/vector-icons';
import { Button, Popover, useThemeColor } from 'heroui-native';
import { Text, View } from 'react-native';
export default function PopoverExample() {
const themeColorMuted = useThemeColor('muted');
return (
<Popover>
<Popover.Trigger asChild>
<Button variant="tertiary" size="sm">
<Button.StartContent>
<Ionicons
name="information-circle"
size={20}
color={themeColorMuted}
/>
</Button.StartContent>
<Button.LabelContent>Show Info</Button.LabelContent>
</Button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Overlay />
<Popover.Content width={320} className="gap-1 rounded-xl px-6 py-4">
<Popover.Close className="absolute top-3 right-3 z-50" />
<Popover.Title>Information</Popover.Title>
<Popover.Description>
This popover includes a title and description to provide more
structured information to users.
</Popover.Description>
</Popover.Content>
</Popover.Portal>
</Popover>
);
}API Reference
Popover
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | Children elements to be rendered inside the popover |
isOpen | boolean | - | Whether the popover is open (controlled mode) |
isDefaultOpen | boolean | - | The open state of the popover when initially rendered (uncontrolled mode) |
onOpenChange | (isOpen: boolean) => void | - | Callback when the popover open state changes |
closeDelay | number | 400 | Delay in milliseconds before closing the popover |
animation | PopoverRootAnimation | - | Animation configuration |
asChild | boolean | false | Whether to render as a child element |
...ViewProps | ViewProps | - | All standard React Native View props are supported |
PopoverRootAnimation
Animation configuration for popover root component. Can be:
falseor"disabled": Disable only root animations"disable-all": Disable all animations including childrentrueorundefined: Use default animationsobject: Custom animation configuration
| prop | type | default | description |
|---|---|---|---|
entering.value | SpringAnimationConfig | TimingAnimationConfig | { type: 'timing',config: { duration: 200,easing: Easing.out(Easing.ease) } } | Animation configuration for opening |
exiting.value | SpringAnimationConfig | TimingAnimationConfig | { type: 'timing',config: { duration: 150,easing: Easing.bezier(0.4, 0, 1, 1) } } | Animation configuration for closing |
SpringAnimationConfig
| prop | type | default | description |
|---|---|---|---|
type | 'spring' | - | Animation type (must be 'spring') |
config | WithSpringConfig | - | Reanimated spring animation configuration |
TimingAnimationConfig
| prop | type | default | description |
|---|---|---|---|
type | 'timing' | - | Animation type (must be 'timing') |
config | WithTimingConfig | - | Reanimated timing animation configuration |
Popover.Trigger
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The trigger element content |
className | string | - | Additional CSS classes for the trigger |
asChild | boolean | true | Whether to render as a child element |
...PressableProps | PressableProps | - | All standard React Native Pressable props are supported |
Popover.Portal
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The portal content (required) |
hostName | string | - | Optional name of the host element for the portal |
forceMount | boolean | - | Whether to force mount the component in the DOM |
className | string | - | Additional CSS classes for the portal container |
...ViewProps | ViewProps | - | All standard React Native View props are supported |
Popover.Overlay
| prop | type | default | description |
|---|---|---|---|
className | string | - | Additional CSS classes for the overlay |
closeOnPress | boolean | true | Whether to close the popover when overlay is pressed |
forceMount | boolean | - | Whether to force mount the component in the DOM |
animation | PopoverOverlayAnimation | - | Animation configuration |
asChild | boolean | false | Whether to render as a child element |
...Animated.ViewProps | Animated.ViewProps | - | All Reanimated Animated.View props are supported |
PopoverOverlayAnimation
Animation configuration for popover overlay component. Can be:
falseor"disabled": Disable all animationstrueorundefined: Use default animationsobject: Custom animation configuration
| prop | type | default | description |
|---|---|---|---|
opacity.value | [number, number, number] | [0, 1, 0] | Opacity values [idle, open, close] |
Popover.Content (Popover Presentation)
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The popover content |
width | number | 'trigger' | 'content-fit' | 'full' | 'content-fit' | Width sizing strategy for the content |
placement | 'top' | 'bottom' | 'left' | 'right' | 'bottom' | Placement of the popover relative to trigger |
align | 'start' | 'center' | 'end' | 'center' | Alignment along the placement axis |
avoidCollisions | boolean | true | Whether to flip placement when close to viewport edges |
offset | number | 8 | Distance from trigger element in pixels |
alignOffset | number | 0 | Offset along the alignment axis in pixels |
disablePositioningStyle | boolean | false | Whether to disable automatic positioning styles |
forceMount | boolean | - | Whether to force mount the component in the DOM |
insets | Insets | - | Screen edge insets to respect when positioning |
className | string | - | Additional CSS classes for the content container |
presentation | 'popover' | - | Presentation mode for the popover |
animation | PopupPopoverContentAnimation | - | Animation configuration |
asChild | boolean | false | Whether to render as a child element |
...Animated.ViewProps | Animated.ViewProps | - | All Reanimated Animated.View props are supported |
Popover.Content (Bottom Sheet Presentation)
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The bottom sheet content |
presentation | 'bottom-sheet' | - | Presentation mode for the popover |
bottomSheetViewClassName | string | - | Additional CSS classes for the bottom sheet view |
bottomSheetViewProps | BottomSheetViewProps | - | Props for the bottom sheet view |
enablePanDownToClose | boolean | true | Whether pan down gesture closes the sheet |
backgroundStyle | ViewStyle | - | Style for the bottom sheet background |
handleIndicatorStyle | ViewStyle | - | Style for the bottom sheet handle indicator |
...BottomSheetProps | BottomSheetProps | - | All @gorhom/bottom-sheet props are supported |
PopupPopoverContentAnimation
Animation configuration for popover content component (popover presentation). Can be:
falseor"disabled": Disable all animationstrueorundefined: Use default animationsobject: Custom animation configuration
| prop | type | default | description |
|---|---|---|---|
opacity.value | [number, number, number] | [0, 1, 0] | Opacity values [idle, open, close] |
scale.value | [number, number, number] | [0.95, 1, 0.95] | Scale values [idle, open, close] |
translateX.value | [number, number, number] | Based on placement(4, 0, 4) or (-4, 0, -4) | TranslateX values [idle, open, close] |
translateY.value | [number, number, number] | Based on placement(4, 0, 4) or (-4, 0, -4) | TranslateY values [idle, open, close] |
transformOrigin.value | string | Based on placement'top', 'bottom', 'left', 'right' | Transform origin value |
Popover.Arrow
| prop | type | default | description |
|---|---|---|---|
className | string | - | Additional CSS classes for the arrow |
height | number | 8 | Height of the arrow in pixels |
width | number | 16 | Width of the arrow in pixels |
fill | string | - | Fill color of the arrow (defaults to content background) |
stroke | string | - | Stroke (border) color of the arrow (defaults to content border color) |
strokeWidth | number | 1 | Stroke width of the arrow border in pixels |
strokeBaselineInset | number | 1 | Baseline inset in pixels for stroke alignment |
placement | 'top' | 'bottom' | 'left' | 'right' | - | Placement of the popover (inherited from content) |
children | ReactNode | - | Custom arrow content (replaces default SVG arrow) |
style | StyleProp<ViewStyle> | - | Additional styles for the arrow container |
...ViewProps | ViewProps | - | All standard React Native View props are supported |
Popover.Close
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The close button content |
className | string | - | Additional CSS classes for the close button |
iconProps | PopoverCloseIconProps | - | Close icon configuration |
hitSlop | number | Insets | 12 | Additional touch area around the button |
asChild | boolean | - | Whether to render as a child element |
...PressableProps | PressableProps | - | All standard React Native Pressable props are supported |
PopoverCloseIconProps
| prop | type | default | description |
|---|---|---|---|
size | number | 18 | Size of the icon |
color | string | --colors.muted | Color of the icon |
Popover.Title
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The title text content |
className | string | - | Additional CSS classes for the title |
...TextProps | TextProps | - | All standard React Native Text props are supported |
Popover.Description
| prop | type | default | description |
|---|---|---|---|
children | ReactNode | - | The description text content |
className | string | - | Additional CSS classes for the description |
...TextProps | TextProps | - | All standard React Native Text props are supported |
Hooks
usePopover
Hook to access popover context values within custom components or compound components.
import { usePopover } from 'heroui-native';
const CustomContent = () => {
const { isOpen, onOpenChange, triggerPosition } = usePopover();
// ... your implementation
};Returns: UsePopoverReturn
| property | type | description |
|---|---|---|
isOpen | boolean | Whether the popover is currently open |
onOpenChange | (open: boolean) => void | Callback function to change the popover open state |
isDefaultOpen | boolean | undefined | Whether the popover should be open by default (uncontrolled mode) |
isDisabled | boolean | undefined | Whether the popover is disabled |
triggerPosition | LayoutPosition | null | The position of the trigger element relative to the viewport |
setTriggerPosition | (triggerPosition: LayoutPosition | null) => void | Function to update the trigger element's position |
contentLayout | LayoutRectangle | null | The layout measurements of the popover content |
setContentLayout | (contentLayout: LayoutRectangle | null) => void | Function to update the content layout measurements |
nativeID | string | Unique identifier for the popover instance |
closeDelay | number | undefined | Delay in milliseconds before the popover closes |
Note: This hook must be used within a Popover component. It will throw an error if called outside of the popover context.
usePopoverAnimation
Hook to access popover animation state values within custom components or compound components.
import { usePopoverAnimation } from 'heroui-native';
const CustomContent = () => {
const { popoverState, progress, isDragging } = usePopoverAnimation();
// ... your implementation
};Returns: UsePopoverAnimationReturn
| property | type | description |
|---|---|---|
popoverState | 'idle' | 'open' | 'close' | Extended internal state for coordinating animations |
progress | SharedValue<number> | Progress value for the popover animation (0=idle, 1=open, 2=close) |
isDragging | SharedValue<boolean> | Dragging state shared value |
Note: This hook must be used within a Popover component. It will throw an error if called outside of the popover animation context.