VayuUI

Popover

Displays rich content in a floating panel, triggered by a button.

Installation

npx vayu-ui init #one time only
npx vayu-ui add popover
npx vayu-ui add -t popover #with test case needs

Usage

Popover Example

Features
Alignment
Positions
Custom Trigger
<Popover>
  <Popover.Trigger>Open Popover</Popover.Trigger>
  <Popover.Content>
    <p>Popover content goes here.</p>
  </Popover.Content>
</Popover>

<Popover>
  <Popover.Trigger>With Arrow</Popover.Trigger>
  <Popover.Content showArrow side="top">
    <p>This popover has an arrow pointing to the trigger.</p>
  </Popover.Content>
</Popover>

<Popover>
  <Popover.Trigger>Aligned Start</Popover.Trigger>
  <Popover.Content side="bottom" align="start">
    <p>align="start"</p>
  </Popover.Content>
</Popover>

<Popover>
  <Popover.Trigger asChild>
    <button className="...">Custom Trigger</button>
  </Popover.Trigger>
  <Popover.Content showArrow>
    <p>Using asChild with a custom trigger element.</p>
  </Popover.Content>
</Popover>

Anatomy

import { Popover } from 'vayu-ui';

<Popover>
  <Popover.Trigger>Trigger</Popover.Trigger>
  <Popover.Content>Content goes here.</Popover.Content>
</Popover>;
  • Popover — Root container. Manages open/close state and provides context to children.
  • Popover.Trigger — Button element that toggles the popover open or closed. Supports asChild to merge props onto a custom element.
  • Popover.Content — Floating panel positioned relative to the trigger. Supports directional placement, arrow indicator, and collision avoidance.

Accessibility

  • Keyboard Support:
    • Enter / Space — Toggle the popover open or closed.
    • Escape — Close the popover and return focus to the trigger.
  • ARIA Attributes:
    • aria-expanded on Popover.Trigger reflects the open/closed state.
    • aria-haspopup="dialog" on Popover.Trigger indicates a dialog will open.
    • role="dialog" on Popover.Content identifies it as a dialog.
    • aria-modal on Popover.Content reflects whether modal mode is enabled.
  • Focus Behavior:
    • Focus moves to Popover.Content when it opens.
    • Focus returns to the trigger when the popover closes.
    • Clicking outside the popover closes it and returns focus to the trigger.

Screen reader behavior

When a user navigates to a popover trigger, the screen reader announces the button text and its expanded or collapsed state via aria-expanded. When the popover opens, focus moves to the content panel which has role="dialog". If the popover is in modal mode, aria-modal="true" is set and the underlying page content becomes inert. When the popover closes via Escape or an outside click, focus returns to the trigger button and the screen reader announces the trigger again.

Component Folder Structure

Popover/
├── Popover.tsx         # Root component with context provider and open/close state
├── PopoverTrigger.tsx  # Trigger button with asChild support
├── PopoverContent.tsx  # Positioned floating content with arrow and collision avoidance
├── hooks.ts            # Context, usePopover hook, and usePopoverPosition positioning logic
├── types.ts            # TypeScript type definitions and arrow position classes
├── index.ts            # Re-exports all components and types
└── README.md           # Component usage reference

Props

Popover (Root)

PropTypeDefaultDescription
defaultOpenbooleanfalseOpen state when initially rendered.
openbooleanControlled open state.
onOpenChange(open: boolean) => voidCallback when the open state changes.
modalbooleanfalseRender with a backdrop overlay.
childrenReactNodePopover.Trigger and Popover.Content.
classNamestringAdditional CSS classes.

Popover.Trigger

PropTypeDefaultDescription
asChildbooleanfalseMerge props onto the child element instead of wrapping.
disabledbooleanfalseDisable the trigger.
childrenReactNodeTrigger label content.
classNamestringAdditional CSS classes.

Popover.Content

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"Preferred side to render against the trigger.
align"start" | "center" | "end""center"Preferred alignment against the trigger.
sideOffsetnumber8Distance in pixels from the trigger.
alignOffsetnumber0Offset in pixels from the start or end alignment.
showArrowbooleanfalseRender an arrow pointing to the trigger.
avoidCollisionsbooleantrueAutomatically flip position to stay within the viewport.
childrenReactNodePopover content.
classNamestringAdditional CSS classes.

On this page