> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Collapsible

> Compose an accessible trigger and animated panel with controlled or uncontrolled expansion.

export const StoryEmbed = ({storyId, title, height = 120}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

`Collapsible` exposes Base UI's Root, Trigger, and Panel contracts. Root owns expansion state, Trigger supplies keyboard activation and the panel relationship, and Panel owns animation and content lifetime.

<StoryEmbed storyId="ui-layout-collapsible--display" title="Collapsible example" height={160} />

## Usage

```tsx theme={null}
import { Button } from 'twenty-ui/primitives/input';
import { Collapsible } from 'twenty-ui/primitives/layout';
import { Text } from 'twenty-ui/primitives/typography';

export const ImportDetails = () => (
  <Collapsible.Root defaultOpen style={{ width: 360, maxWidth: '100%' }}>
    <Collapsible.Trigger render={<Button />}>
      Import details
    </Collapsible.Trigger>
    <Collapsible.Panel>
      <Text
        style={{
          paddingTop: 12,
          color: 'var(--t-font-color-secondary)',
          lineHeight: 1.5,
        }}
      >
        Match each CSV column to a record field before importing.
      </Text>
    </Collapsible.Panel>
  </Collapsible.Root>
);
```

Use `defaultOpen` for uncontrolled expansion. Use `open` and `onOpenChange` when the application owns the state. The callback receives the requested boolean and Base UI event details, including `reason`, `event`, and `cancel()`. Canceling a change preserves the current state. An externally controlled panel can omit Trigger when its state comes from another control or application condition.

Triggers inherit Root's `disabled` state and can override it with their own `disabled` prop. The native trigger supports Enter and Space and supplies `aria-expanded` and `aria-controls` automatically. Give each trigger a meaningful accessible name.

## Anatomy

```text theme={null}
Collapsible.Root
├── Collapsible.Trigger
└── Collapsible.Panel
    └── Content
```

## Native customization

Root and Panel render a `div`; Trigger renders a `button`. Each part accepts native attributes, handlers, `className`, `style`, refs, and Base UI `render` composition. Class and style callbacks receive the part's state. Forward all supplied props and the ref from custom render components. Set `nativeButton={false}` when Trigger renders a non-button element.

Public types include `CollapsibleRootProps`, `CollapsibleTriggerProps`, `CollapsiblePanelProps`, the three part state types, and `CollapsibleRootChangeEventDetails` and `CollapsibleRootChangeEventReason`.

## Animation and content lifetime

Panel defaults to `dimension="height"`. Use `dimension="width"` for horizontal expansion and constrain the content's width when needed. `containAnimation` defaults to `true`, clips overflow, and lays content out in a column. Set it to `false` when content needs to overflow during the transition.

Panel's `duration` chooses a theme preset (`instant`, `fast`, `normal`, or `slow`). For independent timings, use native `style={{ transitionDuration: '0.4s, 0.2s' }}`. The first duration controls size and the second controls opacity. Reduced-motion preferences disable the transitions, including custom timings.

Panel unmounts after closing by default. Use `keepMounted` to preserve local content state while hiding the closed panel. `hiddenUntilFound` lets browser page search reveal closed content and takes precedence over `keepMounted`.

## Props

### Collapsible.Root

<ParamField body="Root.className" type="string | ((state: CollapsibleRootState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Root.defaultOpen" type="boolean" default="false">
  Initial uncontrolled expansion state.
</ParamField>

<ParamField body="Root.disabled" type="boolean" default="false">
  Default disabled state inherited by the triggers in this root.
</ParamField>

<ParamField body="Root.onOpenChange" type="((open: boolean, eventDetails: CollapsibleRootChangeEventDetails) => void)">
  Called with the requested open state and cancelable Base UI event details.
</ParamField>

<ParamField body="Root.open" type="boolean">
  Controlled expansion state. Use defaultOpen for uncontrolled state.
</ParamField>

<ParamField body="Root.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsibleRootState>">
  Replaces the root div. Forward the supplied props and ref.
</ParamField>

<ParamField body="Root.style" type="CSSProperties | ((state: CollapsibleRootState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Collapsible.Trigger

<ParamField body="Trigger.className" type="string | ((state: CollapsibleTriggerState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Trigger.disabled" type="boolean">
  Disables this trigger.
</ParamField>

<ParamField body="Trigger.nativeButton" type="boolean" default="true">
  Set to false when render replaces the native button with another element.
</ParamField>

<ParamField body="Trigger.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsibleTriggerState>">
  Replaces the linked trigger button. Forward the supplied props and ref.
</ParamField>

<ParamField body="Trigger.style" type="CSSProperties | ((state: CollapsibleTriggerState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

### Collapsible.Panel

<ParamField body="Panel.className" type="string | ((state: CollapsiblePanelState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Panel.containAnimation" type="boolean" default="true">
  Clips overflowing content during expansion and uses a column layout.
</ParamField>

<ParamField body="Panel.dimension" type="&#x22;height&#x22; | &#x22;width&#x22;" default="height">
  Dimension animated when the panel opens and closes.
</ParamField>

<ParamField body="Panel.duration" type="&#x22;fast&#x22; | &#x22;instant&#x22; | &#x22;normal&#x22; | &#x22;slow&#x22;" default="normal">
  Theme timing preset for both size and opacity. Native style can customize transition timing.
</ParamField>

<ParamField body="Panel.hiddenUntilFound" type="boolean" default="false">
  Uses hidden until-found so browser page search can reveal the contents. Overrides keepMounted.
</ParamField>

<ParamField body="Panel.keepMounted" type="boolean" default="false">
  Keeps the closed panel mounted and hidden, preserving local content state.
</ParamField>

<ParamField body="Panel.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, CollapsiblePanelState>">
  Replaces the animated panel div. Forward the supplied props and ref.
</ParamField>

<ParamField body="Panel.style" type="CSSProperties | ((state: CollapsiblePanelState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.