NovaUI
Components

Popover

A floating overlay anchored to a trigger element, used for contextual content and forms.

The Popover component is a floating overlay that appears below (or near) a trigger element. It supports configurable alignment, side offset, controlled/uncontrolled state, and auto-positioning to stay within screen bounds. Built with React Native's Modal API and a compound component pattern.

Preview

DimensionsSet the dimensions for the layer.
Width
100%
Height
25px

Installation

npx novaui-cli add popover

Import

import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverAnchor,
  PopoverHeader,
  PopoverTitle,
  PopoverDescription,
} from 'novaui-components'

Basic Usage

The Popover is a compound component with these parts:

  • Popover - Root container with open/close state and position tracking
  • PopoverTrigger - The element that toggles the popover on press
  • PopoverContent - The floating content panel
  • PopoverAnchor - Optional custom anchor element for positioning
  • PopoverHeader - Groups the title and description
  • PopoverTitle - The popover heading
  • PopoverDescription - Subtitle or description text
DimensionsSet the dimensions for the layer.
Width
100%
Max. width
300px
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverHeader,
  PopoverTitle,
  PopoverDescription,
} from 'novaui-components'
import { Button } from 'novaui-components'
import { View, Text, TextInput } from 'react-native'

export function BasicPopover() {
  return (
    <Popover>
      <PopoverTrigger>
        <Button variant="outline" label="Open Popover" />
      </PopoverTrigger>
      <PopoverContent>
        <PopoverHeader>
          <PopoverTitle>Dimensions</PopoverTitle>
          <PopoverDescription>Set the dimensions for the layer.</PopoverDescription>
        </PopoverHeader>
        <View className="gap-2">
          <View className="flex-row items-center justify-between">
            <Text className="text-sm">Width</Text>
            <TextInput
              className="h-8 w-20 rounded-md border border-input bg-background px-2"
              defaultValue="100%"
            />
          </View>
          <View className="flex-row items-center justify-between">
            <Text className="text-sm">Max. width</Text>
            <TextInput
              className="h-8 w-20 rounded-md border border-input bg-background px-2"
              defaultValue="300px"
            />
          </View>
        </View>
      </PopoverContent>
    </Popover>
  )
}

Alignment

Control how the popover aligns relative to the trigger:

// Start-aligned (left edge of trigger)
<PopoverContent align="start">...</PopoverContent>

// Center-aligned (default)
<PopoverContent align="center">...</PopoverContent>

// End-aligned (right edge of trigger)
<PopoverContent align="end">...</PopoverContent>

Controlled State

Control the popover programmatically:

import { useState } from 'react'

export function ControlledPopover() {
  const [open, setOpen] = useState(false)

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger>
        <Button variant="outline" label="Toggle" />
      </PopoverTrigger>
      <PopoverContent>
        <PopoverHeader>
          <PopoverTitle>Controlled</PopoverTitle>
          <PopoverDescription>
            This popover is controlled externally.
          </PopoverDescription>
        </PopoverHeader>
      </PopoverContent>
    </Popover>
  )
}

Props API

Popover Props

PropTypeDefaultDescription
openboolean-Controlled open state
onOpenChange(open: boolean) => void-Callback when open state changes
defaultOpenbooleanfalseInitial open state (uncontrolled)

PopoverTrigger Props

Extends React.ComponentPropsWithoutRef<typeof Pressable>:

PropTypeDefaultDescription
asChildbooleanfalseRender as the child element instead of a Pressable

PopoverContent Props

Extends React.ComponentPropsWithoutRef<typeof View>:

PropTypeDefaultDescription
align'start' | 'center' | 'end''center'Horizontal alignment relative to the trigger
sideOffsetnumber4Distance in pixels between the trigger and content
classNamestring-Additional CSS classes

PopoverAnchor Props

Extends React.ComponentPropsWithoutRef<typeof View>:

PropTypeDefaultDescription
classNamestring-Additional CSS classes

PopoverHeader Props

PropTypeDefaultDescription
classNamestring-Additional CSS classes

PopoverTitle Props

Extends React.ComponentPropsWithoutRef<typeof Text>:

PropTypeDefaultDescription
classNamestring-Additional CSS classes

PopoverDescription Props

Extends React.ComponentPropsWithoutRef<typeof Text>:

PropTypeDefaultDescription
classNamestring-Additional CSS classes

Positioning

The Popover automatically positions itself:

  • Measures the trigger element's position on screen using measure()
  • Places content below the trigger with the configured sideOffset
  • Adjusts horizontal position based on align prop
  • Clamps to screen bounds so content doesn't overflow off-screen

Best Practices

  1. Keep content concise: Popovers should contain small forms, settings, or quick info — not full pages

  2. Use appropriate alignment: Align to the trigger edge that makes sense for the content layout

  3. Dismiss on outside press: The built-in backdrop press handles this automatically

  4. Don't overuse: Reserve popovers for contextual actions — use Dialog for focused tasks

  5. Width control: Default width is w-72 — override with className for wider or narrower content

  • Use HoverCard for preview content that appears on hover/press
  • Use Dialog for larger, centered modal content
  • Use Tooltip for simple text hints (if available)

On this page