Collapsible
A panel that shows and hides with height motion you can reverse mid-way, without jumping the layout.
@preetsuthar17 starred 3 repositories
pnpm dlx shadcn@latest add https://hextaui.com/r/collapsible.jsonAdds the component, the HextaUI theme tokens and any HextaUI components it depends on.
Add the theme tokens to your global CSS, if you haven’t yet.
Install the dependencies.
pnpm add @base-ui/react @tabler/icons-react cnCopy and paste the following code into your project.
components/ui/collapsible.tsx Update the import paths to match your project setup.
Open by default
defaultOpen starts the panel open without taking over its state.
@preetsuthar17 starred 3 repositories
Show more
The panel sits above its trigger. When it closes, the gap in the parent’s flex layout collapses in the same animation, so the button below never jumps.
HextaUI components are built on Base UI primitives and styled with Tailwind. You own the source, so every class can be changed.
Motion is interruptible: clicking again mid-animation reverses from where the panel is instead of snapping. The gap between this paragraph and its neighbours collapses in the same animation, so nothing below jumps when it finishes.
Controlled
Pass open and onOpenChange to drive the panel from your own state. Toggling mid-animation reverses from where the panel is.
Release notes
Disabled
disabled on the root keeps the panel in its current state and makes the trigger ignore clicks and keys.
@preetsuthar17 starred 3 repositories
Custom icon
Children of <CollapsibleTriggerIcon /> replace the chevron. Style the open state with group-data-panel-open/collapsible-trigger.
Notes are only visible to you.
File tree
Each folder is its own collapsible. Outer panels grow smoothly as inner ones open.
- button.tsx
- collapsible.tsx
- card.tsx
- theme-provider.tsx
- layout.tsx
- page.tsx
- package.json
Inside a card
Closed panels stay in the page with hidden=“until-found”, so Cmd/Ctrl+F for “webhook” opens this one.
Unmounted when closed
Set hiddenUntilFound={false} on the content to remove it from the DOM while closed, for heavy panels you don’t want rendered up front.
Long content
Unbroken strings wrap inside the panel instead of widening the page.
Right to left
Chevrons mirror and nested indents follow the reading direction.
المستودعات المميزة
- button.tsx
- collapsible.tsx
- card.tsx
- theme-provider.tsx
- layout.tsx
- page.tsx
- package.json
| Key | Action |
|---|---|
| EnterSpace | Opens or closes the panel from the trigger. |
| Tab | Moves focus from the trigger into the open panel. Closed panels are skipped. |
- The trigger gets
aria-expandedandaria-controlsautomatically. - Icon-only triggers need an
aria-label.<CollapsibleTriggerIcon />is hidden from assistive tech. - With reduced motion the panel opens and closes without animating its height.
Built on the Base UI collapsible. Every part accepts the props of the primitive it wraps.
| Prop | Type | Default |
|---|---|---|
open | boolean | – |
defaultOpen | boolean | false |
onOpenChange | (open: boolean, details) => void | – |
disabled | boolean | false |
render | ReactElement | (props, state) => ReactElement | <div> |
| Attribute | Description |
|---|---|
data-slot="collapsible" | Target the root in CSS. |
data-open | Present when open. |
data-closed | Present when closed. |
| Prop | Type | Default |
|---|---|---|
renderUsually a Button. | ReactElement | (props, state) => ReactElement | <button> |
| Attribute | Description |
|---|---|
data-slot="collapsible-trigger" | Target the trigger in CSS. |
data-panel-open | Present when the panel is open. Style children with group-data-panel-open/collapsible-trigger. |
| Prop | Type | Default |
|---|---|---|
childrenThe default chevron flips when the panel opens. | ReactNode | <IconChevronDown /> |
render | ReactElement | (props, state) => ReactElement | <span> |
| Attribute | Description |
|---|---|
data-slot="collapsible-trigger-icon" | Hidden from assistive tech. Nudges down while the trigger is pressed. |
| Prop | Type | Default |
|---|---|---|
classNameApplied to the inner wrapper, so padding never fights the height animation. | string | – |
hiddenUntilFoundKeeps the closed panel in the DOM so page search can find and open it. | boolean | true |
keepMountedIgnored while hiddenUntilFound is on. | boolean | false |
| Attribute | Description |
|---|---|
data-slot="collapsible-content" | Target the panel in CSS. |
data-open | Present when open. |
data-closed | Present when closed. |
data-starting-style | Present while the panel animates in. |
data-ending-style | Present while the panel animates out. |
--collapsible-panel-height | The panel’s measured height. |
--collapsible-panel-width | The panel’s measured width. |
--collapsible-gap-start | The parent’s gap before the panel, collapsed while closed. |
--collapsible-gap-end | The parent’s gap after the panel, collapsed while closed. |