Accordion
Progressively reveal supporting information in place.
disclosurelayout
Preview
Accordion preview
Live · keyboard ready
No. Manicat UI styles are CSS modules that read CSS variables.
Change a value in foundation.css and every component follows.
Set data-theme="dark" on the html element. Values are tuned, not inverted.
When to use
- FAQ sections where only one answer should be open at a time.
- Settings or help pages that group long content under short, scannable questions.
- Page-level FAQs that need larger type, via size="lg".
When not to use
- Use expandable-card for a single standalone disclosure such as a plan or order summary.
- Use tabs when sections are peer views that people switch between.
- Use onboarding-checklist when the rows are setup tasks to complete.
shadcn CLI
Also installs (1)
- manicat-foundation
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "accordion",
"type": "registry:ui",
"title": "Accordion",
"description": "Progressively reveal supporting information in place.",
"categories": [
"disclosure"
],
"dependencies": [
"@radix-ui/react-accordion",
"lucide-react",
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json"
],
"files": [
{
"path": "registry/components/accordion/accordion.tsx",
"type": "registry:component",
"target": "@components/manicat/accordion/accordion.tsx"
},
{
"path": "registry/components/accordion/accordion.module.css",
"type": "registry:component",
"target": "@components/manicat/accordion/accordion.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/accordion",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/accordion",
"markdown": "https://uiarc.dev/components/accordion/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 { Accordion } from "@/components/manicat/accordion/accordion";
export function AccordionExample() {
return (
<Accordion
defaultOpen={0}
items={[
{ title: "Do I need Tailwind?", content: "No. Manicat UI styles are CSS modules that read CSS variables." },
{ title: "Can I change the tokens?", content: "Change a value in foundation.css and every component follows." },
{ title: "What about dark mode?", content: "Set data-theme=\"dark\" on the html element. Values are tuned, not inverted." },
]}
/>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
FAQ One open at a time, with the first answer open by default.
FAQ
One open at a time, with the first answer open by default. preview
Live · keyboard ready
Yes. Your plan stays active until the end of the billing period.
Within 14 days of a purchase, no questions asked.
Teams of ten or more get 20% off. Contact us for a quote.
faq-one-open-at-a-time-with-the-first-answer-open-by-default-.tsxtsx
"use client";
import { Accordion } from "@/components/manicat/accordion/accordion";
export function AccordionFaqExample() {
return (
<div className="w-full max-w-lg">
<Accordion
defaultOpen={0}
items={[
{ title: "Can I cancel at any time?", content: "Yes. Your plan stays active until the end of the billing period." },
{ title: "Do you offer refunds?", content: "Within 14 days of a purchase, no questions asked." },
{ title: "Is there a team discount?", content: "Teams of ten or more get 20% off. Contact us for a quote." },
]}
/>
</div>
);
}
Keyboard interactions
| Keys | Action |
|---|---|
| Enter / Space | Toggles the focused row. |
| ArrowDown / ArrowUp | Moves focus between row triggers. |
| Home / End | Jumps to the first or last trigger. |
Accessibility
- Radix wires aria-expanded, aria-controls, and region labelling between each trigger and panel.
- Closed panels stay mounted but switch to visibility hidden once collapsed, so they leave the accessibility tree.
- Triggers sit inside heading elements; the chevron is aria-hidden.
Motion
- Panel height springs without overshoot while the answer slides down 6px out of a subtle blur; the chevron rotates on a snappy spring.
- A toggle mid-flight retargets from the current height instead of restarting.
- Reduced motion applies the same end states in one step.
Responsive behavior
- Rows fill their container width; the lg size caps answers at 62ch for readable line length.
- Below 520px the lg size drops to a 68px row and smaller answer text with tighter right padding.
- Hover color changes apply only on hover-capable fine pointers.
Performance
- Closed panels stay mounted and hidden, so every answer is in the DOM; keep very heavy content lazy inside the panel.
- Height springs through motion on the one row that changes, with no layout observers.
Notes for AI
- Use for FAQs and settings groups where only one section should be open. Use expandable-card for a single standalone disclosure and tabs when sections are peers.
- Content is plain data; pass rich ReactNode answers directly. Only single mode is supported.