# React Bootstrap Collapse

A React Bootstrap collapse component: show and hide content from a boolean in React state, with Bootstrap's animated height transition and transition callbacks.

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

Use `Collapse` to keep content out of sight until the user asks for it: extra details under an order, advanced options in a form, a nested menu. It shows and hides its content with Bootstrap's height transition, driven by a boolean in React state instead of Bootstrap's JavaScript. The [accordion](/react/docs/components/accordion/) and the sidebar's nested menus use it. `Collapse` is part of the PRO version of [AdminKit for React](/react/).

The button that toggles it is yours, so you decide what opens it. `Collapse` switches Bootstrap's classes for you: `.collapse` when hidden, `.collapsing` with an animated height while it opens or closes, and `.collapse.show` when shown.

## Example

```html
<button class="btn btn-primary" type="button" data-bs-toggle="collapse" data-bs-target="#orderDetails" aria-expanded="false" aria-controls="orderDetails">
  Order details
</button>
<div class="collapse" id="orderDetails">
  <div class="card card-body mt-3">
    Ordered on May 4, paid by credit card, shipped to Amsterdam.
  </div>
</div>
```
```tsx code
import { useState } from "react";
import { Collapse } from "@/components/bootstrap/collapse";

export function OrderDetails() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button
        className="btn btn-primary"
        type="button"
        aria-expanded={open}
        aria-controls="orderDetails"
        onClick={() => setOpen(!open)}
      >
        Order details
      </button>
      <Collapse in={open} id="orderDetails">
        <div className="card card-body mt-3">
          Ordered on May 4, paid by credit card, shipped to Amsterdam.
        </div>
      </Collapse>
    </>
  );
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `in` | `boolean` | | Required. Shown (`true`) or collapsed (`false`) |
| `as` | `ElementType` | `"div"` | The element to render, such as `"ul"` for a nested list |
| `onEntered` | `() => void` | | Called when the opening transition has ended |
| `onExited` | `() => void` | | Called when the closing transition has ended |

Other props, such as `id`, `className`, `ref` and `aria-*`, go to the collapsing element. The first render shows the `in` state without a transition. Only later changes animate. When the user prefers reduced motion, Bootstrap turns the transition off, and the callbacks run on the next frame. The component is in `src/components/bootstrap/collapse.tsx`.

## Padding and margins

If the transition jumps, look for padding or a margin on the `Collapse` element. `Collapse` animates the `height` of its own element, so put padding and margins on a child element instead, as the examples do with `.card` and `mt-3`. The transition is vertical only: `.collapse-horizontal` has no effect.

## Several panels

Sometimes one button should open several panels at once. Each `Collapse` follows its own `in`, so give the panels a shared state for that button. Each panel can still have its own button too:

```html
<p>
  <button class="btn btn-primary me-2" type="button" data-bs-toggle="collapse" data-bs-target="#panelBilling" aria-expanded="false" aria-controls="panelBilling">Billing</button>
  <button class="btn btn-primary me-2" type="button" data-bs-toggle="collapse" data-bs-target="#panelShipping" aria-expanded="false" aria-controls="panelShipping">Shipping</button>
  <button class="btn btn-secondary" type="button" data-bs-toggle="collapse" data-bs-target=".panel-address" aria-expanded="false" aria-controls="panelBilling panelShipping">Both addresses</button>
</p>
<div class="row">
  <div class="col">
    <div class="collapse panel-address" id="panelBilling">
      <div class="card card-body">Billing: 12 Market Street, Amsterdam</div>
    </div>
  </div>
  <div class="col">
    <div class="collapse panel-address" id="panelShipping">
      <div class="card card-body">Shipping: 4 Harbor Road, Rotterdam</div>
    </div>
  </div>
</div>
```
```tsx code
import { useState } from "react";
import { Collapse } from "@/components/bootstrap/collapse";

export function Addresses() {
  const [billing, setBilling] = useState(false);
  const [shipping, setShipping] = useState(false);
  const both = billing && shipping;

  return (
    <>
      <p>
        <button
          className="btn btn-primary me-2"
          type="button"
          aria-expanded={billing}
          aria-controls="panelBilling"
          onClick={() => setBilling(!billing)}
        >
          Billing
        </button>
        <button
          className="btn btn-primary me-2"
          type="button"
          aria-expanded={shipping}
          aria-controls="panelShipping"
          onClick={() => setShipping(!shipping)}
        >
          Shipping
        </button>
        <button
          className="btn btn-secondary"
          type="button"
          aria-expanded={both}
          aria-controls="panelBilling panelShipping"
          onClick={() => {
            setBilling(!both);
            setShipping(!both);
          }}
        >
          Both addresses
        </button>
      </p>
      <div className="row">
        <div className="col">
          <Collapse in={billing} id="panelBilling">
            <div className="card card-body">Billing: 12 Market Street, Amsterdam</div>
          </Collapse>
        </div>
        <div className="col">
          <Collapse in={shipping} id="panelShipping">
            <div className="card card-body">Shipping: 4 Harbor Road, Rotterdam</div>
          </Collapse>
        </div>
      </div>
    </>
  );
}
```

The "Both addresses" button of the Bootstrap preview toggles each panel. The React version opens both, or closes both when both are open.

## Accessibility

- `Collapse` sets no ARIA attributes itself. Give the toggle `aria-expanded={open}` and `aria-controls` with the panel's `id`, as in the examples.
- Use a `<button>` as the toggle. A link needs `role="button"` and `event.preventDefault()` in its `onClick`, as the card accordion of the demo does.
- A collapsed panel is `display: none`, so its content is out of the tab order and hidden from screen readers.

## Related

- [Next.js Bootstrap collapse](/nextjs/docs/components/collapse/): the same component in AdminKit for Next.js
- [Bootstrap 5 collapse](/bootstrap/docs/components/collapse/): the collapse of the HTML version
- [Accordion](/react/docs/components/accordion/): collapsing sections, one open at a time unless you set `alwaysOpen`
- [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/collapse/

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
