# Popover

> A bubble anchored to an element whose arrow always points at the anchor's center, even when the bubble is pushed in from the screen edge; it flips above or below to fit and unfurls out of the arrow tip.

- Type: Component (overlays)
- Access: Free, open source (MIT)
- Page: https://goodui.dev/native/components/popover
- Markdown: https://goodui.dev/native/components/popover.md
- Registry item: https://goodui.dev/native/r/popover.json
- Dependencies: react-native-reanimated, react-native-svg
- Keywords: react native popover, react native tooltip, expo tooltip, anchored popup with arrow, info icon tooltip, coach mark

## When to use

- A short explanation next to what it explains: an info icon, a chart value, a new feature.
- A small piece of UI tied to a control, such as a guest count picker under a field.

## When not to use

- A list of actions on an element: use context-menu (or action-sheet for screen-level choices).
- Content longer than a few lines or with several inputs: use bottom-sheet.
- Confirmations: use alert-dialog.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add https://goodui.dev/native/r/popover.json
npx expo install --fix
```

The component lands in `components/goodui-native/popover/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs locale.

### Setup

- Wrap the app in ThemeProvider (the bubble renders in its overlay layer).

Built-in strings follow `<GooduiLocaleProvider>` (one [language pack](https://goodui.dev/native/r/locale-tr.json) translates the whole kit); the `labels` prop overrides them for one instance.

## Usage

```tsx
import { Popover } from "@/components/goodui-native/popover/popover";

<Popover
  variant="tooltip"
  placement="top"
  accessibilityLabel="About billing"
  content="Billed once a year. Cancel anytime."
>
  <InfoIcon color={colors.textSecondary} />
</Popover>
```

## Examples

### Content with its own controls

```tsx
<Popover
  title="Guests"
  align="start"
  accessibilityLabel={`Guests, ${guests}`}
  content={(close) => (
    <View style={{ gap: 12, width: 240 }}>
      <GuestStepper value={guests} onChange={setGuests} />
      <Button size="sm" onPress={close}>Done</Button>
    </View>
  )}
>
  <GuestField count={guests} />
</Popover>
```

### Controlled coach mark

```tsx
<Popover open={showTip} onOpenChange={setShowTip} title="Split the bill" content="Split any payment with the people in this chat.">
  <SplitChip />
</Popover>
```

## API reference

### Popover

`import { Popover } from "@/components/goodui-native/popover/popover";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` (required) | `ReactNode` | – | The anchor. Popover makes it the button that opens the bubble, so pass plain content (icon, text, chip), not another button. |
| `content` (required) | `ReactNode \| ((close: () => void) => ReactNode)` | – | Bubble content. A string renders as text; a function receives `close`. |
| `title` | `string` | – | Heading inside a popover bubble. |
| `open` | `boolean` | – | Whether the bubble is shown (controlled). |
| `defaultOpen` | `boolean` | `false` | Open on first render when uncontrolled. |
| `onOpenChange` | `(open: boolean) => void` | – | Called when the bubble opens or closes. |
| `variant` | `"popover" \| "tooltip"` | `"popover"` | `popover` is a raised card for content and actions; `tooltip` is a small inverted label that also opens while the anchor is held (native) or hovered (web). |
| `placement` | `"top" \| "bottom"` | `"bottom"` | Preferred side. It flips to the other side when the bubble does not fit. |
| `align` | `"center" \| "start" \| "end"` | `"center"` | Horizontal alignment with the anchor before it is clamped to the screen. |
| `maxWidth` | `number` | – | Maximum bubble width in points. Default 300 for popovers, 240 for tooltips. |
| `haptic` | `boolean` | `true` | Haptic when a held tooltip appears. Default `true`. |
| `accessibilityLabel` | `string` | – | Label for the anchor button. Defaults to the anchor's text. |
| `anchorStyle` | `StyleProp<ViewStyle>` | – | Style of the anchor wrapper. |
| `labels` | `Partial<PopoverLabels>` | – | Overrides for the built-in strings; a GooduiLocaleProvider pack sets them app-wide. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- The anchor is a button with accessibilityState expanded and a hint; pass accessibilityLabel when it has no text (an icon).
- A popover bubble is modal for screen readers and announces its title when it opens; tooltips are a polite live region.
- Tap outside, Android back or Escape on the web closes a popover; the anchor gets an 8 pt hitSlop so small icons reach 44 pt.
- An accessibilityLabel on an anchor that shows text must start with that text (web browsers check it); leave it out to let the visible text name the anchor.

## Motion

- Open: the bubble grows out of the arrow tip; its height leads on the bouncy spring and its width follows on the morph spring, so it unfurls instead of just zooming, while it fades in.
- Close: fades and shrinks to 0.9 toward the arrow.
- Placement: prefers `placement`, flips to the other side when it does not fit, is clamped 12 pt from the screen edges, and the arrow slides along the bubble to stay on the anchor's center.
- Reduced motion: no growth; the bubble fades in and out.

## Haptics

- select when a tooltip opens from a long press
- none when tapping or hovering

## Performance

- The bubble mounts only while open, measures its content once and animates on the UI thread.

## Notes for AI

- children is the anchor and becomes the button: pass plain content (an icon, a chip, text), never another Button or Pressable.
- Give rich content a fixed width (for example width: 240) so the bubble measures it once.
- Tooltips (variant='tooltip') take a short string; they open on tap, while held (closing on release) and on hover on the web.
- content can be a function receiving close, for a Done button inside the bubble.
- The bubble is placed when it opens; it does not follow an anchor that scrolls while it is open (popovers block scrolling with their backdrop; hover tooltips close on hover out).

## Related

- [Context menu](https://goodui.dev/native/components/context-menu.md): Long-press an element and it lifts out of the page above a dimmed backdrop while a menu springs out beside it; keep the finger down, slide onto an item and release to choose. Right-click opens it on the web.
- [Alert dialog](https://goodui.dev/native/components/alert-dialog.md): A centered alert that springs in from slightly larger; touch an action and slide across the others with a tick per action, tap outside and it nudges, and async actions keep it open with a spinner until they settle.
- [Bottom sheet](https://goodui.dev/native/components/bottom-sheet.md): A sheet that rests at detents, follows the finger 1:1, settles with velocity and hands drags off to its scroll view.

## Guidance for AI tools

Popover: A bubble anchored to an element whose arrow always points at the anchor's center, even when the bubble is pushed in from the screen edge; it flips above or below to fit and unfurls out of the arrow tip. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
