Accordion
A stack of headings that each open a section in place, for long content people read one part of at a time, like an FAQ. Collapsible is the single version, for one show/hide.
Installation
Set up Camaleo once (Installation), then import what you need. It renders on the client.
import { Accordion, AccordionItem, AccordionTrigger, AccordionPanel, Collapsible, CollapsibleTrigger, CollapsiblePanel } from "@camaleo/react";Anatomy
AccordionTrigger puts its button inside a heading, so the sections show up in a screen reader's list of headings. It is an h3; set level to fit the page's outline, such as level={4} under a card title. The panel animates its height; the padding sits on an inner element so nothing jumps. Collapsible has the same trigger and panel without the heading.
Examples
Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above. Open a section, then try Tab and Enter.
Several open
With multiple, opening a section leaves the others open. Use it when people read sections side by side; defaultValue opens the ones most people need.
Sections of a form
Split long settings into sections people fill one at a time. keepMounted keeps the fields of closed sections in the form, so what people typed is still sent.
Expand all
Click the button. With value and onValueChange you control which sections are open, so one button can open or close them all.
Found by page search
Press Ctrl+F and search for "invoice". With hiddenUntilFound, closed panels stay in the page and open when the browser finds a match in them.
Payouts open once your bank account is verified. We usually finish within 2 business days.
Disabled, with a reason
A disabled header is skipped by Tab, so keep the reason in visible text next to it: say why it's closed and when it opens.
Export orders
Advanced options
Collapsible hides options most people never need, so the form stays short and the defaults do the work.
- Unlimited products
- Up to 3 stores
- Abandoned cart emails
Show more
Click it. The extra items appear right above the button, where the reader stopped, and the label says what it will do next.
In context
These are whole pieces of UI you can copy, in the skin you picked.
Help center
Answers to the questions we get most.
Order summary
- Subtotal
- $186.40
- Shipping
- Free
- Total
- $186.40
Guidelines
A question or a topic tells people whether to open it, and reads well in a list of headings.
"More information" and "Other" make people open every section to find anything.
| Plan | Price | Orders |
|---|---|---|
| Basic | $9 per month | Up to 100 orders |
| Pro | $29 per month | Unlimited orders |
Prices and limits in one table can be read at a glance.
With one plan open at a time, people have to remember the other one's price.
Props
defaultValue prop instead.value prop instead.keepMounted prop and uses hidden="until-found"
to hide the element without removing it from the DOM.hiddenUntilFound is used.AccordionItem takes a value and disabled. AccordionTrigger takes level (1 to 6, default 3) for the heading around it. AccordionTrigger and AccordionPanel take the props of their element.
Collapsible opens and closes one panel:
defaultOpen prop instead.open prop instead.Styling hooks
Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the accordion itself.
Attributes
Tokens it reads
Color
Shape & size
Type & motion
This component only
/* a plus that turns into a minus, only on the help page */
.help [data-slot="accordion"] {
--cml-accordion-chevron: none;
--cml-accordion-plus: inline-block;
}Accessibility
- Each header is a button inside a heading (h3, or the level you set), with aria-expanded. While open, aria-controls points at the panel, a region named by its header.
- There are no arrow keys between headers: the WAI-ARIA pattern dropped them, and Tab already moves from one header to the next.
- Content in closed panels leaves the page, so Tab and page search skip it, unless you set keepMounted or hiddenUntilFound.
- A disabled header is a disabled button: Tab skips it, so its reason must be visible text.