Collapsible

One region that shows and hides.

3 freelancers applied to this project

Usage

import { Collapsible } from "@voila.dev/ui/collapsible";
<Collapsible.Root>
	<Collapsible.Trigger render={<Button variant="ghost" size="icon-sm" />}>
		<CaretDownIcon />
	</Collapsible.Trigger>
	<Collapsible.Content>…</Collapsible.Content>
</Collapsible.Root>

One region with a trigger you design yourself, where Accordion is a set of them with a house style and single-open behaviour. If you are writing the same collapsible three times down a page, you wanted Accordion. If the hidden content should cover the page rather than push it down, that is a Popover or a Dialog — a collapsible always takes its space in the flow.

The trigger carries aria-expanded, so rotate the caret off that rather than tracking the open state in React. Collapsible.Root is uncontrolled by default; pass open and onOpenChange only when something outside the component has to close it.

Recipes

Trigger below the content

Northwind Trading is a wholesale importer working with 40 suppliers across Europe.

Nothing requires the trigger to sit above the content — Collapsible.Root is a plain wrapper and the parts can be ordered however the layout reads best. A "show more" link under a truncated paragraph is the common second shape.

Content that is closed is removed from the DOM. Two props change that, and they solve different problems: keepMounted keeps it mounted but hidden, for measuring or for children that must not lose their state; hiddenUntilFound uses hidden="until-found" so the browser's find-in-page can open the section when the match is inside it, which is what you want for FAQ-shaped content.

API

Collapsible.Root

PropTypeDefault
classNamestring | ((state: CollapsibleRootState) => string | undefined)CSS class applied to the element, or a function that returns a class based on the component's state.
defaultOpenbooleanWhether the collapsible panel is initially open. To render a controlled collapsible, use the open prop instead.
disabledbooleanWhether the component should ignore user interaction.
onOpenChange((open: boolean, eventDetails: CollapsibleRootChangeEventDetails) => void)Event handler called when the panel is opened or closed.
openbooleanWhether the collapsible panel is currently open. To render an uncontrolled collapsible, use the defaultOpen prop instead.
renderComponentRenderFn<HTMLProps, CollapsibleRootState> | ReactElement<unknown, string | JSXElementConstructor<any>>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleCSSProperties | ((state: CollapsibleRootState) => CSSProperties | undefined)Style applied to the element, or a function that returns a style object based on the component's state.

Plus the DOM props of the element it renders. Source: collapsible/components/collapsible-root.tsx.

Collapsible.Content

PropTypeDefault
classNamestring | ((state: CollapsiblePanelState) => string | undefined)CSS class applied to the element, or a function that returns a class based on the component's state.
hiddenUntilFoundbooleanAllows the browser's built-in page search to find and expand the panel contents. Overrides the keepMounted prop and uses hidden="until-found" to hide the element without removing it from the DOM.
keepMountedbooleanWhether to keep the element in the DOM while the panel is hidden. This prop is ignored when hiddenUntilFound is used.
renderComponentRenderFn<HTMLProps, CollapsiblePanelState> | ReactElement<unknown, string | JSXElementConstructor<any>>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleCSSProperties | ((state: CollapsiblePanelState) => CSSProperties | undefined)Style applied to the element, or a function that returns a style object based on the component's state.

Plus the DOM props of the element it renders. Source: collapsible/components/collapsible-content.tsx.

Collapsible.Trigger

PropTypeDefault
classNamestring | ((state: CollapsibleTriggerState) => string | undefined)CSS class applied to the element, or a function that returns a class based on the component's state.
nativeButtonbooleanWhether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).
renderComponentRenderFn<HTMLProps, CollapsibleTriggerState> | ReactElement<unknown, string | JSXElementConstructor<any>>Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
styleCSSProperties | ((state: CollapsibleTriggerState) => CSSProperties | undefined)Style applied to the element, or a function that returns a style object based on the component's state.

Plus the DOM props of the element it renders. Source: collapsible/components/collapsible-trigger.tsx.

Accordion · Section · Popover