Collapsible
An interactive component which expands and collapses content.
Preview
Loading...
import { useState } from "react";
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@/components/ui/Collapsible";
import { Button } from "@/components/ui/Button";
export function CollapsibleDemo() {
const [isOpen, setIsOpen] = useState(false);
const items = [
"React",
"TypeScript",
"Tailwind CSS",
"Radix UI",
"Vite",
"Vitest",
];
return (
<Collapsible className="w-full" open={isOpen} onOpenChange={setIsOpen}>
<div className="flex w-full items-center justify-between gap-1">
<span className="small font-semibold text-gray-12">
Technologies ({items.length})
</span>
<CollapsibleTrigger asChild>
<Button variant="menu" size="sm">
{isOpen ? "Hide All" : "Show All"}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent>
<ul className="small space-y-0.5 pt-1 font-normal text-gray-11">
{items.map((item) => (
<li key={item} className="flex items-center gap-0.5">
<span
aria-hidden="true"
className="size-0.5 shrink-0 rounded-full bg-accent-9"
/>
{item}
</li>
))}
</ul>
</CollapsibleContent>
</Collapsible>
);
}Usage
Open
Loading...
import { useState } from "react";
import {
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@/components/ui/Collapsible";
import { Button } from "@/components/ui/Button";
export function CollapsibleDemoOpen() {
const [isOpen, setIsOpen] = useState(true);
const items = [
"React",
"TypeScript",
"Tailwind CSS",
"Radix UI",
"Vite",
"Vitest",
];
return (
<Collapsible className="w-full" open={isOpen} onOpenChange={setIsOpen}>
<div className="flex w-full items-center justify-between gap-1">
<span className="small font-semibold text-gray-12">
Technologies ({items.length})
</span>
<CollapsibleTrigger asChild>
<Button variant="menu" size="sm">
{isOpen ? "Hide All" : "Show All"}
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent>
<ul className="small space-y-0.5 pt-1 font-normal text-gray-11">
{items.map((item) => (
<li key={item} className="flex items-center gap-0.5">
<span
aria-hidden="true"
className="size-0.5 shrink-0 rounded-full bg-accent-9"
/>
{item}
</li>
))}
</ul>
</CollapsibleContent>
</Collapsible>
);
}Controlled
Extract the Preview markup into TechnologiesCollapsible with open and onOpenChange props, then own that state in the parent.
Loading...
import { useState } from "react";
export function CollapsibleDemoControlled() {
const [isOpen, setIsOpen] = useState(false);
return <TechnologiesCollapsible open={isOpen} onOpenChange={setIsOpen} />;
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/collapsibleManual
Install the following dependencies:
pnpm install radix-uiCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the Collapsible component into your components/ui/Collapsible.tsx file.
"use client";
import { Collapsible as CollapsibleRadix } from "radix-ui";
import { cn } from "@/utils/class-names";
function Collapsible({
...props
}: React.ComponentProps<typeof CollapsibleRadix.Root>) {
return <CollapsibleRadix.Root data-slot="collapsible" {...props} />;
}
function CollapsibleTrigger({
...props
}: React.ComponentProps<typeof CollapsibleRadix.CollapsibleTrigger>) {
return (
<CollapsibleRadix.CollapsibleTrigger
data-slot="collapsible-trigger"
{...props}
/>
);
}
function CollapsibleContent({
className,
...props
}: React.ComponentProps<typeof CollapsibleRadix.CollapsibleContent>) {
return (
<CollapsibleRadix.CollapsibleContent
className={cn(
"overflow-hidden data-[state=closed]:animate-collapsible-up data-[state=open]:animate-collapsible-down",
className
)}
data-slot="collapsible-content"
{...props}
/>
);
}
export { Collapsible, CollapsibleTrigger, CollapsibleContent };