{"slug":"collapsible","title":"Collapsible","description":"Using the collapsible machine in your project.","contentType":"component","framework":"react","content":"A collapsible is a component which expands and collapses a panel.\n\n## Resources\n\n\n[Latest version: v1.31.0](https://www.npmjs.com/package/@zag-js/collapsible)\n[Logic Visualizer](https://zag-visualizer.vercel.app/collapsible)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/collapsible)\n\n\n\n**Features**\n\n- Can be controlled or uncontrolled\n- Works for width and height collapsibles\n\n## Installation\n\nTo use the collapsible machine in your project, run the following command in\nyour command line:\n\n```bash\nnpm install @zag-js/collapsible @zag-js/react\n# or\nyarn add @zag-js/collapsible @zag-js/react\n```\n\n## Usage\n\nFirst, import the collapsible package into your project\n\n```jsx\nimport * as collapsible from \"@zag-js/collapsible\"\n```\n\nThe collapsible package exports two key functions:\n\n- `machine` — The state machine logic for the collapsible widget.\n- `connect` — The function that translates the machine's state to JSX attributes\n  and event handlers.\n\n> You'll also need to provide a unique `id` to the `useMachine` hook. This is\n> used to ensure that every part has a unique identifier.\n\nNext, import the required hooks and functions for your framework and use the\ncollapsible machine in your project 🔥\n\n```tsx\nimport * as collapsible from \"@zag-js/collapsible\"\nimport { normalizeProps, useMachine } from \"@zag-js/react\"\nimport { useId } from \"react\"\n\nfunction Collapsible() {\n  const service = useMachine(collapsible.machine, { id: useId() })\n\n  const api = collapsible.connect(service, normalizeProps)\n\n  return (\n    <div {...api.getRootProps()}>\n      <button {...api.getTriggerProps()}>Collapse Trigger</button>\n      <div {...api.getContentProps()}>Collape Content</div>\n    </div>\n  )\n}\n```\n\n### Setting the initial state\n\nPass the `defaultOpen` machine context property to the machine function to set\nthe initial state.\n\n```jsx\nconst service = useMachine(collapsible.machine, {\n  defaultOpen: true,\n})\n```\n\n### Controlled collapsible\n\nTo control the open state programmatically, pass the `open` and `onOpenChange`\nproperties to the machine function.\n\n```tsx\nimport { useState } from \"react\"\n\nexport function ControlledCollapsible() {\n  const [open, setOpen] = useState(false)\n\nconst service = useMachine(collapsible.machine, {\n    open,\n    onOpenChange(details) {\n      setOpen(details.open)\n    }\n })\n\n  return (\n    // ...\n    )\n}\n```\n\n### Listening for changes\n\nWhen the collapsible state changes, the `onOpenChange` callback is invoked.\n\n```jsx {2-5}\nconst service = useMachine(collapsible.machine, {\n  onOpenChange(details) {\n    // details => { open: boolean }\n    console.log(\"collapsible open:\", details.open)\n  },\n})\n```\n\n### Disabling the collapsible\n\nSet the `disabled` machine context property to `true` to disable the\ncollapsible.\n\n```jsx {2}\nconst service = useMachine(collapsible.machine, {\n  disabled: true,\n})\n```\n\n### Partial collapse (setting minimum dimensions)\n\nUse the `collapsedHeight` or `collapsedWidth` machine context properties to\ncreate a \"partially collapsed\" state. When collapsed, the content will maintain\nthe specified minimum dimensions instead of collapsing to `0px`.\n\n```jsx {3}\nconst service = useMachine(collapsible.machine, {\n  // Content shows 100px height when collapsed\n  collapsedHeight: \"100px\",\n})\n```\n\nThis is useful for creating \"show more/less\" content sections or preview states\nwhere a portion of the content shows even when collapsed.\n\n### Animating the collapsible\n\nUse CSS animations to animate the collapsible when it expands and collapses. The\n`--height` and `--width` custom properties are attached to the content part.\n\n```css\n@keyframes expand {\n  from {\n    height: var(--collapsed-height, 0);\n  }\n  to {\n    height: var(--height);\n  }\n}\n\n@keyframes collapse {\n  from {\n    height: var(--height);\n  }\n  to {\n    height: var(--collapsed-height, 0);\n  }\n}\n\n[data-scope=\"collapsible\"][data-part=\"content\"] {\n  overflow: hidden;\n  max-width: 400px;\n}\n\n[data-scope=\"collapsible\"][data-part=\"content\"][data-state=\"open\"] {\n  animation: expand 110ms cubic-bezier(0, 0, 0.38, 0.9);\n}\n\n[data-scope=\"collapsible\"][data-part=\"content\"][data-state=\"closed\"] {\n  animation: collapse 110ms cubic-bezier(0, 0, 0.38, 0.9);\n}\n```\n\n## Styling guide\n\nEarlier, we mentioned that each collapsible part has a `data-part` attribute\nadded to them to select and style them in the DOM.\n\n### Open and closed state\n\nWhen a collapsible is expanded or collapsed, a `data-state` attribute is set on\nthe root, trigger and content elements. This attribute is removed when it is\nclosed.\n\n```css\n[data-part=\"root\"][data-state=\"open|closed\"] {\n  /* styles for the collapsible is open or closed state */\n}\n\n[data-part=\"trigger\"][data-state=\"open|closed\"] {\n  /* styles for the collapsible is open or closed state */\n}\n\n[data-part=\"content\"][data-state=\"open|closed\"] {\n  /* styles for the collapsible is open or closed state */\n}\n```\n\n### Focused state\n\nWhen a collapsible's trigger is focused, a `data-focus` attribute is set on the\nroot, trigger and content.\n\n```css\n[data-part=\"root\"][data-focus] {\n  /* styles for the item's focus state */\n}\n\n[data-part=\"trigger\"][data-focus] {\n  /* styles for the content's focus state */\n}\n\n[data-part=\"content\"][data-focus] {\n  /* styles for the content's focus state */\n}\n```\n\n### Collapse animation\n\nThe collapsible content provides `--width`, `--height`, `--collapsed-width`, and\n`--collapsed-height` CSS variables that can be used to create smooth animations.\nThese variables are automatically calculated and updated based on the content's\ndimensions.\n\n```css\n[data-scope=\"collapsible\"][data-part=\"content\"][data-state=\"open\"] {\n  animation: slideDown 200ms ease;\n}\n\n[data-scope=\"collapsible\"][data-part=\"content\"][data-state=\"closed\"] {\n  animation: slideUp 200ms ease;\n}\n\n@keyframes slideDown {\n  from {\n    opacity: 0.01;\n    height: 0;\n  }\n  to {\n    opacity: 1;\n    height: var(--height);\n  }\n}\n\n@keyframes slideUp {\n  from {\n    opacity: 1;\n    height: var(--height);\n  }\n  to {\n    opacity: 0.01;\n    height: 0;\n  }\n}\n```\n\n## Methods and Properties\n\nThe collapsible's `api` exposes the following methods and properties:\n\n### Machine Context\n\nThe collapsible machine exposes the following context properties:\n\n**`ids`**\nType: `Partial<{ root: string; content: string; trigger: string; }>`\nDescription: The ids of the elements in the collapsible. Useful for composition.\n\n**`open`**\nType: `boolean`\nDescription: The controlled open state of the collapsible.\n\n**`defaultOpen`**\nType: `boolean`\nDescription: The initial open state of the collapsible when rendered.\nUse when you don't need to control the open state of the collapsible.\n\n**`onOpenChange`**\nType: `(details: OpenChangeDetails) => void`\nDescription: The callback invoked when the open state changes.\n\n**`onExitComplete`**\nType: `VoidFunction`\nDescription: The callback invoked when the exit animation completes.\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the collapsible is disabled.\n\n**`collapsedHeight`**\nType: `string | number`\nDescription: The height of the content when collapsed.\n\n**`collapsedWidth`**\nType: `string | number`\nDescription: The width of the content when collapsed.\n\n**`id`**\nType: `string`\nDescription: The unique identifier of the machine.\n\n**`getRootNode`**\nType: `() => ShadowRoot | Node | Document`\nDescription: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.\n\n**`dir`**\nType: `\"ltr\" | \"rtl\"`\nDescription: The document's text/writing direction.\n\n### Machine API\n\nThe collapsible `api` exposes the following methods:\n\n**`open`**\nType: `boolean`\nDescription: Whether the collapsible is open.\n\n**`visible`**\nType: `boolean`\nDescription: Whether the collapsible is visible (open or closing)\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the collapsible is disabled\n\n**`setOpen`**\nType: `(open: boolean) => void`\nDescription: Function to open or close the collapsible.\n\n**`measureSize`**\nType: `VoidFunction`\nDescription: Function to measure the size of the content.\n\n### Data Attributes\n\n**`Root`**\n\n**`data-scope`**: collapsible\n**`data-part`**: root\n**`data-state`**: \"open\" | \"closed\"\n\n**`Content`**\n\n**`data-scope`**: collapsible\n**`data-part`**: content\n**`data-collapsible`**: \n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-has-collapsed-size`**: Present when the content has collapsed width or height\n\n**`Trigger`**\n\n**`data-scope`**: collapsible\n**`data-part`**: trigger\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n\n**`Indicator`**\n\n**`data-scope`**: collapsible\n**`data-part`**: indicator\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n\n### CSS Variables\n\n<CssVarTable name=\"collapsible\" />\n\n## Accessibility\n\nAdheres to the\n[Disclosure WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure).\n\n### Keyboard Interactions\n\n**`Space`**\nDescription: Opens/closes the collapsible.\n\n**`Enter`**\nDescription: Opens/closes the collapsible.","package":"@zag-js/collapsible","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/collapsible.mdx"}