Collapsible
An interactive component which expands/collapses a panel, built on the Base UI Collapsible primitive.
"use client";
import * as React from "react";
import { ChevronsUpDownIcon } from "lucide-react";
import { Button } from "@/registry/base/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/base/ui/collapsible";
export default function CollapsibleDemo() {
const [open, setOpen] = React.useState(false);
return (
<Collapsible
open={open}
onOpenChange={setOpen}
className="flex w-full max-w-sm flex-col gap-2"
>
<div className="flex items-center justify-between gap-4 px-4">
<h4 className="text-sm font-semibold">
@owuzan starred 3 repositories
</h4>
<CollapsibleTrigger
render={<Button variant="ghost" size="icon" className="size-8" />}
>
<ChevronsUpDownIcon className="size-4" />
<span className="sr-only">Toggle</span>
</CollapsibleTrigger>
</div>
<div className="rounded-md border px-4 py-2 font-mono text-sm">
shadcn-ui/ui
</div>
<CollapsibleContent className="flex flex-col gap-2">
<div className="rounded-md border px-4 py-2 font-mono text-sm">
mui/base-ui
</div>
<div className="rounded-md border px-4 py-2 font-mono text-sm">
useui/sevenui
</div>
</CollapsibleContent>
</Collapsible>
);
}
Installation
npx shadcn@latest add https://sevenui.dev/r/collapsible.jsonUsage
"use client";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
export default function CollapsibleDemo() {
return (
<Collapsible>
<CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
<CollapsibleContent>
Yes. Free to use for personal and commercial projects.
</CollapsibleContent>
</Collapsible>
);
}
Examples
File tree
Nested collapsibles with the open state styled through
data-panel-open on the trigger (the rotating chevron).
"use client";
import { ChevronRightIcon, FileIcon, FolderIcon } from "lucide-react";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/registry/base/ui/collapsible";
type TreeNode = { name: string; children?: TreeNode[] };
const tree: TreeNode[] = [
{
name: "src",
children: [
{
name: "components",
children: [{ name: "button.tsx" }, { name: "card.tsx" }],
},
{ name: "lib", children: [{ name: "utils.ts" }] },
{ name: "index.ts" },
],
},
{ name: "package.json" },
{ name: "README.md" },
];
function TreeItem({ node }: { node: TreeNode }) {
if (!node.children) {
return (
<div className="flex items-center gap-2 rounded-md px-2 py-1 text-sm">
<FileIcon className="size-4 text-muted-foreground" />
{node.name}
</div>
);
}
return (
<Collapsible defaultOpen={node.name === "src"}>
<CollapsibleTrigger className="group/tree flex w-full items-center gap-2 rounded-md px-2 py-1 text-sm outline-none hover:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50">
<ChevronRightIcon className="size-4 text-muted-foreground transition-transform group-data-panel-open/tree:rotate-90" />
<FolderIcon className="size-4 text-muted-foreground" />
{node.name}
</CollapsibleTrigger>
<CollapsibleContent className="pl-5">
{node.children.map((child) => (
<TreeItem key={child.name} node={child} />
))}
</CollapsibleContent>
</Collapsible>
);
}
export default function CollapsibleFileTree() {
return (
<div className="w-full max-w-xs rounded-lg border p-2">
{tree.map((node) => (
<TreeItem key={node.name} node={node} />
))}
</div>
);
}
API reference
Collapsible
Extends the
Base UI Collapsible
Root (a <div>).
| Prop | Type | Default |
|---|---|---|
open / defaultOpen |
boolean |
false |
onOpenChange |
(open: boolean) => void |
— |
disabled |
boolean |
false |
CollapsibleTrigger
Open state styles via data-panel-open (presence). A disabled trigger
stays focusable with aria-disabled="true" — style it with
data-disabled:, not disabled:.
CollapsibleContent
Closed content unmounts by default. keepMounted and hiddenUntilFound
are Panel props here (unlike Accordion, where they live on the
Root) — pass them through this component. Open/close animates via the
animate-collapsible-down / animate-collapsible-up utilities, whose
keyframes (driven by the Base UI-set --collapsible-panel-height
variable) ship in this component’s registry item — the CLI merges them
into your CSS, same as the accordion’s.
| Prop | Type | Default |
|---|---|---|
keepMounted |
boolean |
false |
hiddenUntilFound |
boolean |
false |