PopoverUpdated

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 for the popover. Can accept custom children or uses default close icon.
  • 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 presentation="popover">...</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 presentation="popover">
      <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 presentation="popover" placement="top">
      <Popover.Arrow />
      ...
    </Popover.Content>
  </Popover.Portal>
</Popover>

Note: When using <Popover.Arrow />, you need to apply a border to Popover.Content, for instance using the border border-border class. This ensures the arrow visually connects properly with the content border.

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 presentation="popover" width={320}>...</Popover.Content>
  </Popover.Portal>
</Popover>;

{
  /* Match trigger width */
}
<Popover>
  <Popover.Trigger>...</Popover.Trigger>
  <Popover.Portal>
    <Popover.Overlay />
    <Popover.Content presentation="popover" width="trigger">...</Popover.Content>
  </Popover.Portal>
</Popover>;

{
  /* Full width (100%) */
}
<Popover>
  <Popover.Trigger>...</Popover.Trigger>
  <Popover.Portal>
    <Popover.Overlay />
    <Popover.Content presentation="popover" width="full">...</Popover.Content>
  </Popover.Portal>
</Popover>;

{
  /* Auto-size to content (default) */
}
<Popover>
  <Popover.Trigger>...</Popover.Trigger>
  <Popover.Portal>
    <Popover.Overlay />
    <Popover.Content presentation="popover" width="content-fit">...</Popover.Content>
  </Popover.Portal>
</Popover>;

Bottom Sheet Presentation

Use bottom sheet presentation for mobile-optimized interaction patterns.

Important: The presentation prop on Popover.Content must match the presentation prop on Popover.Root. In development mode, a mismatch will throw an error.

<Popover presentation="bottom-sheet">
  <Popover.Trigger>...</Popover.Trigger>
  <Popover.Portal>
    <Popover.Overlay />
    <Popover.Content presentation="bottom-sheet">
      <Popover.Title>...</Popover.Title>
      <Popover.Description>...</Popover.Description>
      <Button>Close</Button>
    </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 presentation="popover" 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 presentation="popover" 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 presentation="popover">...</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 presentation="popover">
      <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 presentation="popover" 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>
  );
}

You can find more examples in the GitHub repository.

API Reference

Popover

proptypedefaultdescription
childrenReactNode-Children elements to be rendered inside the popover
isOpenboolean-Whether the popover is open (controlled mode)
isDefaultOpenboolean-The open state of the popover when initially rendered (uncontrolled mode)
onOpenChange(isOpen: boolean) => void-Callback when the popover open state changes
animationAnimationRootDisableAll-Animation configuration. Can be false, "disabled", "disable-all", true, or undefined
presentation'popover' | 'bottom-sheet''popover'Presentation mode for the popover content
asChildbooleanfalseWhether to render as a child element
...ViewPropsViewProps-All standard React Native View props are supported

AnimationRootDisableAll

Animation configuration for popover root component. Can be:

  • false or "disabled": Disable only root animations
  • "disable-all": Disable all animations including children
  • true or undefined: Use default animations

Popover.Trigger

proptypedefaultdescription
childrenReactNode-The trigger element content
classNamestring-Additional CSS classes for the trigger
asChildbooleantrueWhether to render as a child element
...PressablePropsPressableProps-All standard React Native Pressable props are supported

Popover.Portal

proptypedefaultdescription
childrenReactNode-The portal content (required)
hostNamestring-Optional name of the host element for the portal
forceMountboolean-Whether to force mount the component in the DOM
classNamestring-Additional CSS classes for the portal container
...ViewPropsViewProps-All standard React Native View props are supported

Popover.Overlay

proptypedefaultdescription
classNamestring-Additional CSS classes for the overlay
closeOnPressbooleantrueWhether to close the popover when overlay is pressed
forceMountboolean-Whether to force mount the component in the DOM
animationPopoverOverlayAnimation-Animation configuration
isAnimatedStyleActivebooleantrueWhether animated styles (react-native-reanimated) are active
asChildbooleanfalseWhether to render as a child element
...Animated.ViewPropsAnimated.ViewProps-All Reanimated Animated.View props are supported

PopoverOverlayAnimation

Animation configuration for popover overlay component. Can be:

  • false or "disabled": Disable all animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
state'disabled' | boolean-Disable animations while customizing properties
opacity.value[number, number, number][0, 1, 0]Opacity values [idle, open, close] - Takes effect for bottom-sheet/dialog presentation
enteringEntryOrExitLayoutTypeFadeIn with duration 200msCustom Keyframe animation for entering transition - Takes effect for popover presentation
exitingEntryOrExitLayoutTypeFadeOut with duration 150msCustom Keyframe animation for exiting transition - Takes effect for popover presentation

