# React Bootstrap Accordion

A React Bootstrap accordion built from four small components: items open from React state with Bootstrap's height transition. Flush and always-open variants.

> This component is only available in **AdminKit PRO**. [Learn more](/pricing/#react).

Use an accordion when a page has more sections than a reader wants to see at once, such as a FAQ or a long help page. Only the headers show, and a click on a header opens its section.

In AdminKit the accordion is four small React components: `Accordion`, `AccordionItem`, `AccordionHeader` and `AccordionBody`. They render Bootstrap's accordion markup and open items from React state, without Bootstrap's JavaScript or react-bootstrap. They are part of the PRO version of [AdminKit for React](/react/).

The body slides open with the same height transition as [Collapse](/react/docs/components/collapse/), which the accordion is built on.

## Example

Give each `AccordionItem` an `eventKey`. To start with one item open, pass its key to `defaultActiveKey`. Opening another item then closes it.

```html
<div class="accordion" id="accordionFaq">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#faqShipping" aria-expanded="true" aria-controls="faqShipping">
        When do orders ship?
      </button>
    </h2>
    <div id="faqShipping" class="accordion-collapse collapse show" data-bs-parent="#accordionFaq">
      <div class="accordion-body">Orders ship within two business days.</div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faqReturns" aria-expanded="false" aria-controls="faqReturns">
        Can I return an order?
      </button>
    </h2>
    <div id="faqReturns" class="accordion-collapse collapse" data-bs-parent="#accordionFaq">
      <div class="accordion-body">Return any order within 30 days for a full refund.</div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#faqPayment" aria-expanded="false" aria-controls="faqPayment">
        Which payment methods do you accept?
      </button>
    </h2>
    <div id="faqPayment" class="accordion-collapse collapse" data-bs-parent="#accordionFaq">
      <div class="accordion-body">Credit cards, PayPal and bank transfer.</div>
    </div>
  </div>
</div>
```
```tsx code
import {
  Accordion,
  AccordionBody,
  AccordionHeader,
  AccordionItem,
} from "@/components/bootstrap/accordion";

export function ShippingFaq() {
  return (
    <Accordion defaultActiveKey="shipping">
      <AccordionItem eventKey="shipping">
        <AccordionHeader>When do orders ship?</AccordionHeader>
        <AccordionBody>Orders ship within two business days.</AccordionBody>
      </AccordionItem>
      <AccordionItem eventKey="returns">
        <AccordionHeader>Can I return an order?</AccordionHeader>
        <AccordionBody>Return any order within 30 days for a full refund.</AccordionBody>
      </AccordionItem>
      <AccordionItem eventKey="payment">
        <AccordionHeader>Which payment methods do you accept?</AccordionHeader>
        <AccordionBody>Credit cards, PayPal and bank transfer.</AccordionBody>
      </AccordionItem>
    </Accordion>
  );
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `defaultActiveKey` | `string \| string[]` | | The item or items open on the first render; all closed without it |
| `alwaysOpen` | `boolean` | `false` | Items stay open when another item opens |

Other props of `Accordion`, such as `className` and `id`, go to the `.accordion` element. All four components are in `src/components/bootstrap/accordion.tsx`.

- `AccordionItem` takes a required `eventKey` (`string`), unique in its accordion. Its other props go to `.accordion-item`.
- `AccordionHeader` takes `as` for the heading around the button (`"h2"` to `"h6"`, `"h2"` by default), `className` for that heading, and `children` for the button text.
- `AccordionBody` passes its props, `className` included, to `.accordion-body`, not to the collapsing wrapper around it.

`Accordion` keeps the open items to itself. After the first render, no prop can open an item from outside. If you want to open a panel from your own state, use [Collapse](/react/docs/components/collapse/) instead. The parts throw an error when they are not inside an `Accordion`.

## Flush

Inside a card, you may want the accordion to sit edge to edge. `className="accordion-flush"` removes the outer borders and the rounded corners.

```html
<div class="accordion accordion-flush" id="accordionFlush">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flushAccount" aria-expanded="false" aria-controls="flushAccount">
        Account
      </button>
    </h2>
    <div id="flushAccount" class="accordion-collapse collapse" data-bs-parent="#accordionFlush">
      <div class="accordion-body">Change your name, email and password.</div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flushBilling" aria-expanded="false" aria-controls="flushBilling">
        Billing
      </button>
    </h2>
    <div id="flushBilling" class="accordion-collapse collapse" data-bs-parent="#accordionFlush">
      <div class="accordion-body">Update your payment method and download invoices.</div>
    </div>
  </div>
</div>
```
```tsx code
<Accordion className="accordion-flush">
  <AccordionItem eventKey="account">
    <AccordionHeader>Account</AccordionHeader>
    <AccordionBody>Change your name, email and password.</AccordionBody>
  </AccordionItem>
  <AccordionItem eventKey="billing">
    <AccordionHeader>Billing</AccordionHeader>
    <AccordionBody>Update your payment method and download invoices.</AccordionBody>
  </AccordionItem>
</Accordion>
```

## Always open

Sometimes readers want to compare two sections side by side. With `alwaysOpen`, opening an item leaves the others as they are. To open several items at the start, pass a list of keys to `defaultActiveKey`.

```html
<div class="accordion">
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#openProfile" aria-expanded="true" aria-controls="openProfile">
        Profile
      </button>
    </h2>
    <div id="openProfile" class="accordion-collapse collapse show">
      <div class="accordion-body">Your photo and display name.</div>
    </div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header">
      <button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#openNotifications" aria-expanded="true" aria-controls="openNotifications">
        Notifications
      </button>
    </h2>
    <div id="openNotifications" class="accordion-collapse collapse show">
      <div class="accordion-body">Choose which emails you receive.</div>
    </div>
  </div>
</div>
```
```tsx code
<Accordion alwaysOpen defaultActiveKey={["profile", "notifications"]}>
  <AccordionItem eventKey="profile">
    <AccordionHeader>Profile</AccordionHeader>
    <AccordionBody>Your photo and display name.</AccordionBody>
  </AccordionItem>
  <AccordionItem eventKey="notifications">
    <AccordionHeader>Notifications</AccordionHeader>
    <AccordionBody>Choose which emails you receive.</AccordionBody>
  </AccordionItem>
</Accordion>
```

## Accessibility

- Each header is a `<button>` in a heading, with `aria-expanded` and `aria-controls` pointing at the body. `Accordion` generates the body `id`s with `useId`, so two accordions on a page never share one.
- Pick the heading level that fits the page outline with `as`, for example `as="h3"` under an `h2`.
- The headers are plain buttons: Tab moves between them, Enter and Space open and close an item.
- A closed body has `.collapse` (`display: none`), so its content is out of the tab order and hidden from screen readers.

## Related

- [Next.js Bootstrap accordion](/nextjs/docs/components/accordion/): the same component in AdminKit for Next.js
- [Bootstrap 5 accordion](/bootstrap/docs/components/accordion/): the accordion of the HTML version
- [Collapse](/react/docs/components/collapse/): one panel that shows and hides from your own state
- [General UI demo](https://react-demo.adminkit.io/ui-general): a card accordion built with `Collapse`

---

Canonical HTML page: https://adminkit.io/react/docs/components/accordion/

Site overview for agents: https://adminkit.io/llms.txt (expanded: https://adminkit.io/llms-full.txt) · Documentation: https://adminkit.io/bootstrap/docs/ · Questions: support@adminkit.io
