Expandable card
Give a dense card more room when requested.
disclosurelayout
Preview
Expandable card preview
Live · keyboard ready
The card grows into a larger view in place, so the page around it never moves.
When to use
- A single summary card with optional details, like a plan, order, or log entry.
- Cards whose summary line updates and should roll changed words in place.
When not to use
- Use accordion for a list of mutually exclusive sections.
- Use card when there is nothing to reveal.
- Use card-stack for browsing several cards in one spot.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "expandable-card",
"type": "registry:ui",
"title": "Expandable card",
"description": "Give a dense card more room when requested.",
"categories": [
"disclosure"
],
"dependencies": [
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/expandable-card/expandable-card.tsx",
"type": "registry:component",
"target": "@components/manicat/expandable-card/expandable-card.tsx"
},
{
"path": "registry/components/expandable-card/expandable-card.module.css",
"type": "registry:component",
"target": "@components/manicat/expandable-card/expandable-card.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/expandable-card",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/expandable-card",
"markdown": "https://uiarc.dev/components/expandable-card/markdown",
"tags": [
"disclosure",
"layout"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { ExpandableCard } from "@/components/manicat/expandable-card/expandable-card";
export function ExpandableCardExample() {
return (
<ExpandableCard title="Quarterly plan" description="Three tracks, reviewed every Friday.">
<p className="text-sm text-(color:--text-muted)">
The card grows into a larger view in place, so the page around it never moves.
</p>
</ExpandableCard>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Plan details The card opens into a larger view in place, so the page around it never moves.
Plan details
The card opens into a larger view in place, so the page around it never moves. preview
Live · keyboard ready
- Design system: tokens and dark mode
- Docs: examples for every component
- Registry: framework ports
plan-details-the-card-opens-into-a-larger-view-in-place-so-the-page-around-it-never-moves-.tsxtsx
"use client";
import { ExpandableCard } from "@/components/manicat/expandable-card/expandable-card";
export function ExpandableCardPlanExample() {
return (
<div className="w-full max-w-md">
<ExpandableCard title="Quarterly plan" description="Three tracks, reviewed every Friday.">
<ul className="grid gap-2 text-sm text-(color:--text-muted)">
<li>Design system: tokens and dark mode</li>
<li>Docs: examples for every component</li>
<li>Registry: framework ports</li>
</ul>
</ExpandableCard>
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space | Toggles the card from its header button. |
| Escape | Closes the card while focus is inside it and returns focus to the header. |
Accessibility
- The header is a native button with aria-expanded and aria-controls pointing at the panel.
- The rolling description keeps a screen-reader-only copy of the full text; animated words are aria-hidden.
- The collapsed panel is inert, so its content is not reachable by keyboard or screen readers while closed.
Motion
- Open and close are one morph: width and height move together on the smooth spring, which never overshoots, and the arrow turns on the same spring.
- Details fade in once the box has made room and fade out before it shrinks. They are laid out at their open width throughout, so text never reflows or stretches.
- Clicking again mid-animation reverses from the current size with its velocity. Changed words in the description rise in; unchanged words hold still.
- Reduced motion applies end states instantly and swaps the description without animation.
Responsive behavior
- Without width caps the card fills its container. With width and expandedWidth it stays centered and grows sideways to the open cap, never wider than its container, so on a phone it simply uses the full width.
- The whole header is the toggle with a 64px minimum height, so it is an easy touch target.
Performance
- The panel stays mounted but inert at zero height when collapsed, so a second click mid-animation reverses smoothly.
- Width and height are animated for real on one spring rather than scaled, so text and corners never stretch; keep the details short.
- The description splits into one span per word for the roll; keep it to a short line.
Notes for AI
- Use for a single standalone expandable summary such as a plan, order, or log entry. Use accordion for a list of mutually exclusive sections.
- State is internal; there is no controlled prop.