Collapsible
A trigger that shows and hides one region in place. Use it for details, longer lists, and settings that most people do not need every time.
Open by default
Show or hide sample project details. Nothing is loaded or saved.
The sample Meadow project has three tasks and two team members.
Closed by default
Show or hide sample project details. Nothing is loaded or saved.
Usage
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@tulipfarm/sprout/collapsible";
import { Button } from "@tulipfarm/sprout/button";
<Collapsible>
<CollapsibleTrigger render={<Button variant="ghost" size="sm" />}>
Approval details
</CollapsibleTrigger>
<CollapsibleContent>
<p>Only the listed changes are approved.</p>
</CollapsibleContent>
</Collapsible>Collapsible holds the open state. Pass defaultOpen to let it manage itself, or open and onOpenChange to control it. disabled blocks the trigger.
Triggers
The trigger is unstyled. Give it a Sprõut Button with render. Use outline for a main section, ghost for secondary details, xs and link inside dense status rows, andchat-row for full-width rows inside a list.
Trigger pairings
Each trigger renders a Sprõut Button. Variant and size follow how much weight the hidden content has.
Retries: 3 attempts, 30 seconds apart.
Time zone: Europe/Amsterdam. Runs pause on public holidays.
2 Drive folders and 1 shared drive are searchable in chat.
Only the listed changes are approved. Each table applies as one unit. Completed tables stay applied if later work stops.
- Every invoice has an owner: passed
call_7f2a91c4e0b8 - Totals match the ledger: passed
call_3b19d0aa6f52
Content variants
<CollapsibleContent>…</CollapsibleContent> // instant
<CollapsibleContent variant="sidebar">…</CollapsibleContent> // height and fade
<CollapsibleContent variant="card">…</CollapsibleContent> // height onlyContent variants
CollapsibleContent variant sets how the panel enters and leaves. Reduced motion turns every transition off.
Shows and hides at once, for short notes under a control.
- Only the listed changes are approved.
Grows and fades in 180ms, for nested navigation.
Grows in 180ms inside a bordered card.
- Invoices: 6 fields
- Vendors: 4 fields
Indicators
<CollapsibleTrigger>
<Sparkle aria-hidden="true" />
Thought for 12s
<ChevronDown aria-hidden="true" data-slot="collapsible-indicator" />
</CollapsibleTrigger>
<ChevronRight
aria-hidden="true"
data-slot="collapsible-indicator"
data-direction="right"
/>Mark a chevron with data-slot="collapsible-indicator" and it turns 180° while open. Add data-direction="right" for a right chevron that turns 90°. It works inside the trigger, and anywhere in the header outside the content, so a chevron can sit beside a badge. To swap the icon or label instead, read the state you control.
Reasoning and sources
Plain triggers with an icon, a label, and a turning chevron. Text stays muted until hover.
Activity
The root is a labelled region. Content stays mounted, so the scroll position survives a close.
Tool calls
A full-width header trigger carries the name, a status badge, and a summary that wraps.
Input
{ "filter": "due<2026-10-18;status!=paid" }The Invoices table took too long to answer.
Cards
Put the trigger in the heading and stretch its hit area over the header with a pseudo-element. Control open to close the card when the review settles.
Review card
The whole header is the hit area. The chevron sits outside the trigger and still turns. Settling the review closes the card.
- Invoices: number, vendor, amount, due date, status, owner
- Vendors: name, contact, payment terms, country
Sidebar
Render a SidebarMenuAction as the trigger and use the sidebar content variant. Close the list while the sidebar shows only icons.
const { isMobile, state } = useSidebar();
const visible = open && (isMobile || state === "expanded");
<Collapsible open={visible} onOpenChange={setOpen}>
<SidebarMenuButton …>Chats</SidebarMenuButton>
<CollapsibleTrigger
aria-label={`${visible ? "Collapse" : "Expand"} Chats`}
render={<SidebarMenuAction />}
>
<ChevronRight data-slot="collapsible-indicator" data-direction="right" />
</CollapsibleTrigger>
<CollapsibleContent variant="sidebar">
<SidebarMenuSub aria-label="Recent chats">…</SidebarMenuSub>
</CollapsibleContent>
</Collapsible>Sidebar recent items
A SidebarMenuAction is the trigger. The sidebar content variant grows the nested list.
States
Content can sit before the trigger so a list grows from its button. keepMounted keeps closed content in the page, so form state and scroll position survive. Pass open with no trigger to show a fixed list.
Disabled
A disabled root blocks the trigger. Say why next to it.
The details cannot be opened in this disabled sample.
Content above the trigger
Put the content first and the list grows upward from the button. The label and icon follow the open state.
Start with a task
- Summarize unread email
- Plan my week
Mount on first open
keepMounted keeps the panel in the page. Render the children only after the first open to defer their work.
Always open
Pass open with no trigger to show the content as a fixed list, with loading and error rows inside.
- Searched Drive for “Q3 planning”
- Read Q3 planning notes
- Read Vendor contract — Northwind
API
The three parts wrap Base UI Collapsible. Every Base UI prop works, including render, keepMounted, hiddenUntilFound, and className as a string or a state function.
Parts get data-slot values of collapsible, collapsible-trigger, and collapsible-content. Pass your own data-slot to rename a root. The root has data-open or data-closed, the trigger has data-panel-open, and the content has data-variant plus Base UI's starting and ending style attributes. collapsibleContentVariantNames lists the variants.
Accessibility
The trigger is a button with aria-expanded and aria-controls. Enter and Space toggle it. Give icon-only triggers an aria-label that names the action, and link a disabled trigger to its reason with aria-describedby. Put the trigger inside a heading when it names a section.
Chevrons turn over 120ms and animated content grows over 180ms. Both stop when reduced motion is requested.
Theme tokens
Collapsible uses --sprout-focus, --sprout-radius-control, --sprout-motion-fast, --sprout-motion-normal, and --sprout-motion-ease. Everything else comes from the trigger and content you render, so it follows light, dark, and the TulipFarm theme.