Skip to content

Accordion

Stacks sections that fold open and shut. Use it to keep long content collapsed to its headings so only what is needed is expanded.

tsx
import { Accordion, AccordionItem } from 'neba';

<Accordion defaultValue={['billing']}>
  <AccordionItem value="billing" title="How does billing work?" subtitle="Plans and invoices">
    You are charged on the first of each month.
  </AccordionItem>
  <AccordionItem value="regions" title="Where do builds run?">
    In the region closest to the default branch.
  </AccordionItem>
</Accordion>;

Props

Accordion

PropTypeDefaultDescription
variantshared'solid' | 'outline' | 'text''outline'Weight of the surface: filled, hairline, or none
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'The sheet's radius and each section's padding: the same thing size means on Box
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
densityshared'default' | 'compact''default'Padding only: never the height, never the type scale
elevationshared0 | 1 | 2 | 30Drop shadow depth. 0 means no shadow at all
multiplebooleanfalseWhether more than one section may be open. Off by default: closing the last as you open the next is the whole difference between an accordion and a stack of collapsibles
value(string | number)[]Which sections are open, for a controlled accordion
defaultValue(string | number)[]Which start open
onValueChange(value: (string | number)[]) => voidCalled when the open set changes
dividersbooleantrueSeparates the sections with a hairline rather than space. The opposite default from List: an accordion of tiles is a stack of cards, not one thing
headingLevel1 | 2 | 3 | 4 | 5 | 63Which heading every section's header is in the page outline. 3 under an h2, 4 under an h3
disabledbooleanfalseUnavailable. Every section stops answering
hiddenUntilFoundbooleanfalseKeeps closed panels in the DOM so the browser's own page search can find and open them. Overrides keepMounted
keepMountedbooleanfalseKeeps closed panels in the DOM. For content that is expensive to build, or form state that should survive being folded away
childrenReactNodeThe AccordionItems

value with onValueChange makes it controlled; defaultValue makes it uncontrolled. The value is an array of the open items' values.

AccordionItem

PropTypeDefaultDescription
valuestring | numberIdentifies the section to value / defaultValue. Base UI generates one when it is left out
titleReactNodeThe heading on the fold
subtitleReactNodeA second line under the title
startIconReactNodeContent before the title
actionReactNodeA control pinned to the end of the header, outside the folding button: a button inside a button is markup the browser rewrites
linesnumberCuts the title and the subtitle off after this many lines. Unset, both wrap
disabledbooleanfalseThis section stops folding; the rest keep working
childrenReactNodeThe body

Examples

variant

The sheet is never filled with colour. Use text inside a Card: the card is already a sheet, so the borders do not double up.

multiple · dividers · action

multiple is off by default, so opening one section closes the one that was open. Turn it on when the sections are a checklist rather than mutually exclusive answers.

dividers rules between the sections, binding them into one block. action is a control slot outside the folding button, so a header can carry a switch and still fold when pressed.

size

headingLevel · lines

Every section's header is a real heading, so it belongs in the page outline at the right depth: headingLevel sets it for the whole stack — 3 under an <h2>, 4 under an <h3>. It lives on Accordion rather than on a section because the sections are siblings, and a run of headings at different levels is an outline that lies.

Pass plain text as title. A heading element passed in would land inside the one the header already is.

lines on a section cuts the title and the subtitle off after that many lines. Unset, both wrap: an FAQ's title is a sentence, and an ellipsis there loses the question.

tsx
<Accordion headingLevel={2}>
  <AccordionItem lines={2} title="What happens to my data when I close my account?">

  </AccordionItem>
</Accordion>

hiddenUntilFound and keepMounted

hiddenUntilFound keeps closed panels in the DOM so the browser's find-on-page can locate and open them: worth turning on for an FAQ. keepMounted keeps a closed panel's React tree alive.

Accessibility

  • The header button and its panel are wired together with aria-controls and aria-expanded.
  • Each header is a real heading element, at headingLevel (3 by default), so the sections are in the document outline. Pass plain text as title: a heading passed in would be nested inside that one.
  • The panel opens by animating its height; the content does not shift inside the panel.

Released under the MIT License