# Accordion

> Collapsible rows whose panels open from their measured height on the UI thread, with content that drops into place and a chevron that turns on the same spring.

- Type: Component (data)
- Access: Free, open source (MIT)
- Page: https://goodui.dev/native/components/accordion
- Markdown: https://goodui.dev/native/components/accordion.md
- Registry item: https://goodui.dev/native/r/accordion.json
- Dependencies: react-native-reanimated, react-native-svg
- Keywords: react native accordion, expo accordion, collapsible list, expandable rows, faq list, disclosure group, animated height react native

## When to use

- FAQs, order details, plan comparisons and settings groups where most rows stay closed.
- Long forms split into sections that people open one at a time (type="single").
- Receipts and breakdowns where a summary row hides line items.

## When not to use

- Switching between two to five views of the same data: use segmented-control.
- A short choice list or picker: use a bottom-sheet with rows.
- Content everyone needs to read: show it, do not hide it behind a tap.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add https://goodui.dev/native/r/accordion.json
npx expo install --fix
```

The component lands in `components/goodui-native/accordion/` and imports the foundation from `components/goodui-native/foundation/` with relative paths.

## Usage

```tsx
import { Accordion } from "@/components/goodui-native/accordion/accordion";
import { Text } from "@/components/goodui-native/foundation/text";

export function Faq() {
  return (
    <Accordion
      accessibilityLabel="Questions"
      defaultValue={["refund"]}
      items={[
        {
          value: "refund",
          title: "Can I get a refund?",
          content: <Text tone="secondary">Yes, within 14 days of purchase, no questions asked.</Text>,
        },
        {
          value: "seats",
          title: "How do seats work?",
          subtitle: "Teams plan",
          content: <Text tone="secondary">Each seat is one person. Add or remove seats at any time.</Text>,
        },
      ]}
    />
  );
}
```

## Examples

### Controlled, several open at once, card per row

```tsx
const [open, setOpen] = useState<string[]>([]);

<Accordion
  type="multiple"
  variant="inset"
  value={open}
  onValueChange={setOpen}
  items={orders.map((o) => ({
    value: o.id,
    title: o.title,
    detail: o.total,
    content: <OrderLines order={o} />,
  }))}
/>
```

### A section that must stay open

```tsx
<Accordion type="single" collapsible={false} defaultValue={["shipping"]} items={checkoutSteps} />
```

## API reference

### Accordion

`import { Accordion } from "@/components/goodui-native/accordion/accordion";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` (required) | `AccordionItem[]` | – | Rows, top to bottom. |
| `type` | `"single" \| "multiple"` | `"single"` | `single` keeps one row open at a time; `multiple` lets rows open independently. |
| `value` | `string[]` | – | Open row values (controlled). Pair with `onValueChange`. |
| `defaultValue` | `string[]` | `[]` | Open row values on first render (uncontrolled). |
| `onValueChange` | `(value: string[]) => void` | – | Called with every open row value after a row opens or closes. |
| `collapsible` | `boolean` | `true` | With `type="single"`, tapping the open row closes it. Default `true`. |
| `variant` | `"grouped" \| "inset"` | `"grouped"` | `grouped` puts rows on one rounded surface with hairlines; `inset` gives every row its own card. |
| `size` | `"sm" \| "md"` | `"md"` | `md` rows are 52 pt with body titles; `sm` rows are 44 pt with subhead titles. |
| `haptic` | `HapticName \| false` | `"select"` | Haptic when a row opens or closes. `false` turns it off. |
| `accessibilityLabel` | `string` | – | Label for the whole group, read before the first row. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- Each header is a button with accessibilityState expanded and disabled.
- The accessibility label joins title, subtitle and detail.
- A closed panel is hidden from screen readers and, after it closes, unmounted, so it is never reachable by keyboard on the web.
- Titles and subtitles wrap to two lines, which keeps rows readable at large font sizes.
- On the web each header is named by its visible title, subtitle and detail, and reports aria-expanded.

## Motion

- The panel's height is measured from its content and animated on the UI thread with the smooth spring.
- Content drops 8 pt into place and fades in on open; it fades out quickly on close.
- The chevron rotates 180 degrees on the same spring, so it lands with the panel.
- Content that changes height while open eases to its new height.
- Reduced motion: the height changes at once, the chevron flips without turning, and the content only fades.

## Haptics

- select when a row opens or closes (configurable with the haptic prop)

## Performance

- Height, offset, opacity and rotation run on the UI thread; React renders only when a row opens or closes.
- Panels mount on open and unmount after they close, so a long list of closed rows renders headers only.

## Notes for AI

- Pass rows through items; each item needs a unique value and its panel in content.
- value is always a string array, also with type="single".
- Use variant="grouped" inside a screen's list and variant="inset" when rows should read as separate cards.
- Do not wrap the accordion in another card: grouped already draws its own surface.

## Related

- [Segmented control](https://goodui.dev/native/components/segmented-control.md): Two to five views of the same thing with an elastic highlight that stretches toward the new segment, can be dragged, and ticks at every boundary. Includes a billing toggle.
- [Bottom sheet](https://goodui.dev/native/components/bottom-sheet.md): A sheet that rests at detents, follows the finger 1:1, settles with velocity and hands drags off to its scroll view.
- [Skeleton](https://goodui.dev/native/components/skeleton.md): Loading placeholders whose shimmer is one light passing diagonally over the whole screen, plus presets and a Swap that eases from the skeleton's height to the content's while it cross-fades.

## Guidance for AI tools

Accordion: Collapsible rows whose panels open from their measured height on the UI thread, with content that drops into place and a chevron that turns on the same spring. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
