Skip to content

Collapsible

An interactive component that expands and collapses content sections.

@thomkrupa starred 3 repositories
@data-slot/collapsible
@bejamas/ui
@astrojs/astro
---
import { ChevronsUpDownIcon } from '@lucide/astro';
import { Button } from '@bejamas/ui/components/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/ui/components/collapsible';
---
<Collapsible class="w-[350px] flex flex-col gap-2">
<div class="flex items-center justify-between gap-4 px-4">
<span class="text-sm font-semibold">@thomkrupa starred 3 repositories</span>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="icon" class="size-8">
<ChevronsUpDownIcon class="size-4" />
<span class="sr-only">Toggle</span>
</Button>
</CollapsibleTrigger>
</div>
<div class="rounded-md border px-4 py-2 font-mono text-sm">@data-slot/collapsible</div>
<CollapsibleContent animation="slide" class="flex flex-col gap-2">
<div class="rounded-md border px-4 py-2 font-mono text-sm">@bejamas/ui</div>
<div class="rounded-md border px-4 py-2 font-mono text-sm">@astrojs/astro</div>
</CollapsibleContent>
</Collapsible>
Terminal window
bunx bejamas add collapsible
---
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@bejamas/ui/components/collapsible';
import { Button } from '@bejamas/ui/components/button';
---
<Collapsible>
<CollapsibleTrigger>
<Button variant="ghost">Toggle</Button>
</CollapsibleTrigger>
<CollapsibleContent animation="slide">
Hidden content here
</CollapsibleContent>
</Collapsible>
PropTypeDefault
classstring""
openbooleanfalse
hiddenUntilFoundbooleanfalse
Expanded by default
This content is visible by default
---
import { ChevronsUpDownIcon } from '@lucide/astro';
import { Button } from '@bejamas/ui/components/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/ui/components/collapsible';
---
<Collapsible open class="w-[350px] flex flex-col gap-2">
<div class="flex items-center justify-between gap-4 px-4">
<span class="text-sm font-semibold">Expanded by default</span>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="icon" class="size-8">
<ChevronsUpDownIcon class="size-4" />
<span class="sr-only">Toggle</span>
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent class="flex flex-col gap-2">
<div class="rounded-md border px-4 py-2 font-mono text-sm">This content is visible by default</div>
</CollapsibleContent>
</Collapsible>
This content animates panel height using CSS variables.
---
import { Button } from '@bejamas/ui/components/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/ui/components/collapsible';
---
<Collapsible class="w-[350px] flex flex-col gap-2">
<CollapsibleTrigger asChild>
<Button variant="outline">Toggle with slide</Button>
</CollapsibleTrigger>
<CollapsibleContent animation="slide" class="pt-2">
<div class="rounded-md border px-4 py-2 text-sm">
This content animates panel height using CSS variables.
</div>
</CollapsibleContent>
</Collapsible>
Search this sentence with browser find to auto-expand.
---
import { Button } from '@bejamas/ui/components/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/ui/components/collapsible';
---
<Collapsible hiddenUntilFound class="w-[350px] flex flex-col gap-2">
<CollapsibleTrigger asChild>
<Button variant="outline">Toggle hidden-until-found content</Button>
</CollapsibleTrigger>
<CollapsibleContent class="pt-2">
<div class="rounded-md border px-4 py-2 text-sm">
Search this sentence with browser find to auto-expand.
</div>
</CollapsibleContent>
</Collapsible>
PropElementValuesDefault
opencollapsiblebooleanfalse
hiddenUntilFoundcollapsiblebooleanfalse
animationcollapsible-contentnone, slidenone

slide uses --collapsible-panel-height for smooth height transitions.

The collapsible emits custom events that you can listen to:

EventDetailDescription
collapsible:change{ open: boolean }Fired when the open state changes
Hidden content
<Collapsible id="my-collapsible">
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
<CollapsibleContent>Hidden content</CollapsibleContent>
</Collapsible>
const collapsible = document.getElementById('my-collapsible');
collapsible.addEventListener('collapsible:change', (e) => {
console.log('Is open:', e.detail.open);
});

You can control the collapsible programmatically by dispatching a collapsible:set event:

const collapsible = document.getElementById('my-collapsible');
// Open the collapsible
collapsible.dispatchEvent(new CustomEvent('collapsible:set', {
detail: { open: true }
}));
// Close the collapsible
collapsible.dispatchEvent(new CustomEvent('collapsible:set', {
detail: { open: false }
}));

The collapsible sets these data attributes that you can use for styling or querying state:

AttributeElementDescription
data-statecollapsible, collapsible-contentCurrent state (open or closed)
data-hidden-until-foundcollapsibleEnables hidden="until-found" when closed
data-starting-stylecollapsible-contentAdded while enter transition styles are applied
data-ending-stylecollapsible-contentAdded while exit transition styles are applied

The collapsible content exposes size variables for dimension animations:

VariableElementDescription
--collapsible-panel-heightcollapsible-contentMeasured panel height
--collapsible-panel-widthcollapsible-contentMeasured panel width