# Collapsible
> An interactive component for collapsing and expanding sections of content.

## Import

```js
import { Collapsible } from '@gemini-suite/vera-react';

// you may also access Collapsible's context via hook:
// import { useCollapsibleContext } from '@gemini-suite/vera-react';
```

Collapsible is a compound component that consists of multiple parts:

- `Collapsible.Root`: The wrapper that contains all the parts of a collapsible and provides context for its children.
- `Collapsible.Trigger`: The button that toggles the collapsible.
- `Collapsible.Panel`: The container for the collapsible content.

## Examples

### Basic

`Collapsible` works in an uncontrolled way by default, meaning each `Collapsible` component instance is responsible for managing its own state internally.

<Callout variant="tip">

The `Collapsible.Trigger` component can be instructed via `as` prop to render _as_ something else. In our case we want to render it as a `<Button>` component.

</Callout>

```jsx
<Collapsible.Root>
  <Collapsible.Trigger as={Button} variant="outline">
    {'Toggle Collapsible'}
  </Collapsible.Trigger>
  <Collapsible.Panel>
    <Box
      padding="spacingM"
      marginTop="spacingM"
      css={{
        backgroundColor: '$backgroundNeutralModerate'
      }}
    >
      {'Content 1'}
    </Box>
  </Collapsible.Panel>
</Collapsible.Root>
```

### Controlled Collapsible

You can easily make the collapsible controlled, by passing your own state to `isOpen` prop.
`onIsOpenChange` handler is called when the state of the collapsible changes, allowing you to sync state.

```jsx
() => {
  const [state, setState] = React.useState(true);

  return (
    <Collapsible.Root isOpen={state} onIsOpenChange={setState}>
      <Collapsible.Trigger as={Button} variant="outline">
        {'Toggle Collapsible'}
      </Collapsible.Trigger>
      <Collapsible.Panel>
        <Box
          padding="spacingM"
          marginTop="spacingM"
          css={{
            backgroundColor: '$backgroundNeutralModerate'
          }}
        >
          {'Content 1'}
        </Box>
      </Collapsible.Panel>
    </Collapsible.Root>
  );
};
```

### With starting height

```jsx
() => {
  const [isOpen, setIsOpen] = React.useState(true);

  return (
    <Collapsible.Root isOpen={isOpen} onIsOpenChange={setIsOpen}>
      <Collapsible.Panel startingHeight={24}>
        Green tea banana refreshing cucumber splash mangos tempeh crumbled
        lentils ginger carrot spiced juice fall shiitake mushrooms lime morning
        smoothie bowl udon noodles green onions coriander hazelnut shiitake
        sweet potato lemongrass lychee basmati red pepper strawberry spinach
        salad heat mediterranean.
      </Collapsible.Panel>
      <Collapsible.Trigger
        as={Button}
        variant="outline"
        marginTop="spacingM"
        leftIcon={<SvgIcon iconName={isOpen ? 'chevronDown' : 'chevronUp'} />}
      >
        {'Show more'}
      </Collapsible.Trigger>
    </Collapsible.Root>
  );
};
```

### Unmount on exit

You can force `<Collapsible.Panel>` children to unmount when exit state is done by setting `unmountOnExit` to `true`.

```jsx
<Collapsible.Root>
  <Collapsible.Trigger as={Button} variant="outline">
    {'Toggle Collapsible'}
  </Collapsible.Trigger>
  <Collapsible.Panel unmountOnExit>
    <Box
      padding="spacingM"
      marginTop="spacingM"
      css={{
        backgroundColor: '$backgroundNeutralModerate'
      }}
    >
      {'Content 1'}
    </Box>
  </Collapsible.Panel>
</Collapsible.Root>
```

---

## API Reference

### Collapsible.Root

| Name             | Type                        | Default | Description                                                                                                 | Required |
| ---------------- | --------------------------- | ------- | ----------------------------------------------------------------------------------------------------------- | -------- |
| `isOpen`         | `boolean`                   | `false` | The controlled open state of the collapsible. Use in conjunction with `onIsOpenChange`.                     |          |
| `defaultIsOpen`  | `boolean`                   |         | The open state of the collapsible when it's first rendered. Use when you do not need to control open state. |          |
| `onIsOpenChange` | `(isOpen: boolean) => void` |         | Event handler called when the open state of the collapsible changes.                                        |          |

### Collapsible.Trigger

| Name  | Type                                                      | Default  | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `button` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### Collapsible.Panel

| Name                  | Type               | Default      | Description                                                                                                                                                                                                                                   | Required |
| --------------------- | ------------------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`                 | `StitchesCss`      |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `unmountOnExit`       | `boolean`          | `false`      | When `true`, panel's children will unmount when exit animation is done.                                                                                                                                                                       |          |
| `startingHeight`      | `string \| number` |              | The height of the panel in its collapsed state. You cannot use `startingHeight` in conjunction with `unmountOnExit` set to `true`.                                                                                                            |          |
| `onAnimationComplete` | `() => void`       |              | Event handler called when the collapsible has completed animating.                                                                                                                                                                            |          |
| `onExitComplete`      | `() => void`       | `() => void` | Event handler called when the collapsible has completed animating out and is to be unmounted.                                                                                                                                                 |          |
| `containPaint`        | `boolean`          | `true`       | When `true`, [paint containment](https://developer.chrome.com/blog/css-containment#paint_contain_paint) is activated for the panel improving the rendering performance.                                                                       |          |
