Collapsible
A single disclosure that animates open and closed — built on Base UI's Collapsible primitive with four variants, five sizes, intent accents, and full RTL support.
Playground
Installation
pnpm add @tessinaui/uiUsage
import {
CollapsibleRoot,
CollapsibleHeader,
CollapsibleTrigger,
CollapsiblePanel,
} from "@tessinaui/ui";<CollapsibleRoot variant="outline">
<CollapsibleHeader>
<CollapsibleTrigger>Show advanced options</CollapsibleTrigger>
</CollapsibleHeader>
<CollapsiblePanel>
Tweak request timeouts, retry policy, and SDK telemetry — most teams leave
these on the defaults.
</CollapsiblePanel>
</CollapsibleRoot>Showcase
When to use
Reach for Collapsible whenever you have a single block of secondary content that should be hidden by default and revealed on demand. Common cases: advanced form options, FAQ teasers, "show more" sections, expandable list rows.
If you have multiple related disclosures stacked together, prefer Accordion — it adds keyboard navigation between items and a single-or-multiple-open semantic.
API Reference
CollapsibleRoot props
| Prop | Type | Default | Description |
|---|---|---|---|
size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Scales trigger padding, text, indicator, and panel padding |
variant | "ghost" | "outline" | "filled" | "elevated" | "ghost" | Visual treatment — ghost is just trigger + panel, the others wrap everything in a card |
rounded | "none" | "sm" | "md" | "lg" | "full" | "md" | Card corner radius (only applies to non-ghost variants) |
intent | "none" | "primary" | "error" | "warning" | "success" | "info" | "none" | Adds a subtle border accent to non-ghost variants |
dir | "ltr" | "rtl" | "ltr" | Text direction — flips trigger row and indicator placement |
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Uncontrolled initial open state |
onOpenChange | (open: boolean) => void | — | Called when the panel opens or closes |
disabled | boolean | false | Disables the trigger and prevents toggling |
render | ReactElement | (props, state) => ReactElement | — | Base UI polymorphic prop — replace the rendered element or compose with a custom component (equivalent to Radix asChild) |
CollapsibleHeader props
A flex row container that respects the root's dir. Use it to place a title, badge, or extra actions next to the trigger. Accepts all standard <div> HTML attributes plus className for overrides.
CollapsibleTrigger props
| Prop | Type | Default | Description |
|---|---|---|---|
indicator | "chevron" | "plus-minus" | "caret" | "none" | "chevron" | Built-in indicator icon set |
indicatorPosition | "start" | "end" | "end" | Logical position — flips with dir="rtl" |
customIndicator | ReactNode | — | Render a custom icon instead of the built-in indicator |
fullWidth | boolean | true | Stretch the trigger to fill its container |
render | ReactElement | (props, state) => ReactElement | — | Base UI polymorphic prop — render as a different element (e.g. an <a> or another component) while preserving trigger behaviour |
nativeButton | boolean | true | Whether to render a real <button> element |
Renders a <button> underneath. Animates the indicator on the trigger's data-panel-open state. Accepts all standard button HTML attributes.
CollapsiblePanel props
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keep the panel in the DOM while closed |
hiddenUntilFound | boolean | false | Use hidden="until-found" so closed content is reachable by browser find-in-page |
withPadding | boolean | true | Apply default panel padding (set to false when wrapping a Card or other padded surface) |
render | ReactElement | (props, state) => ReactElement | — | Base UI polymorphic prop — render as a different element while preserving panel behaviour |
Animates open and close via Base UI's --collapsible-panel-height CSS variable, transitioning the height with no layout-thrashing measurement.
Notes
- Built on
@base-ui/react/collapsible, which exposes the open state on the trigger asdata-panel-openand on the panel asdata-open/data-closed. - The animation transitions
heightbetween0andvar(--collapsible-panel-height)— works for any content height without explicit measurement. - For multi-item disclosures, prefer Accordion. For floating revealed content, prefer Popover or HoverCard.