Expandable
A card that morphs into a full view, App Store style. Shared elements — media, title, subtitle — fly to their new place while the rest fades in.
Overlays
Playground
Tweak the props, the preview and the code follow.
Props
0.12
0.5
330
<Expandable transition={{ type: "spring", bounce: 0.12, duration: 0.5 }}>
<ExpandableTrigger>
<ExpandableMedia>…</ExpandableMedia>
<ExpandableTitle>Spring tuning</ExpandableTitle>
<ExpandableSubtitle>Click to expand</ExpandableSubtitle>
</ExpandableTrigger>
<ExpandableContent>
<ExpandableClose />
<ExpandableMedia>…</ExpandableMedia>
<ExpandableTitle>Spring tuning</ExpandableTitle>
<ExpandableSubtitle>…</ExpandableSubtitle>
<ExpandableDescription>Only rendered when open.</ExpandableDescription>
</ExpandableContent>
</Expandable>Installation
npx @plumsydev/plum-ui add expandableUsage
import {
Expandable,
ExpandableClose,
ExpandableContent,
ExpandableDescription,
ExpandableMedia,
ExpandableSubtitle,
ExpandableTitle,
ExpandableTrigger,
} from "@/components/ui/expandable"<Expandable>
<ExpandableTrigger>
<ExpandableMedia>…</ExpandableMedia>
<ExpandableTitle>acme-storefront</ExpandableTitle>
<ExpandableSubtitle>Next.js</ExpandableSubtitle>
</ExpandableTrigger>
<ExpandableContent>
<ExpandableClose />
<ExpandableMedia>…</ExpandableMedia>
<ExpandableTitle>acme-storefront</ExpandableTitle>
<ExpandableSubtitle>Next.js</ExpandableSubtitle>
<ExpandableDescription>Only rendered when open.</ExpandableDescription>
</ExpandableContent>
</Expandable>Examples
Gallery
Each card in a grid expands on its own.
Profile
Any shape works: a pill morphs into a profile card.
API Reference
Expandable
| Prop | Type | Default |
|---|---|---|
openControlled open state. | boolean | — |
defaultOpenInitial state when uncontrolled. | boolean | false |
onOpenChangeCalled on open and close. | (open: boolean) => void | — |
transitionMotion transition used for the morph. | Transition | { type: "spring", bounce: 0.12, duration: 0.5 } |
ExpandableMedia / Title / Subtitle
Shared elements. Render them in both the trigger and the content: they morph between the two.
ExpandableDescription
Content that only exists in the open view. Fades in after the morph.
Notes
- The open view is a real dialog:
role="dialog",aria-modal, labelled by its title, Esc to close, focus kept inside and returned to the card. - Titles and subtitles animate their position only, so text never stretches mid-flight.