527 lines
26 KiB
Plaintext
527 lines
26 KiB
Plaintext
---
|
|
title: Popover
|
|
description: Displays a floating content panel anchored to a trigger element with placement and alignment options.
|
|
links:
|
|
source_native: popover/popover.tsx
|
|
styles_native: popover/popover.styles.ts
|
|
figma: true
|
|
---
|
|
|
|
<NativeVideoPlayerView
|
|
srcLight="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/popover-docs-light.mp4"
|
|
srcDark="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/docs/native/components/videos/popover-docs-dark.mp4"
|
|
/>
|
|
|
|
## Import
|
|
|
|
```tsx
|
|
import { Popover } from 'heroui-native';
|
|
```
|
|
|
|
## Anatomy
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
{
|
|
/* 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.
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
<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.
|
|
|
|
```tsx
|
|
<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`.
|
|
|
|
```tsx
|
|
<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
|
|
|
|
```tsx
|
|
// 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
|
|
|
|
```tsx
|
|
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:
|
|
|
|
- `false` or `"disabled"`: Disable only root animations
|
|
- `"disable-all"`: Disable all animations including children
|
|
- `true` or `undefined`: Use default animations
|
|
- `object`: Custom animation configuration
|
|
|
|
| prop | type | default | description |
|
|
| ---------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------ | ----------------------------------- |
|
|
| `entering.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',`<br/>`config: { duration: 200,`<br/>`easing: Easing.out(Easing.ease) } }` | Animation configuration for opening |
|
|
| `exiting.value` | `SpringAnimationConfig \| TimingAnimationConfig` | `{ type: 'timing',`<br/>`config: { duration: 150,`<br/>`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:
|
|
|
|
- `false` or `"disabled"`: Disable all animations
|
|
- `true` or `undefined`: Use default animations
|
|
- `object`: 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:
|
|
|
|
- `false` or `"disabled"`: Disable all animations
|
|
- `true` or `undefined`: Use default animations
|
|
- `object`: 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<br/>`(4, 0, 4)` or `(-4, 0, -4)` | TranslateX values [idle, open, close] |
|
|
| `translateY.value` | `[number, number, number]` | Based on placement<br/>`(4, 0, 4)` or `(-4, 0, -4)` | TranslateY values [idle, open, close] |
|
|
| `transformOrigin.value` | `string` | Based on placement<br/>`'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.
|
|
|
|
```tsx
|
|
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.
|
|
|
|
```tsx
|
|
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.
|