collapsible

An interactive component which expands and collapses a panel.

PreviousNext

@peduarte starred 3 repositories

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideChevronsUpDown } from '@ng-icons/lucide';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCollapsibleImports } from '@/shared/components/collapsible/collapsible.imports';

@Component({
  selector: 'z-demo-collapsible-default',
  imports: [ZardCollapsibleImports, ZardButtonComponent, NgIcon],
  template: `
    <z-collapsible class="flex w-[350px] flex-col gap-2">
      <div class="flex items-center justify-between gap-4 px-4">
        <h4 class="text-sm font-semibold">&#64;peduarte starred 3 repositories</h4>

        <button z-button z-collapsible-trigger zType="ghost" zSize="icon-sm">
          <ng-icon name="lucideChevronsUpDown" />
          <span class="sr-only">Toggle</span>
        </button>
      </div>

      <z-collapsible-content>
        <div class="flex flex-col gap-2">
          <div class="rounded-md border px-4 py-2 font-mono text-sm">&#64;radix-ui/primitives</div>
          <div class="rounded-md border px-4 py-2 font-mono text-sm">&#64;radix-ui/colors</div>
          <div class="rounded-md border px-4 py-2 font-mono text-sm">&#64;stitches/react</div>
        </div>
      </z-collapsible-content>
    </z-collapsible>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideChevronsUpDown })],
})
export class ZardDemoCollapsibleDefaultComponent {}

Installation

Copy
npx zard-cli@latest add collapsible

Usage

import { ZardCollapsibleImports } from '@/shared/components/collapsible/collapsible.imports';
Copy
<z-collapsible>
  <button z-collapsible-trigger>Toggle</button>
  <z-collapsible-content>Content</z-collapsible-content>
</z-collapsible>
Copy

Examples

controlled

Bind zOpen to a signal and listen to zOpenChange to drive the panel from outside the component.
The panel is open
Both buttons drive the same signal, so the component stays in sync with the host state.
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCollapsibleImports } from '@/shared/components/collapsible/collapsible.imports';

@Component({
  selector: 'z-demo-collapsible-controlled',
  imports: [ZardCollapsibleImports, ZardButtonComponent],
  template: `
    <div class="flex w-[350px] flex-col gap-3">
      <div class="flex items-center justify-between gap-4">
        <span class="text-muted-foreground text-sm">The panel is {{ open() ? 'open' : 'closed' }}</span>

        <button z-button zType="outline" zSize="sm" (click)="open.set(!open())">
          {{ open() ? 'Close' : 'Open' }} from outside
        </button>
      </div>

      <z-collapsible class="flex flex-col gap-2" [zOpen]="open()" (zOpenChange)="open.set($event)">
        <button z-button z-collapsible-trigger zType="secondary" zSize="sm">Toggle from inside</button>

        <z-collapsible-content>
          <div class="text-muted-foreground rounded-md border px-4 py-3 text-sm">
            Both buttons drive the same signal, so the component stays in sync with the host state.
          </div>
        </z-collapsible-content>
      </z-collapsible>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoCollapsibleControlledComponent {
  readonly open = signal(true);
}

disabled

Use zDisabled to block the trigger. The panel keeps whatever state it was rendered with.
The trigger is disabled, so this panel stays exactly as it was rendered.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCollapsibleImports } from '@/shared/components/collapsible/collapsible.imports';

@Component({
  selector: 'z-demo-collapsible-disabled',
  imports: [ZardCollapsibleImports, ZardButtonComponent],
  template: `
    <z-collapsible class="flex w-[350px] flex-col gap-2" zDisabled zOpen>
      <button z-button z-collapsible-trigger zType="outline" zSize="sm">Cannot be toggled</button>

      <z-collapsible-content>
        <div class="text-muted-foreground rounded-md border px-4 py-3 text-sm">
          The trigger is disabled, so this panel stays exactly as it was rendered.
        </div>
      </z-collapsible-content>
    </z-collapsible>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoCollapsibleDisabledComponent {}

API Reference

z-collapsible, [z-collapsible]Component

An interactive component which expands and collapses a panel. It renders no markup of its own, so it can also be applied as an attribute to an element that is already a component — for example li[z-sidebar-menu-item].

PropertyDescriptionTypeDefault
[zOpen] Open state of the panel. Supports two-way binding through [(zOpen)] boolean false
[zDisabled] Blocks the trigger from toggling the panel boolean false
[class] Additional CSS classes ClassValue ''
(zOpenChange) Emits the new open state whenever the panel toggles boolean

[z-collapsible-trigger]Component

Toggles the panel. Apply it to your own button — the directive only wires the behaviour and the ARIA attributes, it does not style anything.

PropertyDescriptionTypeDefault

z-collapsible-contentComponent

The panel revealed by the trigger. Animates its height with a CSS grid transition.

PropertyDescriptionTypeDefault
[class] Additional CSS classes ClassValue ''
github iconwhatsapp icondiscord iconX icon

Made with in Brazil. Open source and available on GitHub .