Skip to main content

Collapsible

Hide secondary content. Reduce visual noise. Improve focus.

Build settings

Framework preset detected: Vite. These values are used on every deployment.

1'use client';
2
3import { Collapsible } from '@/components/ui/collapsible';
4
5const advanced = [
6 { label: 'Build command', value: 'pnpm build' },
7 { label: 'Output directory', value: 'dist' },
8 { label: 'Install command', value: 'pnpm install --frozen-lockfile' },
9 { label: 'Node version', value: '22.x' },
10];
11
12export function Default() {
13 return (
14 <div className="border-border bg-card w-full max-w-md space-y-4 rounded-xl border p-4">
15 <div>
16 <p className="text-sm font-medium">Build settings</p>
17 <p className="text-muted-foreground text-xs">
18 Framework preset detected: Vite. These values are used on every deployment.
19 </p>
20 </div>
21
22 <Collapsible>
23 <Collapsible.Trigger>
24 <span className="text-sm font-medium">Advanced options</span>
25 </Collapsible.Trigger>
26 <Collapsible.Content>
27 <dl className="divide-border divide-y pt-3">
28 {advanced.map((setting) => (
29 <div key={setting.label} className="flex items-center justify-between gap-3 py-2">
30 <dt className="text-muted-foreground text-xs">{setting.label}</dt>
31 <dd className="bg-muted rounded px-2 py-1 font-mono text-xs">{setting.value}</dd>
32 </div>
33 ))}
34 </dl>
35 </Collapsible.Content>
36 </Collapsible>
37 </div>
38 );
39}

Installation

pnpm dlx nachui add collapsible

Anatomy

1import { Collapsible } from '@/components/ui/collapsible';
1<Collapsible>
2 <Collapsible.Trigger>Can I use this in my project?</Collapsible.Trigger>
3 <Collapsible.Content>Yes. Free to use for personal and commercial projects.</Collapsible.Content>
4</Collapsible>

Composition

Use the following composition to build a Collapsible:
Collapsible
├── Collapsible.Trigger
└── Collapsible.Content

Variants

Bordered

Collapsible with border and rounded corners.
Edge cache hits
286 GB
Origin responses
104 GB
Image optimization
22 GB
1'use client';
2
3import { Collapsible } from '@/components/ui/collapsible';
4
5const usage = [
6 {
7 title: 'Bandwidth',
8 total: '412 GB of 1 TB',
9 lines: [
10 { label: 'Edge cache hits', value: '286 GB' },
11 { label: 'Origin responses', value: '104 GB' },
12 { label: 'Image optimization', value: '22 GB' },
13 ],
14 },
15 {
16 title: 'Build minutes',
17 total: '318 of 400',
18 lines: [
19 { label: 'Production builds', value: '96 min' },
20 { label: 'Preview builds', value: '204 min' },
21 { label: 'Cancelled builds', value: '18 min' },
22 ],
23 },
24 {
25 title: 'Edge requests',
26 total: '2.4M of 5M',
27 lines: [
28 { label: 'API routes', value: '1.7M' },
29 { label: 'Static assets', value: '0.6M' },
30 { label: 'Redirects', value: '0.1M' },
31 ],
32 },
33];
34
35export function Bordered() {
36 return (
37 <div className="w-full max-w-md space-y-3">
38 {usage.map((group, index) => (
39 <Collapsible key={group.title} variant="bordered" defaultOpen={index === 0}>
40 <Collapsible.Trigger>
41 <span className="flex flex-col items-start">
42 <span className="text-sm font-medium">{group.title}</span>
43 <span className="text-muted-foreground text-xs">{group.total}</span>
44 </span>
45 </Collapsible.Trigger>
46 <Collapsible.Content>
47 <dl className="divide-border divide-y pt-1">
48 {group.lines.map((line) => (
49 <div key={line.label} className="flex items-center justify-between gap-3 py-2">
50 <dt className="text-muted-foreground text-xs">{line.label}</dt>
51 <dd className="text-xs font-medium tabular-nums">{line.value}</dd>
52 </div>
53 ))}
54 </dl>
55 </Collapsible.Content>
56 </Collapsible>
57 ))}
58 </div>
59 );
60}

