Easy Shadcn
Components

Popover

Popover provides one rich floating-content API with two interaction adapters. The default click mode uses shadcn Popover for editable or interactive content. interaction="hover" uses shadcn Hover Card / Base UI Preview Card for supplemental link previews opened by hover or focus. Both modes keep the same trigger, content slots, positioning, and open-state vocabulary.

Preview profile

Installation

With the @easy-shadcn namespace configured:

pnpm dlx shadcn@latest add @easy-shadcn/popover

Or install via the full URL:

pnpm dlx shadcn@latest add https://easy-shadcn.vercel.app/r/popover.json

The shadcn popover and hover-card primitives are installed automatically.

Click mode

Click mode is the default and preserves the original Popover API. Use it for forms, controls, and other content the user deliberately opens and interacts with.

<Popover
  content="Set the dimensions for the layer."
  description="Adjust width and height."
  footer={<Button size="sm">Save</Button>}
  title="Dimensions"
>
  <Button variant="outline">Open</Button>
</Popover>

Hover and focus mode

Set interaction="hover" for a preview of a link destination. The Preview Card primitive owns hover intent, focus opening, safe pointer movement between the link and popup, dismissal, and open/close delays.

<Popover
  closeDelay={200}
  content="Open the profile to see current projects."
  delay={300}
  description="easy-shadcn maintainer"
  interaction="hover"
  title="Simon Wong"
>
  <a href="/profile">Simon Wong</a>
</Popover>

Hover previews are supplemental. Do not put unique or essential information in them: touch and screen-reader users cannot rely on hover-card content. The link destination must remain useful on its own.

Props

Shared

PropTypeDefaultDescription
childrenReactElement-Single trigger element. Click mode commonly uses a button; hover mode should use a link.
contentReactNode-Popup body in data-slot="popover-body".
titleReactNode-Optional header title.
descriptionReactNode-Optional header description.
footerReactNode-Optional footer content.
side"top" | "bottom" | "left" | "right" | "inline-start" | "inline-end""bottom"Popup side.
sideOffsetnumber4Gap from the trigger.
align"start" | "center" | "end""center"Alignment along the chosen side.
alignOffsetnumbermode defaultOffset along the alignment axis. Click defaults to 0; hover defaults to 4.
openboolean-Controlled open state.
defaultOpenbooleanfalseInitial uncontrolled state.
onOpenChangeprimitive callback-Exact callback for the selected primitive adapter.

Every slot accepts a class override: headerClassName, titleClassName, descriptionClassName, contentClassName for the body, and footerClassName. Remaining safe popup props such as className, non-owned data-*, ARIA, and event handlers are forwarded to data-slot="popover-content". Both adapters reject and runtime-strip popup render, raw HTML, and data-slot because the Compose layer owns the popup element and slot tree.

Interaction discriminator

ModeExtra propsExcluded props
interaction="click" or omitteddisableddelay, closeDelay
interaction="hover"delay (600 ms), closeDelay (300 ms)disabled

The TypeScript union enforces this boundary. Changing a click popover to a hover preview keeps all shared props and adds only the interaction discriminator.

Slot structure

Both adapters expose the same optional regions in order:

  • Header: title and description inside data-slot="popover-header".
  • Body: content inside data-slot="popover-body".
  • Footer: footer inside data-slot="popover-footer".

The trigger uses data-slot="popover-trigger"; the popup uses data-slot="popover-content". No extra trigger wrapper is added.

The trigger element remains caller-owned: its children, id, handlers, navigation, and custom attributes are passed to the selected primitive without recursive sanitization. Use the primitive directly when the popup element or child order must change.

Notes

  • children must forward props and a ref. Hover mode should receive an anchor whose destination contains the complete information.
  • Click titles and descriptions use the Popover dialog semantics. Hover titles and descriptions are ordinary preview content rather than dialog labels.
  • null, undefined, and booleans omit a slot; valid falsy nodes such as 0 and "" render.
  • Use Tooltip for concise descriptive text. Use the underlying primitives for custom arrows, modal backdrops, payload-driven shared preview cards, custom trigger handles, or heterogeneous layouts.

On this page