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.
FormField
Provides consistent layout and interaction for form controls with label, description, and error handling. Perfect for Switch and Checkbox components when you want the entire field to be pressable.
PressableFeedback
Container component that provides visual feedback for press interactions with automatic scale animation.