Popover Morph

Popover that grows out of its trigger and folds back.

Installation

pnpm dlx shadcn@latest add @paneui/popover-morph

Usage

Composition

Examples

Placement

Controlled Form

Use when the panel should close after a submit.

Motion

The surface grows from a copy of the trigger across the 8px gap over 450ms, and the content settles in 150ms later. Closing folds it back in 300ms. With reduced motion it only cross-fades, in 150ms.

Keyboard

Enter or Space opens it, focus moves into the panel, Escape or an outside press closes it and returns focus to the trigger.

API Reference

Built on the Popover primitive. Only the props this library adds or changes are listed; everything else passes through.

MorphPopover

Popover.Root, re-exported unchanged. Also accepts every prop of Popover.Root.

MorphPopoverTrigger

A raised trigger (32px, rounded-lg). Also accepts every prop of Popover.Trigger.

MorphPopoverContent

Portal, positioner and popup, anchored to the trigger like Popover (8px side offset) with the standard popover surface (rounded-2xl, bg-popover, shadow-surface). A 288px panel by default. Also accepts every prop of Popover.Popup.

side= "bottom"
"top" | "bottom"
Which side of the trigger the panel opens on (and grows towards).
sideOffset= 8
number
Gap between trigger and panel in px, as in Popover.
collisionPadding= 8
number
Viewport margin kept when the panel flips or shifts.
align= "center"
"start" | "center" | "end"
Which trigger edge the panel lines up with, as in Popover.
triggerRadius= "var(--radius-lg)"
string
Corner radius (CSS length) of the trigger shape the panel starts from. The default matches MorphPopoverTrigger's rounded-lg; change it only if you reshape the trigger.
PropTypeDefaultDescription
side"top" | "bottom""bottom"Which side of the trigger the panel opens on (and grows towards).
sideOffsetnumber8Gap between trigger and panel in px, as in Popover.
collisionPaddingnumber8Viewport margin kept when the panel flips or shifts.
align"start" | "center" | "end""center"Which trigger edge the panel lines up with, as in Popover.
triggerRadiusstring"var(--radius-lg)"Corner radius (CSS length) of the trigger shape the panel starts from. The default matches MorphPopoverTrigger's rounded-lg; change it only if you reshape the trigger.
data-side / data-align
The resolved placement (on the positioner and popup), used to work out where the morph starts.
data-starting-style / data-ending-style
Present while the panel opens or closes.
Data attributeDescription
data-side / data-alignThe resolved placement (on the positioner and popup), used to work out where the morph starts.
data-starting-style / data-ending-stylePresent while the panel opens or closes.

MorphPopoverHeader

Title and description stack; leaves room on the right for the close button. Also accepts every prop of div.

MorphPopoverTitle

Also accepts every prop of Popover.Title.

MorphPopoverDescription

Also accepts every prop of Popover.Description.

MorphPopoverFooter

Right-aligned row of actions. Also accepts every prop of div.

MorphPopoverClose

Unstyled close part; pass render to turn any element (e.g. a Button) into a close control. Also accepts every prop of Popover.Close.

MorphPopoverCloseButton

Round × button pinned to the panel's top-right corner, labelled Close. Also accepts every prop of Popover.Close.