Tessina UI
Tessina UI
GitHubIntroduction
InstallationUsageTheming
Components
ButtonIconButtonLinkSpinnerBadgeAvatarStatusChipShortcutSkeletonSurfaceProgressMeterRating
LabelFieldFieldsetCheckboxRadioSwitchSliderSelectComboboxSearchTextareaNumberFieldDate PickerTime PickerOTP InputFile UploadCalendar
AlertBannerToastTooltip
TabsAccordionCollapsibleBreadcrumbPaginationStepperSegmentedControlButtonGroupToggleButtonToggleGroupToolbarNavigation MenuMenubarBottom NavSidebar
Split ButtonFABDropdown MenuContextMenuCommandPopoverHoverCard
ContainerStackFlexGridAspectRatioSpacerCardCarouselDividerScroll Area
Table
ChatBubblePromptInputCodeBlock
ModalAlertDialogDrawerAction SheetTop Header MobileTop Header DesktopEmptyStateForm
Contributing
ComponentsAction Blocks

Popover

A floating panel that appears next to its trigger and holds interactive content. Click-activated, with full keyboard support, positioning, an optional arrow, and compound parts for header, body, and footer.

Playground

Installation

pnpm add @tessinaui/ui

Usage

import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  PopoverHeader,
  PopoverTitle,
  PopoverDescription,
  PopoverBody,
  PopoverFooter,
  PopoverArrow,
  PopoverClose,
} from "@tessinaui/ui";
<Popover size="md" rounded="md">
  <PopoverTrigger render={<Button>Open</Button>} />
  <PopoverContent side="bottom" align="center">
    <PopoverHeader showClose>
      <PopoverTitle>Popover title</PopoverTitle>
      <PopoverDescription>Brief description.</PopoverDescription>
    </PopoverHeader>
    <PopoverBody>
      <p>Any interactive content goes here — forms, lists, buttons…</p>
    </PopoverBody>
    <PopoverFooter>
      <PopoverClose render={<Button variant="ghost">Cancel</Button>} />
      <PopoverClose render={<Button>Confirm</Button>} />
    </PopoverFooter>
    <PopoverArrow />
  </PopoverContent>
</Popover>

Showcase

When to use Popover vs. Tooltip vs. DropdownMenu vs. Modal

Use Popover when…Use Tooltip when…Use DropdownMenu when…Use Modal when…
You need interactive contentYou just need informational text on hoverThe content is a list of menu itemsYou need to block the rest of the page
The trigger is click-activatedThe trigger is hover/focusUsers pick one option then dismissThe decision is critical or blocking
The panel can contain a form, list, or buttonsThe tip is short and non-interactiveKeyboard arrow navigation between itemsContent is large or requires focus

Anatomy

Popover composes several parts. Only Popover, PopoverTrigger, and PopoverContent are required — everything else is optional.

<Popover>
  <PopoverTrigger>…</PopoverTrigger>
  <PopoverContent>
    <PopoverHeader>
      <PopoverTitle />
      <PopoverDescription />
    </PopoverHeader>
    <PopoverBody />
    <PopoverFooter />
    <PopoverArrow />
  </PopoverContent>
</Popover>

Size

SizeMin widthMax widthText
"sm"200px240pxxs
"md" (default)260px320pxsm
"lg"320px400pxsm
"xl"400px480pxbase

Intent

Applies a semantic border colour to the popup and arrow — useful for warning/error confirmations.

ValueBorder
"none" (default)border-border
"error"border-error
"warning"border-warning
"success"border-success
"info"border-info

Rounded

ValueCSS
"none"rounded-none
"sm"rounded-md
"md" (default)rounded-lg
"lg"rounded-xl
"full"rounded-3xl

Positioning

PopoverContent accepts side (top | right | bottom | left), align (start | center | end), sideOffset (px gap from trigger, default 8), and alignOffset (px shift along the side, default 0).

<PopoverContent side="right" align="start" sideOffset={12}>
  …
</PopoverContent>

Arrow

The <PopoverArrow /> is a rotated square that blends into the popup surface, inheriting the current intent's border colour. It's entirely optional — omit it for a chip-style floating panel.

Backdrop & modal behaviour

By default the popover is non-modal — clicks outside dismiss but the page remains interactive. For destructive confirmations or flows that need focus-trapping, pass modal:

<Popover modal>
  …
