Collapsible
A headless show-and-hide panel that animates on its measured height.
npx shadcn@latest add @velaui/collapsiblepnpm dlx velaui add @velaui/collapsibleyarn dlx shadcn@latest add @velaui/collapsiblebunx --bun shadcn@latest add @velaui/collapsibleveni add collapsibleInstalls the copy of vela-ui that veni-builder serves to Venizia apps; veni-builder serves the Radix UI copy only, so this tab exists for that base alone.
npx shadcn@latest add @velaui/collapsiblepnpm dlx velaui add @velaui/collapsibleyarn dlx shadcn@latest add @velaui/collapsiblebunx --bun shadcn@latest add @velaui/collapsibleExamples
- Default
Usage
import * as React from "react";
import { ChevronDown } from "@/components/icons/chevron-down";
import { Button } from "@/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
export default function Example() {
const [open, setOpen] = React.useState(false);
return (
<Collapsible open={open} onOpenChange={setOpen} className="w-full max-w-sm">
<div className="flex items-center justify-between gap-4">
<p className="text-sm font-medium text-text-strong">
3 repositories starred
</p>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="icon-sm" aria-label="Toggle list">
<ChevronDown
className={open ? "rotate-180 transition-transform" : "transition-transform"}
/>
</Button>
</CollapsibleTrigger>
</div>
<div className="mt-2 rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/ignis
</div>
<CollapsibleContent className="flex flex-col gap-2 pt-2">
<div className="rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/velaui
</div>
<div className="rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/ardor
</div>
</CollapsibleContent>
</Collapsible>
);
}import * as React from "react";
import { ChevronDown } from "@/components/icons/chevron-down";
import { Button } from "@/components/ui/button";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
export default function Example() {
const [open, setOpen] = React.useState(false);
return (
<Collapsible open={open} onOpenChange={setOpen} className="w-full max-w-sm">
<div className="flex items-center justify-between gap-4">
<p className="text-sm font-medium text-text-strong">
3 repositories starred
</p>
<CollapsibleTrigger
render={
<Button variant="ghost" size="icon-sm" aria-label="Toggle list">
<ChevronDown
className={
open
? "rotate-180 transition-transform"
: "transition-transform"
}
/>
</Button>
}
/>
</div>
<div className="mt-2 rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/ignis
</div>
<CollapsibleContent className="flex flex-col gap-2 pt-2">
<div className="rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/velaui
</div>
<div className="rounded-lg border border-border-default px-3 py-2 text-sm">
venizia/ardor
</div>
</CollapsibleContent>
</Collapsible>
);
}Props
Collapsible
Takes every prop of CollapsibleProps.
CollapsibleContent
Takes every prop of CollapsibleContentProps.
CollapsibleTrigger
Takes every prop of CollapsibleTriggerProps.
Dependencies
- npm
radix-ui@1.6.0- Installs with it
- nothing else
- npm
@base-ui/react@1.6.0- Installs with it
- nothing else
Source
components/ui/collapsible.tsx
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
import { cn } from "@/lib/utils";
export type CollapsibleProps = React.ComponentProps<typeof CollapsiblePrimitive.Root>;
/**
* Collapsible — a headless show/hide primitive. It carries no design of its
* own; the trigger and the panel are whatever the caller renders inside it.
* The content animates on its measured height, which Radix publishes as
* `--radix-collapsible-content-height`.
*/
function Collapsible({
...props
}: CollapsibleProps) {
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
}
export type CollapsibleTriggerProps = React.ComponentProps<typeof CollapsiblePrimitive.Trigger>;
function CollapsibleTrigger({
...props
}: CollapsibleTriggerProps) {
return (
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
);
}
export type CollapsibleContentProps = React.ComponentProps<typeof CollapsiblePrimitive.Content>;
function CollapsibleContent({
className,
...props
}: CollapsibleContentProps) {
return (
<CollapsiblePrimitive.Content
data-slot="collapsible-content"
className={cn(
"overflow-hidden data-open:animate-collapsible-down data-closed:animate-collapsible-up",
className,
)}
{...props}
/>
);
}
export { Collapsible, CollapsibleContent, CollapsibleTrigger };components/ui/collapsible.tsx
import { Collapsible as CollapsiblePrimitive } from "@base-ui/react/collapsible";
import { cn } from "@/lib/utils";
export type CollapsibleProps = React.ComponentProps<typeof CollapsiblePrimitive.Root>;
/**
* Collapsible — a headless show/hide primitive. It carries no design of its
* own; the trigger and the panel are whatever the caller renders inside it.
* The content animates on its measured height, which Base UI publishes as
* `--collapsible-panel-height`.
*/
function Collapsible({
...props
}: CollapsibleProps) {
return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
}
export type CollapsibleTriggerProps = React.ComponentProps<typeof CollapsiblePrimitive.Trigger>;
function CollapsibleTrigger({
...props
}: CollapsibleTriggerProps) {
return (
<CollapsiblePrimitive.Trigger data-slot="collapsible-trigger" {...props} />
);
}
export type CollapsibleContentProps = React.ComponentProps<typeof CollapsiblePrimitive.Panel>;
function CollapsibleContent({
className,
...props
}: CollapsibleContentProps) {
return (
<CollapsiblePrimitive.Panel
data-slot="collapsible-content"
className={cn(
"h-(--collapsible-panel-height) overflow-hidden transition-[height] duration-200 ease-out data-starting-style:h-0 data-ending-style:h-0",
className,
)}
{...props}
/>
);
}
export { Collapsible, CollapsibleContent, CollapsibleTrigger };