import { Collapsible } from '@cerberus/react'The Collapsible component allows you to show or hide content with a trigger. It is useful for accordions, dropdowns, and expandable sections.
Use the defaultOpen prop to render the collapsible in an open state by default.
Use the collapsedHeight prop to show a preview of the content when collapsed.
To turn off the animation effect, you can set the effect prop to none on the Collapsible.Content component.
Use the open and onOpenChange props to control the collapsible state.
You can customize the Collapsible component any way you like with style props and data-selectors.
You can utilize the primitive components to build a custom collapsible solution.
| Component | Description |
|---|---|
| CollapsibleRoot | The context provider of the collapsible. |
| CollapsibleTrigger | The button that toggles the collapsible. |
| CollapsibleIndicator | The indicator that shows the state. |
| CollapsibleContent | The content of the collapsible. |
The primitives additionally use the following data attributes for custom styling:
| Name | Value | Description |
|---|---|---|
data-scope | collapsible | The scope of the components. |
data-part | root | The root container part. |
data-part | trigger | The trigger part. |
data-part | indicator | The indicator part. |
data-part | content | The content part. |
data-state | "open" | "closed" | The state of the content. |
The Collapsible component is an Object containing all the primitive components.
| Prop | Type | Required | Description |
|---|---|---|---|
asChild | boolean | No | Use the provided child element as the default rendered element, combining their props and behavior. |
collapsedHeight | string | number | No | The height of the content when collapsed. |
collapsedWidth | string | number | No | The width of the content when collapsed. |
defaultOpen | boolean | No | The initial open state of the collapsible when rendered. Use when you don't need to control the open state of the collapsible. |
disabled | boolean | No | Whether the collapsible is disabled. |
effect | "none" | "fadeIin" | "expandIn" | No | The animation effect of the content when collapsed. |
ids | Partial<{ root: string; content: string; trigger: string }> | No | The ids of the elements in the collapsible. Useful for composition. |
lazyMount | boolean | No | Whether to enable lazy mounting |
onExitComplete | VoidFunction | No | The callback invoked when the exit animation completes. |
onOpenChange | (details: OpenChangeDetails) => void | No | The callback invoked when the open state changes. |
open | boolean | No | The controlled open state of the collapsible. |
unmountOnExit | boolean | No | Whether to unmount on exit. |
You can see additional options for the Root component.
The CollapsibleParts API is the same as the Collapsible component.
On this page
'use client'
import { Box, HStack } from '@/styled-system/jsx'
import { ChevronDown } from '@carbon/icons-react'
import { Collapsible } from '@cerberus/react'
export function BasicDemo() {
return (
<HStack h="full" w="3/4">
<Collapsible.Root w="full">
<Collapsible.Trigger asChild>
<HStack gap="sm" userSelect="none">
<Collapsible.Indicator
transform="rotate(-90deg)"
transition="transform 0.2s"
_open={{ transform: 'rotate(0deg)' }}
>
<ChevronDown />
</Collapsible.Indicator>
Toggle
</HStack>
</Collapsible.Trigger>
<Collapsible.Content>
<Box
border="1px solid"
borderColor="page.border.initial"
p="md"
mt="sm"
rounded="md"
w="full"
>
Collapsible content goes here.
</Box>
</Collapsible.Content>
</Collapsible.Root>
</HStack>
)
}
'use client'
import { Box } from '@/styled-system/jsx'
import { Collapsible } from '@cerberus/react'
export function CustomDemo() {
return (
<Collapsible.Root w="full">
<Collapsible.Trigger
color="danger.text.100"
bgColor="danger.surface.initial"
px="sm"
w="full"
>
Custom Toggle
</Collapsible.Trigger>
<Collapsible.Content>
<Box w="full">Custom collapsible content.</Box>
</Collapsible.Content>
</Collapsible.Root>
)
}
'use client'
import { Box, HStack } from '@/styled-system/jsx'
import { ChevronDown } from '@carbon/icons-react'
import { Collapsible } from '@cerberus/react'
export function OpenDemo() {
return (
<HStack h="full" w="3/4">
<Collapsible.Root defaultOpen w="full">
<Collapsible.Trigger asChild>
<HStack gap="sm" userSelect="none">
<Collapsible.Indicator
transform="rotate(-90deg)"
transition="transform 0.2s"
_open={{ transform: 'rotate(0deg)' }}
>
<ChevronDown />
</Collapsible.Indicator>
Toggle
</HStack>
</Collapsible.Trigger>
<Collapsible.Content>
<Box
border="1px solid"
borderColor="page.border.initial"
p="md"
mt="sm"
rounded="md"
w="full"
>
Collapsible content goes here.
</Box>
</Collapsible.Content>
</Collapsible.Root>
</HStack>
)
}
'use client'
import { Box, HStack } from '@/styled-system/jsx'
import { Button, Collapsible } from '@cerberus/react'
export function PartialDemo() {
return (
<HStack h="full" w="3/4">
<Collapsible.Root collapsedHeight="100px" w="full">
<Collapsible.Content effect="fade">
<Box
border="1px solid"
borderColor="page.border.initial"
p="md"
mt="sm"
rounded="md"
w="full"
>
It is a long established fact that a reader will be distracted by the
readable content of a page when looking at its layout. The point of using
Lorem Ipsum is that it has a more-or-less normal distribution of letters, as
opposed to using 'Content here, content here', making it look like readable
English. Many desktop publishing packages and web page editors now use Lorem
Ipsum as their default model text, and a search for 'lorem ipsum' will
uncover many web sites still in their infancy. Various versions have evolved
over the years, sometimes by accident, sometimes on purpose (injected humour
and the like).
</Box>
</Collapsible.Content>
<Collapsible.Trigger asChild>
<Button mt="md" usage="outlined-subtle">
Show More
</Button>
</Collapsible.Trigger>
</Collapsible.Root>
</HStack>
)
}
'use client'
import { Box, HStack } from '@/styled-system/jsx'
import { Collapsible } from '@cerberus/react'
export function FadeDemo() {
return (
<HStack h="full" w="17rem">
<Collapsible.Root>
<Collapsible.Trigger>Toggle</Collapsible.Trigger>
<Collapsible.Content effect="none">
<Box
border="1px solid"
borderColor="page.border.initial"
p="md"
rounded="md"
w="full"
>
Collapsible content goes here.
</Box>
</Collapsible.Content>
</Collapsible.Root>
</HStack>
)
}
'use client'
import { Box, Stack } from '@/styled-system/jsx'
import { Collapsible, type OpenChangeDetails, Text } from '@cerberus/react'
import { useSignal } from '@cerberus/signals'
export function ControlledDemo() {
const [open, setOpen] = useSignal<boolean>(false)
return (
<Stack gap="4" w="3/4">
<Text textStyle="label-sm">Status: {open ? 'Open' : 'Closed'}</Text>
<Collapsible.Root
open={open}
onOpenChange={(e: OpenChangeDetails) => setOpen(e.open)}
w="full"
>
<Collapsible.Trigger paddingY="3">Toggle Collapsible</Collapsible.Trigger>
<Collapsible.Content>
<Box padding="4" borderWidth="1px">
This collapsible is controlled by external state. You can open and close it
using the buttons above or by clicking the trigger.
</Box>
</Collapsible.Content>
</Collapsible.Root>
</Stack>
)
}
Status: Closed