Skip to main content
A popover component for displaying rich content in a floating container positioned relative to a trigger.

Installation

npm install @kuzenbo/core

Usage

Basic Example

import { Popover, Button } from "@kuzenbo/core";

export default function PopoverExample() {
  return (
    <Popover>
      <Popover.Trigger render={<Button variant="outline" />}>
        View quota status
      </Popover.Trigger>
      <Popover.Content>
        <Popover.Header>
          <Popover.Title>Usage summary</Popover.Title>
          <Popover.Description>
            Workspace usage is at 82% of monthly compute quota.
          </Popover.Description>
        </Popover.Header>
      </Popover.Content>
    </Popover>
  );
}

With Sizes

import { Popover, Button } from "@kuzenbo/core";

export default function PopoverSizes() {
  return (
    <div className="flex gap-2">
      <Popover size="xs">
        <Popover.Trigger render={<Button variant="outline" />}>
          XS Popover
        </Popover.Trigger>
        <Popover.Content>
          <Popover.Header>
            <Popover.Title>Extra small</Popover.Title>
          </Popover.Header>
        </Popover.Content>
      </Popover>

      <Popover size="lg">
        <Popover.Trigger render={<Button variant="outline" />}>
          LG Popover
        </Popover.Trigger>
        <Popover.Content>
          <Popover.Header>
            <Popover.Title>Large popover</Popover.Title>
          </Popover.Header>
        </Popover.Content>
      </Popover>
    </div>
  );
}

Controlled State

import { Popover, Button } from "@kuzenbo/core";
import { useState } from "react";

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

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <Popover.Trigger render={<Button variant="outline" />}>
        Open popover
      </Popover.Trigger>
      <Popover.Content>
        <Popover.Header>
          <Popover.Title>Controlled popover</Popover.Title>
          <Popover.Description>
            Open state is controlled externally.
          </Popover.Description>
        </Popover.Header>
        <Popover.Close render={<Button size="sm" variant="outline" />}>
          Close
        </Popover.Close>
      </Popover.Content>
    </Popover>
  );
}

Composed Anatomy

import { Popover, Button } from "@kuzenbo/core";

export default function ComposedPopover() {
  return (
    <Popover>
      <Popover.Trigger render={<Button variant="outline" />}>
        Open actions
      </Popover.Trigger>
      <Popover.Portal>
        <Popover.Positioner side="bottom" sideOffset={8}>
          <Popover.Popup>
            <Popover.Arrow />
            <Popover.Viewport>
              <Popover.Header>
                <Popover.Title>Actions</Popover.Title>
                <Popover.Description>
                  Choose an action to perform.
                </Popover.Description>
              </Popover.Header>
            </Popover.Viewport>
          </Popover.Popup>
        </Popover.Positioner>
      </Popover.Portal>
    </Popover>
  );
}

API Reference

Popover (Root)

defaultOpen
boolean
The initial open state when uncontrolled.
open
boolean
The controlled open state of the popover.
onOpenChange
(open: boolean) => void
Callback fired when the open state changes.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default:"'md'"
The size variant for the popover.

Popover.Content

side
'top' | 'right' | 'bottom' | 'left'
default:"'bottom'"
The preferred side of the trigger to render against.
sideOffset
number
default:"4"
The distance in pixels from the trigger.
align
'start' | 'center' | 'end'
default:"'center'"
The alignment of the popover relative to the trigger.
alignOffset
number
default:"0"
The offset in pixels from the alignment axis.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
Override the root size for this content.
className
string
Additional CSS classes to apply.

Popover.Popup

size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
Override the root size for this popup.
className
string
Additional CSS classes to apply.

Popover.Positioner

side
'top' | 'right' | 'bottom' | 'left'
The preferred side of the trigger to render against.
sideOffset
number
The distance in pixels from the trigger.
align
'start' | 'center' | 'end'
The alignment relative to the trigger.
alignOffset
number
The offset in pixels from the alignment axis.

Popover.Trigger

render
ReactElement
The element to render as the trigger.

Popover.Title

children
ReactNode
The title content for the popover.

Popover.Description

children
ReactNode
The description content for the popover.

Popover.Header

children
ReactNode
The header content, typically contains Title and Description.

Popover.Close

render
ReactElement
The element to render as the close trigger.

Popover.Arrow

Renders a visual arrow pointing to the trigger.

Component Parts

  • Popover - Root component that manages state
  • Popover.Trigger - Opens the popover
  • Popover.Portal - Portals the popover content
  • Popover.Positioner - Positions the popover relative to trigger
  • Popover.Popup - The popover container
  • Popover.Viewport - Content viewport
  • Popover.Content - Convenience wrapper that includes Portal, Positioner, Popup, and Viewport
  • Popover.Header - Styled header container
  • Popover.Title - Accessible title
  • Popover.Description - Accessible description
  • Popover.Arrow - Visual arrow indicator
  • Popover.Close - Closes the popover
  • Popover.Backdrop - Optional backdrop overlay

Accessibility

  • Popover implements proper ARIA attributes
  • Pressing Escape closes the popover
  • Clicking outside closes the popover
  • Focus management when opening and closing
  • Title and Description are automatically linked for screen readers

Build docs developers (and LLMs) love