Popover.Content (Popover Presentation)

proptypedefaultdescription
childrenReactNode-The popover content
presentation'popover''popover'Presentation mode - must match Popover.Root presentation prop. When not provided, defaults to 'popover'
widthnumber | '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
avoidCollisionsbooleantrueWhether to flip placement when close to viewport edges
offsetnumber9Distance from trigger element in pixels
alignOffsetnumber0Offset along the alignment axis in pixels
disablePositioningStylebooleanfalseWhether to disable automatic positioning styles
forceMountboolean-Whether to force mount the component in the DOM
insetsInsets-Screen edge insets to respect when positioning
classNamestring-Additional CSS classes for the content container
animationPopupPopoverContentAnimation-Animation configuration
isAnimatedStyleActivebooleantrueWhether animated styles (react-native-reanimated) are active
asChildbooleanfalseWhether to render as a child element
...Animated.ViewPropsAnimated.ViewProps-All Reanimated Animated.View props are supported

Popover.Content (Bottom Sheet Presentation)

proptypedefaultdescription
childrenReactNode-The bottom sheet content
presentation'bottom-sheet'-Presentation mode - must be 'bottom-sheet' and match Popover.Root presentation prop (required)
contentContainerClassNamestring-Additional CSS classes for the content container
contentContainerPropsBottomSheetViewProps-Props for the content container
enablePanDownToClosebooleantrueWhether pan down gesture closes the sheet
backgroundStyleViewStyle-Style for the bottom sheet background
handleIndicatorStyleViewStyle-Style for the bottom sheet handle indicator
...BottomSheetPropsBottomSheetProps-All @gorhom/bottom-sheet props are supported

PopupPopoverContentAnimation

Animation configuration for popover content component (popover presentation). Can be:

  • false or "disabled": Disable all animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
state'disabled' | boolean-Disable animations while customizing properties
enteringEntryOrExitLayoutTypeKeyframe with translateY/translateX, scale, and opacity (200ms)Custom Keyframe animation for entering transition
exitingEntryOrExitLayoutTypeKeyframe mirroring entering animation (150ms)Custom Keyframe animation for exiting transition

Popover.Arrow

proptypedefaultdescription
classNamestring-Additional CSS classes for the arrow
heightnumber12Height of the arrow in pixels
widthnumber20Width of the arrow in pixels
fillstring-Fill color of the arrow (defaults to content background)
strokestring-Stroke (border) color of the arrow (defaults to content border color)
strokeWidthnumber1Stroke width of the arrow border in pixels
strokeBaselineInsetnumber1Baseline inset in pixels for stroke alignment
placement'top' | 'bottom' | 'left' | 'right'-Placement of the popover (inherited from content)
childrenReactNode-Custom arrow content (replaces default SVG arrow)
styleStyleProp<ViewStyle>-Additional styles for the arrow container
...ViewPropsViewProps-All standard React Native View props are supported

Popover.Close

Popover.Close extends CloseButton and automatically handles popover dismissal when pressed.

Popover.Title

proptypedefaultdescription
childrenReactNode-The title text content
classNamestring-Additional CSS classes for the title
...TextPropsTextProps-All standard React Native Text props are supported

Popover.Description

proptypedefaultdescription
childrenReactNode-The description text content
classNamestring-Additional CSS classes for the description
...TextPropsTextProps-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

propertytypedescription
isOpenbooleanWhether the popover is currently open
onOpenChange(open: boolean) => voidCallback function to change the popover open state
isDefaultOpenboolean | undefinedWhether the popover should be open by default (uncontrolled mode)
isDisabledboolean | undefinedWhether the popover is disabled
triggerPositionLayoutPosition | nullThe position of the trigger element relative to the viewport
setTriggerPosition(triggerPosition: LayoutPosition | null) => voidFunction to update the trigger element's position
contentLayoutLayoutRectangle | nullThe layout measurements of the popover content
setContentLayout(contentLayout: LayoutRectangle | null) => voidFunction to update the content layout measurements
nativeIDstringUnique identifier for the popover instance

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 { progress, isDragging } = usePopoverAnimation();
  // ... your implementation
};

Returns: UsePopoverAnimationReturn

propertytypedescription
progressSharedValue<number>Progress value for the popover animation (0=idle, 1=open, 2=close)
isDraggingSharedValue<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.

On this page