A list where each item reveals an inline Elevated panel on click — nesting the Surface system in-page instead of in an overlay. Multiple items can stay open at once.
pnpm dlx shadcn@latest add https://matos-ui.com/r/expandable-list.jsonimport {
ExpandableList,
ExpandableListItem
} from '@/components/matos-ui/expandable-list'<ExpandableList defaultOpenValues={['billing']}>
<ExpandableListItem value="billing" title="How does billing work?">
You're billed monthly based on active seats.
</ExpandableListItem>
<ExpandableListItem value="export" title="Can I export my data?">
Yes — every workspace can export a full JSON snapshot.
</ExpandableListItem>
</ExpandableList>Elevated of its own. The panel
revealed on expand is Elevated offset={1} relative to the list, so it
reads a step above it — the same outer/inner relationship the
Elevated primitive uses everywhere else,
just nested inline instead of in a portal.spring.moderate — the tier the
Motion Tokens reserve for panels that need
to settle precisely.height: "auto" never
tweens cleanly). Instead the item wrapper has Framer Motion's layout
prop, and only the panel's opacity/position animate — Framer measures the
before/after box and turns that into a smooth resize on its own.prefers-reduced-motion drops the layout animation and the panel's
spatial offset; only the opacity fade remains.| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | ExpandableListItem children. |
defaultOpenValues | string[] | [] | Item values expanded on mount. |
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Unique identifier for the item. |
title | ReactNode | — | Trigger row content. |
children | ReactNode | — | Content revealed inside the Elevated panel. |
aria-expanded and aria-controls; the revealed panel
is a labelled role="region".Install Matos UI
Choose a package manager and copy one command for every component.