Collapsible

An interactive component which expands and collapses a panel.

Order #4189

Status Shipped

Shipping address

100 Market St, San Francisco

Items

2x Studio Headphones

Component Code
<april:collapsible class="flex w-full max-w-md flex-col gap-2 rounded-lg border p-4">
<slot:trigger>
<div class="flex items-center justify-between gap-4 px-4">
<h4 class="text-sm font-semibold">Order #4189</h4>
<april:button variant="ghost" size="icon" class="size-8" aria-label="Toggle details">
<x-lucide-chevrons-up-down class="size-4" />
</april:button>
</div>
<div class="flex items-center justify-between rounded-md border px-4 py-2 text-sm">
<span class="text-muted-foreground">Status</span>
<span class="font-medium">Shipped</span>
</div>
</slot:trigger>
<slot:content class="flex flex-col gap-2">
<div class="rounded-md border px-4 py-2 text-sm">
<p class="font-medium">Shipping address</p>
<p class="text-muted-foreground">100 Market St, San Francisco</p>
</div>
<div class="rounded-md border px-4 py-2 text-sm">
<p class="font-medium">Items</p>
<p class="text-muted-foreground">2x Studio Headphones</p>
</div>
</slot:content>
</april:collapsible>

Usage

Use slot:trigger for the control and slot:content for the panel. The panel stays hidden until the trigger is activated.

<april:collapsible>
<slot:trigger>
<div class="flex items-center justify-between gap-4">
<h4 class="text-sm font-semibold">Order #4189</h4>
<april:button variant="ghost" size="icon" class="size-8" aria-label="Toggle details">
<x-lucide-chevrons-up-down class="size-4" />
</april:button>
</div>
<div class="mt-2 flex items-center justify-between rounded-md border px-4 py-2 text-sm">
<span class="text-muted-foreground">Status</span>
<span class="font-medium">Shipped</span>
</div>
</slot:trigger>
<slot:content>
<div class="rounded-md border px-4 py-2 text-sm">
<p class="font-medium">Shipping address</p>
<p class="text-muted-foreground">100 Market St, San Francisco</p>
</div>
<div class="mt-2 rounded-md border px-4 py-2 text-sm">
<p class="font-medium">Items</p>
<p class="text-muted-foreground">2x Studio Headphones</p>
</div>
</slot:content>
</april:collapsible>

Composition

The component has two named slots:

april:collapsible
├── slot:trigger
└── slot:content

Keep the trigger and content in the same april:collapsible component. The component connects them with id, aria-controls, and aria-labelledby attributes.

Controlled state

Use open to start expanded. Use x-model or wire:model when another state owns the value.

<div x-data="{ detailsOpen: false }">
<april:collapsible x-model="detailsOpen">
<slot:trigger>
<april:button variant="outline">Toggle details</april:button>
</slot:trigger>
<slot:content>These details follow the Alpine state.</slot:content>
</april:collapsible>
</div>
<p>&lt;april:collapsible wire:model=&quot;detailsOpen&quot;&gt;
<a href="slot:trigger">slot:trigger</a><a href="april:button">april:button</a>Toggle details&lt;/april:button&gt;&lt;/slot:trigger&gt;
<a href="slot:content">slot:content</a>These details follow the Livewire property.&lt;/slot:content&gt;
&lt;/april:collapsible&gt;

The component exposes its state through x-modelable="open", so Alpine and Livewire can update the same value.

Disabled

Set disabled to prevent the trigger from changing the panel state.

<april:collapsible disabled>
<slot:trigger>
<april:button variant="outline">Unavailable details</april:button>
</slot:trigger>
<slot:content>This panel cannot be opened.</slot:content>
</april:collapsible>

Nested panels

Place another april:collapsible in the content slot to create a nested panel.

<april:collapsible>
<slot:trigger><april:button variant="ghost">Project details</april:button></slot:trigger>
<slot:content>
<p>Project description.</p>
<april:collapsible>
<slot:trigger><april:button variant="ghost">Advanced details</april:button></slot:trigger>
<slot:content>Advanced project settings.</slot:content>
</april:collapsible>
</slot:content>
<p>&lt;/april:collapsible&gt;

API reference

Props

Prop Type Default Description
open boolean false Starts the panel in the open state.
disabled boolean false Prevents the trigger from changing the state.

Slots

Slot Description
trigger The button or control that toggles the panel.
content The panel content.

The root, trigger, and content expose data-state="open" or data-state="closed" for styling. The root exposes data-disabled when the component is disabled.

Press Enter or Space on the trigger to toggle the panel.

Publishing Views

Use the following command to publish this view:

php artisan april:publish collapsible
April UI keeps package views in `vendor/` by default. The command uses Laravel's vendor publishing system and copies overrides to `resources/views/vendor/april/components`. To publish all components, run:
php artisan april:publish --all
Review local overrides after an upgrade with `php artisan april:update --diff`.