Kern Component Library GitHub GitHub

Disclosure

Expand/collapse primitive with accessible trigger and animated panel. Requires @alpinejs/collapse.
Requires Alpine.js

Default

This panel content is revealed when the trigger is clicked. Padding lives on the inner wrapper so the collapse animation stays smooth.
1{{ partial:components/primitives/disclosure label="Toggle disclosure" }}
2 This panel content is revealed when the trigger is clicked. Padding lives on the inner wrapper so the collapse
3 animation stays smooth.
4{{ /partial:components/primitives/disclosure }}

Initially Open

This disclosure starts expanded. Pass open="true" to set the initial state.
1{{ partial:components/primitives/disclosure label="What is a disclosure?" open="true" }}
2 This disclosure starts expanded. Pass
3 <code>open="true"</code>
4 to set the initial state.
5{{ /partial:components/primitives/disclosure }}

Custom Trigger

Use slot:trigger for any HTML content in the trigger button — icons, badges, or custom layouts.
1{{ partial:components/primitives/disclosure }}
2 {{ slot:trigger }}
3 {{ svg src="icons/star" class="size-4 shrink-0" aria-hidden="true" }}
4 Show details
5 {{ /slot:trigger }}
6 {{ slot:panel }}
7 Use
8 <code>slot:trigger</code>
9 for any HTML content in the trigger button — icons, badges, or custom layouts.
10 {{ /slot:panel }}
11{{ /partial:components/primitives/disclosure }}

Props

Name Type Default Description
label string Trigger button label text (falls back to slot:trigger, then "Toggle disclosure")
open boolean Initial expanded state
class string Additional classes merged via tw_merge (root element only)

Slots

Name Fallback / Default Description
default
panel default slot Collapsible panel content (falls back to default slot)
trigger label Trigger button content as HTML (overrides label)

Source

1{{#
2 @name Disclosure
3 @desc Expand/collapse primitive with accessible trigger and animated panel. Requires @alpinejs/collapse.
4 @param label string - Trigger button label text (falls back to slot:trigger, then "Toggle disclosure")
5 @param open boolean [false] - Initial expanded state
6 @param class string - Additional classes merged via tw_merge (root element only)
7 @slot trigger - Trigger button content as HTML (overrides label)
8 @slot panel - Collapsible panel content (falls back to default slot)
9#}}
10{{ _class = 'overflow-hidden rounded-default border border-border bg-background w-full {class}'
11 | tw_merge }}
12<div
13 class="{{ _class }}"
14 x-data="{ isOpen: {{ open == 'true' ? 'true' : 'false' }} }"
15 x-id="['disclosure-trigger', 'disclosure-panel']"
16>
17 {{ partial:components/primitives/button intent="ghost" class="group h-auto w-full justify-between gap-3 rounded-none px-4 py-3 text-left text-sm aria-expanded:bg-secondary/60 hover:bg-secondary/50" }}
18 {{ slot:attrs }}
19 :id="$id('disclosure-trigger')" :aria-expanded="isOpen" :aria-controls="$id('disclosure-panel')"
20 @click="isOpen = !isOpen"
21 {{ /slot:attrs }}
22 {{ if label }}
23 {{ label }}
24 {{ elseif slot:trigger }}
25 {{ slot:trigger }}
26 {{ else }}
27 Toggle disclosure
28 {{ /if }}
29 {{ slot:after }}
30 <span
31 class="text-muted-foreground shrink-0 transition-transform duration-200 group-aria-expanded:rotate-180"
32 aria-hidden="true"
33 >
34 {{ svg src="icons/chevron-down" class="size-5" }}
35 </span>
36 {{ /slot:after }}
37 {{ /partial:components/primitives/button }}
38 <div
39 x-show="isOpen"
40 x-collapse
41 :id="$id('disclosure-panel')"
42 role="region"
43 :aria-labelledby="$id('disclosure-trigger')"
44 style="display: none"
45 >
46 <div class="text-muted-foreground px-4 pt-1 pb-4 text-sm leading-relaxed">
47 {{ if slot:panel }}
48 {{ slot:panel }}
49 {{ else }}
50 {{ slot }}
51 {{ /if }}
52 </div>
53 </div>
54</div>

Dependencies

Packages

1composer require marcorieser/tailwind-merge-statamic
2npm install alpinejs @alpinejs/collapse

Internal dependency graph

Current

Disclosure

/primitives/disclosure

Transitive

None