# Accordion

A stacked list of `Collapsible` items with coordinated open/close behaviour. By default only one item can be open at a time; pass `multiple` to allow several open simultaneously.

For a single standalone expandable section, use `@xsolla/xui-b2b-collapsible`.

## Installation

```bash
npm install @xsolla/xui-b2b-accordion
```

`@xsolla/xui-b2b-collapsible` is a peer dependency and is installed automatically.

## Imports

```tsx
import {
  Accordion,
  type AccordionItem,
  type AccordionProps,
} from "@xsolla/xui-b2b-accordion";
```

## Quick start

```tsx
import { Accordion, type AccordionItem } from "@xsolla/xui-b2b-accordion";

const items: AccordionItem[] = [
  {
    key: "what",
    title: "What is Xsolla?",
    content: <p>Global video game commerce.</p>,
  },
  {
    key: "sdk",
    title: "How do I integrate the SDK?",
    content: <p>Follow the integration guide.</p>,
  },
];

<Accordion items={items} defaultOpenKeys={["what"]} />;
```

## API Reference

### `<Accordion>`

| Prop              | Type                       | Default | Description                                                                                                   |
| ----------------- | -------------------------- | ------- | ------------------------------------------------------------------------------------------------------------- |
| `testID`          | `string`                   | —       | Test ID for testing frameworks. On web this renders as `data-testid`; on React Native it renders as `testID`. |
| `items`           | `AccordionItem[]`          | —       | Required. Array of item definitions.                                                                          |
| `multiple`        | `boolean`                  | `false` | Allow more than one item open simultaneously.                                                                 |
| `defaultOpenKeys` | `string[]`                 | `[]`    | Keys open on first render (uncontrolled).                                                                     |
| `openKeys`        | `string[]`                 | —       | Controlled open keys.                                                                                         |
| `onOpenChange`    | `(keys: string[]) => void` | —       | Called when open keys change.                                                                                 |
| `className`       | `string`                   | —       | CSS class applied to the root wrapper.                                                                        |

Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).

### `AccordionItem`

| Field      | Type        | Description                                                                                                                                                                  |
| ---------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `key`      | `string`    | Required. Unique identifier used for open/close tracking.                                                                                                                    |
| `title`    | `ReactNode` | Required. Title text or node in the trigger row.                                                                                                                             |
| `content`  | `ReactNode` | Required. Body content shown when expanded.                                                                                                                                  |
| `caption`  | `ReactNode` | Secondary text below the title.                                                                                                                                              |
| `icon`     | `ReactNode` | Optional 32×32 left slot. Wrap with `IconWrapper`, or pass a `Checkbox` for selection-style accordions. Click events on this slot are stopped before they reach the trigger. |
| `trailing` | `ReactNode` | Content to the right of the text, before the chevron (e.g. `Status`).                                                                                                        |

## Examples

### Setup guide pattern

```tsx
import { Accordion, type AccordionItem } from "@xsolla/xui-b2b-accordion";
import { Status } from "@xsolla/xui-status";

const items: AccordionItem[] = [
  {
    key: "template",
    title: "Create and review the template of your game store page",
    trailing: (
      <Status palette="success" size="md" labelType="dot-color">
        Done
      </Status>
    ),
    content: <p>Content here.</p>,
  },
  {
    key: "tips",
    title: "See tips and tricks for your game store",
    trailing: (
      <Status palette="warning" size="md" labelType="dot-color">
        In progress
      </Status>
    ),
    content: <p>Content here.</p>,
  },
  {
    key: "keys",
    title: "Set up game keys to sell on your game store page",
    trailing: (
      <Status palette="default" size="md" labelType="dot-color">
        Pending
      </Status>
    ),
    content: <p>Content here.</p>,
  },
];

<Accordion items={items} defaultOpenKeys={["template"]} />;
```

### With checkbox left slot

```tsx
import { useState } from "react";
import { Accordion, type AccordionItem } from "@xsolla/xui-b2b-accordion";
import { Checkbox } from "@xsolla/xui-checkbox";

function Selectable() {
  const [done, setDone] = useState<Record<string, boolean>>({});
  const make = (key: string, title: string): AccordionItem => ({
    key,
    title,
    icon: (
      <Checkbox
        size="md"
        checked={!!done[key]}
        onChange={(e) => setDone((d) => ({ ...d, [key]: e.target.checked }))}
      />
    ),
    content: <p>Step body.</p>,
  });

  return (
    <Accordion
      items={[
        make("one", "Connect your store"),
        make("two", "Add at least one product"),
        make("three", "Publish"),
      ]}
    />
  );
}
```

### Multiple open

```tsx
<Accordion items={items} multiple defaultOpenKeys={["what", "sdk"]} />
```

### Controlled

```tsx
import { useState } from "react";

function ControlledAccordion({ items }) {
  const [openKeys, setOpenKeys] = useState<string[]>(["what"]);
  return (
    <Accordion
      items={items}
      multiple
      openKeys={openKeys}
      onOpenChange={setOpenKeys}
    />
  );
}
```

## Accessibility

- Each item's trigger inherits `Collapsible`'s `role="button"`, `tabIndex={0}`, and `aria-expanded` semantics.
- Triggers respond to Enter and Space; the `icon` and `trailing` slots stop click propagation so interactive elements inside them (checkboxes, buttons) do not toggle the panel.
- Panel content is always in the DOM (hidden via `grid-template-rows: 0fr`) so screen readers can reach it.

## Behaviour

- All items render as `Collapsible` with `view="white-surface"`.
- In single mode (default), opening an item closes the others; in multiple mode, items toggle independently.
- Controlled mode (`openKeys` + `onOpenChange`) overrides internal state.
