# Accordion

> Stacked sections that open and close.

Component · Foundations · Halo kit · [Live page](https://ui.twentyfirst.media/halo/components/Accordion/)

Stacked sections that open and close. One section at a time by default, or several with `multiple`.

- `cards` (default) shows each section as a card; `flush` uses hairlines, for use inside a panel.
- Keyboard: Tab reaches each header, ↑/↓ move between headers, Home/End jump, Enter or Space toggles.
- Headers are buttons with `aria-expanded`; panels are regions labelled by their header.

## Example

```tsx
import * as React from "react";
import { Accordion, Badge, Panel } from "@twentyfirstmedia/halo";

export default function Preview() {
  return (
    <div
      className="tf-grid"
      style={{ "--cols": "1fr 1fr", gap: 24, alignItems: "start" } as React.CSSProperties}
    >
      <Accordion
        defaultValue={["billing"]}
        items={[
          {
            id: "billing",
            title: "How does billing work?",
            content:
              "You pay per seat and month. Seats added mid-cycle are prorated to the next invoice.",
          },
          {
            id: "export",
            title: "Can I export my data?",
            content: "Yes. Every table exports to CSV, and the API returns the same fields.",
          },
          {
            id: "sso",
            title: "Do you support single sign-on?",
            meta: <Badge tone="info">Team plan</Badge>,
            content: "SAML and OIDC are included from the Team plan up.",
          },
          { id: "old", title: "Legacy importer", disabled: true, content: "" },
        ]}
      />
      <Panel title="Settings">
        <Accordion
          variant="flush"
          multiple
          defaultValue={["n", "p"]}
          items={[
            {
              id: "n",
              icon: "bell",
              title: "Notifications",
              content: "Approvals and overdue invoices reach you by mail and push.",
            },
            {
              id: "p",
              icon: "lock",
              title: "Privacy",
              content: "Workspace data stays in the EU region.",
            },
            {
              id: "a",
              icon: "code",
              title: "API access",
              content: "Two active keys. Rotate them from Developer settings.",
            },
          ]}
        />
      </Panel>
    </div>
  );
}
```

## Props

### Accordion

| Prop | Type | Notes |
| --- | --- | --- |
| `items` | `AccordionItem[]` | Required |
| `multiple?` | `boolean` | Several sections open at once (default: one at a time). |
| `value?` | `string[]` | Open section ids (controlled). |
| `defaultValue?` | `string[]` |  |
| `onChange?` | `(open: string[]) => void` |  |
| `variant?` | `"cards" \| "flush"` | `cards`: each section is a card; `flush`: hairlines only (inside a panel). |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Badge

| Prop | Type | Notes |
| --- | --- | --- |
| `tone?` | `Tone` |  |
| `dot?` | `boolean` |  |
| `live?` | `boolean` |  |
| `children?` | `ReactNode` |  |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |

### Panel

| Prop | Type | Notes |
| --- | --- | --- |
| `side?` | `boolean` |  |
| `title?` | `string` |  |
| `subtitle?` | `string` |  |
| `action?` | `ReactNode` |  |
| `children?` | `ReactNode` |  |
| `surface?` | `Surface` | `"glass"`: translucent glass over what is behind (maps, 3D, video, photos); `"solid"` opts out inside a glass `UIProvider`. |
| `className?` | `string` | Extra class on the root element. |
| `style?` | `CSSProperties` | Inline style on the root element. |
