shadcn.io is not affiliated with official shadcn/ui
Shadcn Collapsible for React and Tailwind
Collapsible content in a vertical stack.
Total visits
22.3%10.1%6.8%1.4%
Installation
bunx --bun shadcn@latest add https://kit.dev/r/collapsible.jsonpnpm dlx shadcn@latest add https://kit.dev/r/collapsible.jsonnpx shadcn@latest add https://kit.dev/r/collapsible.jsonyarn shadcn@latest add https://kit.dev/r/collapsible.jsonInstall the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactAdd the following to your globals.css.
@theme inline {
--animate-collapse: collapse 0.2s ease-out;
--animate-expand: expand 0.2s ease-out;
}
@keyframes collapse {
from { height: var(--height); }
to { height: var(--collapsed-height, 0); }
}
@keyframes expand {
from { height: var(--collapsed-height, 0); }
to { height: var(--height); }
}Copy and paste the following code into your project.
"use client";
import {
Collapsible as ArkCollapsible,
useCollapsible as useArkCollapsible,
useCollapsibleContext as useArkCollapsibleContext,
} from "@ark-ui/react/collapsible";
import { ChevronDownIcon } from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
export const useCollapsible = useArkCollapsible;
export const useCollapsibleContext = useArkCollapsibleContext;
export const CollapsibleContext = ArkCollapsible.Context;
const collapsibleRootClassName = "group/collapsible";
const splitCollapsedMount = (props: {
collapsedHeight?: React.ComponentProps<
typeof ArkCollapsible.Root
>["collapsedHeight"];
lazyMount?: boolean;
unmountOnExit?: boolean;
}) => {
const { collapsedHeight, lazyMount = true, unmountOnExit = true } = props;
const hasCollapsedHeight =
collapsedHeight !== undefined && collapsedHeight !== null;
return {
collapsedHeight,
"data-partial-collapse": hasCollapsedHeight ? "" : undefined,
lazyMount: hasCollapsedHeight ? false : lazyMount,
unmountOnExit: hasCollapsedHeight ? false : unmountOnExit,
};
};
export const Collapsible = (
props: React.ComponentProps<typeof ArkCollapsible.Root>
) => {
const { collapsedHeight, lazyMount, unmountOnExit, className, ...rest } =
props;
const mount = splitCollapsedMount({
collapsedHeight,
lazyMount,
unmountOnExit,
});
return (
<ArkCollapsible.Root
className={cn(collapsibleRootClassName, className)}
data-slot="collapsible"
{...mount}
{...rest}
/>
);
};
export const CollapsibleRootProvider = (
props: React.ComponentProps<typeof ArkCollapsible.RootProvider>
) => {
const { className, ...rest } = props;
return (
<ArkCollapsible.RootProvider
className={cn(collapsibleRootClassName, className)}
data-slot="collapsible"
{...rest}
/>
);
};
export const CollapsibleTrigger = (
props: React.ComponentProps<typeof ArkCollapsible.Trigger>
) => {
const { className, ...rest } = props;
return (
<ArkCollapsible.Trigger
className={cn(
"cursor-pointer",
"data-disabled:pointer-events-none data-disabled:opacity-64",
"has-data-[slot=collapsible-indicator]:[button]:justify-between",
className
)}
data-slot="collapsible-trigger"
{...rest}
/>
);
};
export const CollapsibleContent = (
props: React.ComponentProps<typeof ArkCollapsible.Content>
) => {
const { className, children, ...rest } = props;
return (
<ArkCollapsible.Content
className={cn(
"h-(--collapsed-height)",
"group-data-partial-collapse/collapsible:h-full",
"transition-[height] duration-200",
"overflow-hidden",
"data-[state=open]:animate-expand",
"data-[state=closed]:animate-collapse",
"motion-reduce:animate-none! motion-reduce:transition-none!"
)}
data-slot="collapsible-content"
{...rest}
>
<div className={className}>{children}</div>
</ArkCollapsible.Content>
);
};
export const CollapsibleIndicator = (
props: React.ComponentProps<typeof ArkCollapsible.Indicator>
) => {
const { className, children, ...rest } = props;
return (
<ArkCollapsible.Indicator
className={cn("data-[state=open]:[&_svg]:rotate-180", className)}
data-slot="collapsible-indicator"
{...rest}
>
{children ?? (
<ChevronDownIcon
aria-hidden="true"
className="transition-transform duration-200 motion-reduce:transition-none!"
/>
)}
</ArkCollapsible.Indicator>
);
};Update the import paths to match your project setup.
Anatomy
Collapsible
├── CollapsibleTrigger
├── CollapsibleContent
└── CollapsibleIndicatorUsage
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardAction,
CardDescription,
CardHeader,
} from "@/components/ui/card";
import {
Collapsible,
CollapsibleContent,
CollapsibleIndicator,
CollapsibleTrigger,
} from "@/components/ui/collapsible";<Card className="w-96">
<Collapsible>
<CardHeader title="Total visits">
<CardDescription asChild>
<div className="flex items-center gap-1">
<Badge variant="success">22.3%</Badge>
<Badge variant="info">10.1%</Badge>
<Badge variant="warning">6.8%</Badge>
<Badge variant="destructive">1.4%</Badge>
</div>
</CardDescription>
<CardAction>
<CollapsibleTrigger asChild>
<Button clickEffect={false} size="sm" variant="outline">
Details
<CollapsibleIndicator />
</Button>
</CollapsibleTrigger>
</CardAction>
</CardHeader>
<CollapsibleContent className="text-sm">
<div className="mt-(--space) grid gap-3 px-(--space)">
<div className="grid grid-cols-3 items-center gap-4">
<div className="col-span-2 text-muted-foreground">Google</div>
<div className="place-self-end">
<Badge variant="success">22.3%</Badge>
</div>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<div className="col-span-2 text-muted-foreground">Facebook</div>
<div className="place-self-end">
<Badge variant="destructive">-10.1%</Badge>
</div>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<div className="col-span-2 text-muted-foreground">TikTok</div>
<div className="place-self-end">
<Badge variant="warning">6.8%</Badge>
</div>
</div>
<div className="grid grid-cols-3 items-center gap-4">
<div className="col-span-2 text-muted-foreground">Instagram</div>
<div className="place-self-end">
<Badge variant="info">1.4%</Badge>
</div>
</div>
</div>
</CollapsibleContent>
</Collapsible>
</Card>Accessibility
| Key | Description |
|---|---|
Enter | Activate the focused control. |
Space | Activate the focused control. |
Demos
Context
Controlled
Default Open
Disabled
Lazy Mount
Nested
Partial Collapse
Root Provider
API Reference
Collapsible
div
PropType
AttributeType
CollapsibleTrigger
button
PropType
AttributeType
CollapsibleContent
div
PropType
AttributeType
CSS variableType
CollapsibleIndicator
div
PropType
AttributeType
CollapsibleRootProvider
div
PropType
AttributeType
useCollapsible
PropType
CollapsibleContext
PropType