Advanced Components

Collapsible

A container that expands and collapses to show or hide content. Useful for sidebars, menus, filters, nested lists, or any place where content needs to toggle from a trigger.

Example

A basic collapsible with a trigger and expandable content.

Basic collapsible
Multiple collapsibles
<div buiCollapsible>
<button
buiCollapsibleTrigger
class="flex items-center justify-between ..."
>
<span>Click to expand</span>
<mat-icon svgIcon="chevron-down" class="size-4 transition-transform group-data-[state=open]/bui-collapsible:rotate-180" />
</button>
<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>
<div class="p-4">
This is the collapsible content.
</div>
</div>
</ng-template>
</div>

Directives

The directives are standalone. Import only the slots the collapsible actually uses. Trigger, panel and content require the root.

import {
BuiCollapsible,
BuiCollapsibleContent,
BuiCollapsiblePanel,
BuiCollapsibleTrigger,
} from '@/bui/ui/collapsible';
DirectiveDescription
buiCollapsibleRoot directive that manages state and accessibility.
buiCollapsibleTriggerApplied to a clickable element to toggle the collapsible.
buiCollapsiblePanel Wraps content in an ng-template, rendered only when expanded.
buiCollapsibleContentMarks the animated content container inside the panel.

This is how the slots nest.

<div buiCollapsible>
<button buiCollapsibleTrigger>Toggle</button>

<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>
Content goes here
</div>
</ng-template>
</div>

Collapsible

The root directive. Apply it to any element to create a collapsible instance. It manages the expanded state, generates accessibility IDs, and exposes a data-state attribute for CSS hooks.

<!-- Default (collapsed) -->
<div buiCollapsible>...</div>

<!-- Expanded by default -->
<div buiCollapsible [(expanded)]="isExpanded">...</div>

<!-- Template reference -->
<div buiCollapsible #ref="buiCollapsible">...</div>
PropTypeDefaultDescription
expandedmodel<boolean>falseTwo-way binding for the expanded state.

Trigger

Apply buiCollapsibleTrigger to a button or any clickable element. It automatically sets aria-expanded, aria-controls, and keyboard support (Enter / Space). It also exposes data-state for CSS styling.

<button buiCollapsibleTrigger>Toggle</button>

Panel

The buiCollapsiblePanel directive goes on an ng-template. Its content is only rendered in the DOM when the collapsible is expanded and destroyed when collapsed.

<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>
Content rendered only when expanded
</div>
</ng-template>

Content

The buiCollapsibleContent directive marks the animated container inside the panel. It applies expand/collapse animations and connects to aria-labelledby for accessibility. It uses role="region" by default.

<div buiCollapsibleContent>
Animated content container
</div>
PropTypeDefaultDescription
enterAnimationstring'animate-collapsible-down'CSS animation class applied when expanding.
leaveAnimationstring'animate-collapsible-up'CSS animation class applied when collapsing.

Programmatic control

You can control the collapsible without a trigger. Use the expanded model for two-way binding, or grab a template reference via #ref="buiCollapsible" and call toggle().

<!-- Two-way binding -->
<div buiCollapsible [(expanded)]="isExpanded">
<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>...</div>
</ng-template>
</div>

<button (click)="isExpanded = !isExpanded">Toggle</button>

<!-- Template reference -->
<div buiCollapsible #myCollapsible="buiCollapsible">
<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>...</div>
</ng-template>
</div>

<button (click)="myCollapsible.toggle()">Toggle</button>

Expanded by default

Set [(expanded)] to a signal initialized to true to render the collapsible in its expanded state on mount. The enter animation is automatically skipped on the initial render so the content appears immediately without an animation flash.

Open on mount

This content was visible from the start without an animation. Toggle it to see the collapse and expand animations.

<!-- In the component class -->
private readonly isExpanded = signal(true);

<!-- In the template -->
<div buiCollapsible [(expanded)]="isExpanded">
<button buiCollapsibleTrigger class="...">
Already expanded
</button>
<ng-template buiCollapsiblePanel>
<div buiCollapsibleContent>
This content is visible from the start.
</div>
</ng-template>
</div>

CSS hooks

The collapsible exposes data-state on the root, trigger, and content elements. Use Tailwind's group-data-[state=open] selector (scoped via the group/bui-collapsible group) to style child elements based on the expanded state. For example, rotating a chevron icon:

<div buiCollapsible>
<button buiCollapsibleTrigger class="flex items-center gap-2">
<span>Toggle</span>
<mat-icon svgIcon="chevron-down" class="size-4 transition-transform group-data-[state=open]/bui-collapsible:rotate-180" />
</button>
...
</div>

See it in blocks

  • Collapsible sections folds documentation sections under a version selector.
  • Nested items nests a workspace tree three levels deep.
  • Auxiliary actions combines badges, section menus and per-row hover actions.
  • Calendar collapses the selection lists under a month calendar.
  • Filtering groups category, brand, price and availability filters.