# Accordion
Disclosure rows that open in place.
- Group: Navigation
- Import: `import { Accordion } from '@misoto22/folio'`
- Page: https://ui.misoto22.com/components/accordion/
- Related: tabs
## When to reach for it
The marker is a plus, not a chevron: a plus says “this opens”, a chevron says “there is more below”.
## Anatomy
- **Row** (required) — AccordionItem — one hairline-ruled record, keyed by the value Radix opens and closes it by. The set is the root above it: type="single" with collapsible for an FAQ, type="multiple" for a stack of settings.
- **Heading** (required) — Radix’s Accordion.Header, which is an
and takes no level prop. Every row therefore adds an h3 to the document outline, wherever the accordion happens to sit.
- **Trigger** (required) — The full-width button inside that heading: title against the start edge, marker against the end, py-4. It is also what names the open panel.
- **Marker** (required) — A 16px plus, aria-hidden, rotating 45° into a minus when the row opens. The state it draws is carried for everyone else by aria-expanded on the trigger.
- **Panel** — Radix’s Content — a role="region" labelled by its trigger, mounted only while open, overflow-hidden so its measured height can animate, with pb-4 pe-8 inside so the text stops short of the marker’s column. It carries data-folio-animated, so the open and close are dropped outright for a reader who asked for less motion.
## Best practices
### Do
- Pass collapsible alongside type="single": without it there is no empty value to return to, so the first row the reader opens is a row they can never close again.
- Key each item by something stable rather than by its position — Radix tracks the open row by value, so re-ordering or filtering the list leaves whatever now sits in that slot standing open.
- Write the title as the whole question: it is the accessible name of the panel as well as of the trigger, so a row titled “More” opens a region called “More”.
- Reach for type="multiple" when two rows have to be read against each other — single closes the one the reader was holding in order to open the one they wanted to compare it with.
### Don’t
- A closed row’s content is not in the DOM, so an FAQ built out of these is invisible to find-in-page and prints as a list of questions — anything that has to be searchable or printable belongs in the page.
- The trigger is fixed at h3 by Radix’s header, so an accordion under an
lists its rows as that heading’s siblings and the outline goes flat exactly where it should have nested.
- The panel is overflow-hidden — that is what lets the open height animate — so anything inside that must escape the row’s box has to portal out of it; a menu that renders in place is cut off at the row’s edge.
## Keyboard
- Tab — Moves between rows.
- Enter / Space — Opens or closes the focused row.
## Accordion
Re-export of `AccordionPrimitive.Root`.
Radix root, re-exported. Pass `type="single" collapsible` for an FAQ and `type="multiple"` for a settings stack; Radix's own discriminated union then types `value` correctly for each.
## AccordionItem
One disclosure row: a hairline-ruled trigger and its panel. The marker is a plus that rotates into a minus, not a chevron. A chevron says "there is more below"; a plus says "this opens" — and in a stack of rows the difference decides whether the reader expects navigation or expansion. The panel animates on Radix's own `--radix-accordion-content-height`, so it opens to its real height without measuring anything at the call site.
### Props
- `title` (required) — `ReactNode`. The row's summary — what the reader clicks. Named `title` rather than inherited from the DOM attribute of the same name, which is a tooltip.
- `children` (required) — `ReactNode`.
Also accepts: `Omit, 'children' | 'title'>`.
## Example — default
```tsx
import { Accordion, AccordionItem } from '@misoto22/folio'
pnpm add @misoto22/folio, then import the stylesheet once
at your app root.
No. The compiled stylesheet is self-contained. If you already compile Tailwind, import the token
layers instead and skip the second copy of the utilities.
None. Components that navigate take asChild, so you hand
them your own Link.
```
## Example — a settings stack
```tsx
import { Accordion, AccordionItem, Field, Input, Switch } from '@misoto22/folio'
```
## Example — the whole question
```tsx
import { Accordion, AccordionItem, Text } from '@misoto22/folio'
Opens a region called More
Invoices are issued on the first working day of the month.
Payment is due 30 days after the issue date.
Opens a region called by its question
Invoices are issued on the first working day of the month.
Payment is due 30 days after the issue date.