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/registry/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/registry/ui/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>
Prop Type Default
class string ""
open boolean false
hiddenUntilFound boolean false
Expanded by default
This content is visible by default
---
import { ChevronsUpDownIcon } from '@lucide/astro';
import { Button } from '@bejamas/registry/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/registry/ui/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/registry/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/registry/ui/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/registry/ui/button';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@bejamas/registry/ui/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>
Prop Element Values Default
open collapsible boolean false
hiddenUntilFound collapsible boolean false
animation collapsible-content none, slide none

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

The collapsible emits custom events that you can listen to:

Event Detail Description
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:

Attribute Element Description
data-state collapsible, collapsible-content Current state (open or closed)
data-hidden-until-found collapsible Enables hidden="until-found" when closed
data-starting-style collapsible-content Added while enter transition styles are applied
data-ending-style collapsible-content Added while exit transition styles are applied

The collapsible content exposes size variables for dimension animations:

Variable Element Description
--collapsible-panel-height collapsible-content Measured panel height
--collapsible-panel-width collapsible-content Measured panel width