Skip to content

Pickers and overlays

Popover

A small non-modal layer attached to a trigger.

When to use it: Use it for extra controls or detail that should not block the page.

On this page

Example

Popover.tsxtsx
import { Popover, PopoverOverlay, PopoverTrigger } from "@comp0/react";

export function Example() {
  return (
    <Popover>
      <PopoverTrigger className="rounded border border-zinc-950/10 px-3 py-2.5 text-base text-zinc-800 sm:py-2 sm:text-sm dark:border-white/10 dark:text-zinc-100">
        Show details
      </PopoverTrigger>
      <PopoverOverlay
        placement="bottom start"
        offset={8}
        className="flex w-56 flex-col gap-1 rounded border-0 bg-white p-3 shadow-lg ring-1 ring-zinc-950/10 dark:bg-zinc-900 dark:shadow-none dark:ring-white/10"
      >
        <p className="text-base font-medium text-zinc-900 sm:text-sm dark:text-zinc-100">
          New release
        </p>
        <p className="text-base text-zinc-600 sm:text-sm dark:text-zinc-400">
          Version 0.1 is ready to explore.
        </p>
      </PopoverOverlay>
    </Popover>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. Popover

    Non-modal open-state provider. Does not add a DOM element.

  2. PopoverTrigger

    Button that opens content. Owns a DOM element.

  3. PopoverOverlay

    Non-modal floating content. Owns a DOM element.

  4. PopoverArrowOptional

    Optional decorative arrow inside PopoverOverlay. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start Popover with PopoverTrigger.

  2. 2

    Add the supporting parts

    Put PopoverOverlay after it and pick a placement such as bottom start.

  3. 3

    Make the behavior clear

    Use a visible label for the trigger.

    Exampletsx
    <Popover><PopoverTrigger>More</PopoverTrigger><PopoverOverlay placement="bottom start" offset={8}><PopoverArrow />Extra choices</PopoverOverlay></Popover>

Keyboard

Opens or closes from trigger.
Space
Opens or closes from trigger.
Esc
Closes and restores trigger focus.

Forms and accessibility

No native form behavior.

Accessibility checklist

  • Name the trigger so people know what opens.
  • Do not put essential instructions only in a popover.
  • PopoverArrow is decorative and should not carry meaning.

API reference

Importtsx
import { Popover, PopoverArrow, PopoverOverlay, PopoverTrigger } from "@comp0/react";

Popover

Context only

Non-modal open-state provider.

PropTypeDescription
open / defaultOpenbooleanControlled or initial open state.
onToggle(open: boolean) => voidReceives the next open state.

PopoverTrigger

DOM element

Button that opens content.

PropTypeDescription
asElementType | FragmentFragment merges the trigger onto your own element child.

PopoverOverlay

DOM element

Non-modal floating content.

PropTypeDescription
aria-labelstringAccessible name; the content is a dialog with no default name.
popover"auto" | "manual" | "none"Top-layer mode; auto by default.
placementPopoverPlacementTrigger side to open on, such as "bottom start"; flips when there is no room.
offsetnumberPixel gap between the trigger and the surface.

PopoverArrow

OptionalDOM element

Optional decorative arrow inside PopoverOverlay.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

[data-open]

on PopoverTrigger, PopoverOverlay

The popover is open.
:popover-open

on PopoverOverlay

Native pseudo-class equivalent.

Keep exploring