Skip to content
Containment

Collapsible

A single disclosure: a header you press and the block it shows or hides.

Walkthrough

1. Basic

One header, one body. bind:open holds the state; the body grows to its own height and the chevron turns with it.

Karada, Street 62, house 14 — ring twice.

The courier calls from 07xx when they are ten minutes away.

<script lang="ts">	import { Collapsible, Text } from 'omaris';​	let open = $state(false);</script>​<div class="w-full max-w-md">	<Collapsible		bind:open		variant="outlined"		title="Delivery details"		supportingText="Tiger Express · today, 2–6 pm"	>		<div class="flex flex-col gap-2">			<Text variant="body-md">Karada, Street 62, house 14 — ring twice.</Text>			<Text variant="body-sm" tone="muted">				The courier calls from 07xx when they are ten minutes away.			</Text>		</div>	</Collapsible></div>

2. States

A leading icon and a count in end for a panel that says how much it holds; filled when it is a thing of its own; disabled with the reason in the supporting line.

No refunds yet.

<script lang="ts">	import { Badge, Collapsible, Switch, Text } from 'omaris';​	let open = $state(true);	let settings = $state({ spicy: true, vegan: false, delivery: true });</script>​<div class="flex w-full max-w-md flex-col gap-4">	<Collapsible bind:open variant="filled" title="Filters">		{#snippet icon()}			...		{/snippet}		{#snippet end()}			<Badge size="sm">{Object.values(settings).filter(Boolean).length}</Badge>		{/snippet}		<div class="flex flex-col gap-3">			<Switch bind:checked={settings.spicy} label="Spicy dishes" />			<Switch bind:checked={settings.vegan} label="Vegan only" />			<Switch bind:checked={settings.delivery} label="Delivers now" />		</div>	</Collapsible>​	<Collapsible		variant="outlined"		disabled		title="Refund history"		supportingText="Available once the order is delivered"	>		<Text variant="body-md" tone="muted">No refunds yet.</Text>	</Collapsible></div>

3. Custom trigger

Any button can be the trigger: trigger hands you aria-expanded, aria-controls and the toggle to spread on it. Here, the "More options" under a form's one required field.

<script lang="ts">	import { Button, Collapsible, Input } from 'omaris';​	let open = $state(false);</script>​<div class="flex w-full max-w-sm flex-col gap-2">	<Input label="Restaurant name" value="Beit Baghdad" />​	<Collapsible bind:open classes={{ inner: 'flex flex-col gap-4 px-0 pt-2' }}>		{#snippet trigger(props)}			<Button variant="text" size="sm" {...props}>				{open ? 'Fewer options' : 'More options'}				<svg					viewBox="0 0 24 24"					fill="none"					stroke="currentColor"					stroke-width="2"					aria-hidden="true"					class={[						'transition-[rotate] duration-300 ease-emphasized motion-reduce:transition-none',						open && 'rotate-180'					]}				>					<path d="m6 9 6 6 6-6" stroke-linecap="round" stroke-linejoin="round" />				</svg>			</Button>		{/snippet}		<Input label="Slug" value="beit-baghdad" />		<Input label="WhatsApp number" value="0770 123 4567" />	</Collapsible></div>

4. Overridden

Every part is reachable: class for the root, classes for the trigger, chevron and body. headingLevel makes the trigger a real heading for a disclosure that titles a section.

Faster menus, Kurdish plurals, and a lighter spinner.
<script lang="ts">	import { Collapsible } from 'omaris';</script>​<div class="w-full max-w-md">	<Collapsible		open		headingLevel={3}		variant="outlined"		title="Release notes"		supportingText="v2.4.0"		class="rounded-shape-2xl border-primary"		classes={{			trigger: 'bg-primary-container text-primary-container-foreground',			supporting: 'text-primary-container-foreground/80',			chevron: 'text-primary-container-foreground',			inner: 'pt-4 font-mono text-xs'		}}	>		Faster menus, Kurdish plurals, and a lighter spinner.	</Collapsible></div>