# Collapsible

A panel that expands and collapses.

Source: [collapsible.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/collapsible.tsx)

```tsx
import { ChevronsUpDownIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";

const row = "rounded-md border-[0.5px] border-border-muted px-3 py-2 font-mono text-sm";

export default function CollapsibleBasic() {
  return (
    <Collapsible className="flex w-full max-w-sm flex-col gap-2">
      <div className="flex items-center justify-between gap-4">
        <span className="text-sm font-medium">Ada Park starred 3 projects</span>
        <CollapsibleTrigger
          render={<Button variant="ghost" size="icon-sm" aria-label="Toggle starred projects" />}
        >
          <ChevronsUpDownIcon />
        </CollapsibleTrigger>
      </div>
      <div className={row}>website-redesign</div>
      <CollapsibleContent className="flex flex-col gap-2">
        <div className={row}>mobile-app</div>
        <div className={row}>brand-guidelines</div>
      </CollapsibleContent>
    </Collapsible>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/collapsible
```

## Usage

```tsx
import { Button } from "@/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";

export function Details() {
  return (
    <Collapsible>
      <CollapsibleTrigger render={<Button variant="ghost" size="sm" />}>
        Show details
      </CollapsibleTrigger>
      <CollapsibleContent>
        <p className="text-sm text-muted-foreground">Created by Ada Park on March 4.</p>
      </CollapsibleContent>
    </Collapsible>
  );
}
```

`CollapsibleTrigger` is an unstyled button. Pass `render` to draw it as a [Button](https://ui.jarv.is/components/button.md).

## Composition

- `Collapsible`
  - `CollapsibleTrigger`
  - `CollapsibleContent`

## Examples

### Open by default

`defaultOpen` starts it open. The trigger gets `data-panel-open` while open, which you can use to
rotate an icon.

```tsx
import { ChevronRightIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";

export default function CollapsibleOpenByDefault() {
  return (
    <Collapsible defaultOpen className="flex w-full max-w-sm flex-col gap-2">
      <CollapsibleTrigger
        render={
          <Button
            variant="ghost"
            size="sm"
            className="-ml-2 self-start [&_svg]:transition-transform [&[data-panel-open]_svg]:rotate-90"
          />
        }
      >
        <ChevronRightIcon />
        Advanced options
      </CollapsibleTrigger>
      <CollapsibleContent>
        <FieldGroup className="gap-3 pb-1">
          <Field>
            <FieldLabel htmlFor="production-branch">Production branch</FieldLabel>
            <Input id="production-branch" defaultValue="main" />
          </Field>
          <Field>
            <FieldLabel htmlFor="root-directory">Root directory</FieldLabel>
            <Input id="root-directory" defaultValue="apps/web" />
          </Field>
        </FieldGroup>
      </CollapsibleContent>
    </Collapsible>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `Collapsible` | [`Collapsible.Root`](https://base-ui.com/react/components/collapsible#root) |
| `CollapsibleTrigger` | [`Collapsible.Trigger`](https://base-ui.com/react/components/collapsible#trigger) |
| `CollapsibleContent` | [`Collapsible.Panel`](https://base-ui.com/react/components/collapsible#panel) |

The tables leave out `className`, `style` and `render`. Parts built on Base UI take them as its [styling](https://base-ui.com/react/handbook/styling) and [composition](https://base-ui.com/react/handbook/composition) guides describe.

### Collapsible

| Prop            | Type                                                                         | Description                                                                                                                        |
| --------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `open?`         | `boolean`                                                                    | Whether the collapsible panel is currently open. To render an uncontrolled collapsible, use the `defaultOpen` prop instead.        |
| `defaultOpen?`  | `boolean`                                                                    | Whether the collapsible panel is initially open. To render a controlled collapsible, use the `open` prop instead. Default: `false` |
| `onOpenChange?` | `((open: boolean, eventDetails: CollapsibleRootChangeEventDetails) => void)` | Event handler called when the panel is opened or closed.                                                                           |
| `disabled?`     | `boolean`                                                                    | Whether the component should ignore user interaction. Default: `false`                                                             |

### CollapsibleTrigger

| Prop            | Type      | Description                                                                                                                                                                                       |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `nativeButton?` | `boolean` | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). Default: `true` |

### CollapsibleContent

| Prop                | Type      | Description                                                                                                                                                                                                              |
| ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `hiddenUntilFound?` | `boolean` | Allows the browser's built-in page search to find and expand the panel contents. Overrides the `keepMounted` prop and uses `hidden="until-found"` to hide the element without removing it from the DOM. Default: `false` |
| `keepMounted?`      | `boolean` | Whether to keep the element in the DOM while the panel is hidden. This prop is ignored when `hiddenUntilFound` is used. Default: `false`                                                                                 |