Card

Collapsible with card styling including border, background, and shadow.
  1. 09:12Investigating slow responses on /v1/orders.
  2. 09:41Traced to a saturated read replica, traffic shifted to iad1.
  3. 10:05Latency back to normal, replica replaced.
1'use client';
2
3import { Badge } from '@/components/ui/badge';
4import { Collapsible } from '@/components/ui/collapsible';
5
6const incidents = [
7 {
8 title: 'Elevated API latency in eu-central',
9 date: 'Mar 14',
10 status: 'Resolved',
11 tone: 'success',
12 updates: [
13 { time: '09:12', text: 'Investigating slow responses on /v1/orders.' },
14 { time: '09:41', text: 'Traced to a saturated read replica, traffic shifted to iad1.' },
15 { time: '10:05', text: 'Latency back to normal, replica replaced.' },
16 ],
17 },
18 {
19 title: 'Webhook deliveries delayed',
20 date: 'Mar 12',
21 status: 'Monitoring',
22 tone: 'warning',
23 updates: [
24 { time: '17:20', text: 'Delivery queue backed up behind a retry storm.' },
25 { time: '17:55', text: 'Queue drained, watching retry rates for the next few hours.' },
26 ],
27 },
28] as const;
29
30export function Card() {
31 return (
32 <div className="w-full max-w-md space-y-3">
33 {incidents.map((incident, index) => (
34 <Collapsible key={incident.title} variant="card" defaultOpen={index === 0}>
35 <Collapsible.Trigger>
36 <span className="flex flex-col items-start gap-1">
37 <span className="flex items-center gap-2">
38 <Badge variant={incident.tone}>{incident.status}</Badge>
39 <span className="text-muted-foreground text-xs">{incident.date}</span>
40 </span>
41 <span className="text-left text-sm font-medium">{incident.title}</span>
42 </span>
43 </Collapsible.Trigger>
44 <Collapsible.Content>
45 <ol className="border-border ml-1 space-y-3 border-l pt-1 pl-4">
46 {incident.updates.map((update) => (
47 <li key={update.time} className="text-sm">
48 <span className="text-muted-foreground mr-2 font-mono text-xs">
49 {update.time}
50 </span>
51 {update.text}
52 </li>
53 ))}
54 </ol>
55 </Collapsible.Content>
56 </Collapsible>
57 ))}
58 </div>
59 );
60}

API Reference

Collapsible

PropTypeDefaultDescription
defaultOpenbooleanfalseInitial open state (uncontrolled mode).
openbooleanControlled open state.
onOpenChange(open: boolean) => voidCallback fired when the open state changes.
disabledbooleanfalseDisables interaction.
variant'default' | 'bordered' | 'card''default'Visual style of the collapsible container.
classNamestringAdditional classes.
childrenReact.ReactNodeContent inside the collapsible.

Collapsible.Trigger

PropTypeDefaultDescription
showChevronbooleantrueShows the chevron icon.
chevronIconReact.ReactNodeCustom icon for the chevron.
chevronPosition'left' | 'right''right'Position of the chevron icon.
asChildbooleanfalseAllows passing a custom child element as the trigger.
childrenReact.ReactNodeTrigger label or content.
onClick(event: React.MouseEvent) => voidClick handler (merged with open/close logic).
classNamestringAdditional classes.

Collapsible.Content

PropTypeDefaultDescription
forceMountbooleanfalseRenders content even when closed (useful for SSR).
childrenReact.ReactNodeContent to be revealed/collapsed.
classNamestringAdditional classes.
Found something to improve?

Notice a bug, typo, or missing detail on this page? Help us make the documentation better by opening a GitHub issue.

Create an Issue
Ctrl+I