</Popover>

To dim the background, render <PopoverBackdrop /> inside the popover:

<Popover modal>
  <PopoverTrigger render={<Button>Delete</Button>} />
  <PopoverBackdrop />
  <PopoverContent>…</PopoverContent>
</Popover>

Controlled

Popover accepts open, defaultOpen, and onOpenChange.

const [open, setOpen] = React.useState(false);

<Popover open={open} onOpenChange={setOpen}>
  <PopoverTrigger render={<Button>Open</Button>} />
  <PopoverContent>…</PopoverContent>
</Popover>

Close button in header

PopoverHeader accepts showClose — renders a small X button wired to close the popover. Only use when the popover is long-lived or contains interactive content that makes the dismiss affordance non-obvious.

<PopoverHeader showClose>
  <PopoverTitle>Rename file</PopoverTitle>
</PopoverHeader>

Accessibility

  • The trigger and popup are linked via ARIA — screen readers announce the popup's content when it opens.
  • PopoverTitle maps to aria-labelledby, PopoverDescription to aria-describedby.
  • Focus moves to the first focusable element in the popup on open, and returns to the trigger on close.
  • Escape closes the popover; outside-click closes it when dismissible is true (default).
  • Use intent="error" for destructive confirmations so assistive tech surfaces the semantic colour via the rendered border.

RTL

Pass dir="rtl" to the root. PopoverHeader's close button, PopoverFooter actions, and alignment all flip to follow the reading direction.

<Popover dir="rtl">
  <PopoverTrigger render={<Button>فتح</Button>} />
  <PopoverContent side="bottom" align="start">…</PopoverContent>
</Popover>

API Reference

Popover (root)

PropTypeDefaultDescription
size"sm" | "md" | "lg" | "xl""md"Min/max width + text size
rounded"none" | "sm" | "md" | "lg" | "full""md"Corner radius of popup
intent"none" | "error" | "warning" | "success" | "info""none"Semantic border colour
dir"ltr" | "rtl""ltr"Reading direction
openboolean—Controlled open state
defaultOpenbooleanfalseUncontrolled initial state
onOpenChange(open, event) => void—Fired when open state changes
modalbooleanfalseTrap focus and block page interaction
delaynumber—Hover-open delay (when the trigger is hoverable)

PopoverContent

PropTypeDefaultDescription
side"top" | "right" | "bottom" | "left""bottom"Which side of the trigger to position on
align"start" | "center" | "end""center"Alignment along the side axis
sideOffsetnumber8Distance in px from the trigger
alignOffsetnumber0Shift along the side axis
portalbooleantrueRender inside a portal
containerHTMLElement | nulldocument.bodyPortal target
size, rounded, intent—inheritedOverride the root's variant

PopoverHeader

PropTypeDefaultDescription
iconReactNode—Leading icon rendered beside the title
showClosebooleanfalseRender the built-in X close button

PopoverTrigger, PopoverClose

Render a <button>. Use render={<CustomElement />} to swap in a Button or any element. Standard Base UI render-prop pattern.

Sub-components

PopoverTitle, PopoverDescription, PopoverBody, PopoverFooter, PopoverBackdrop, PopoverArrow — all accept className and any HTML props.

Notes

  • Built on @base-ui/react/popover — the same headless primitive used by the design system for tooltips and menus.
  • Enter/exit animations use Base UI's data-[starting-style] and data-[ending-style] plus position-aware data-[side=*] attributes, so the popup "lifts off" from whichever side it opens on.
  • The arrow is drawn as a single rotated square — no SVG — so it inherits the border colour automatically when intent changes.

Command

Command palette / ⌘K menu — filterable, keyboard-driven action launcher with inline and modal modes, grouped items, descriptions, breadcrumbs, shortcuts, and footer key hints.

HoverCard

A floating card that appears when a trigger is hovered or focused. Use for lightweight previews — user profiles, link previews, citations, or footnote definitions. Built on Base UI's preview-card primitive.

On this page

PlaygroundInstallationUsageShowcaseWhen to use Popover vs. Tooltip vs. DropdownMenu vs. ModalAnatomySizeIntentRoundedPositioningArrowBackdrop & modal behaviourControlledClose button in headerAccessibilityRTLAPI ReferencePopover (root)PopoverContentPopoverHeaderPopoverTrigger, PopoverCloseSub-componentsNotes