fifth/ui

Collapsible

Customizable animated collapsible element using Framer Motion + Radix-UI

Pasithea

Pasithea

import {
	Collapsible,
	CollapsibleContent,
	CollapsibleItem,
	CollapsibleTrigger,
} from "@/components/collapsible";

import {
	CaretDownIcon,
	GithubLogoIcon,
} from "@phosphor-icons/react";

export function CollapsibleDevsDemo() {
	const [open, setOpen] = useState(false);

	const comments: { name: string; pfp: string; link: string }[] = [
		{
			name: "Pasithea",
			pfp: "https://github.com/Pasithea0.png",
			link: "https://github.com/Pasithea0",
		},
		{
			name: "FifthWit",
			pfp: "https://github.com/FifthWit.png",
			link: "https://github.com/FifthWit",
		},
		{
			name: "shadcn",
			pfp: "https://github.com/shadcn.png",
			link: "https://github.com/shadcn",
		},
	];

	return (
		<div className="flex flex-col h-screen max-h-80">
			<Collapsible open={open} onOpenChange={setOpen}>
				<div className="flex flex-col items-center w-full">
					<CollapsibleTrigger
						className="flex flex-row justify-center items-center gap-1 w-fit min-h-12"
						asChild
					>
						<Button variant="ghost">
							Cool Developers
							<span
								aria-hidden
								data-open={open}
								className="bg-accent p-1 rounded-full aspect-square text-accent-foreground flex data-open:-rotate-180 transition-all"
							>
								<CaretDownIcon />
							</span>
						</Button>
					</CollapsibleTrigger>
					<div className="w-full">
						<CollapsibleContent>
							{comments.map((c) => (
								<CollapsibleItem
									key={c.name}
									className="flex flex-row gap-2 items-center"
								>
									<Avatar>
										<AvatarImage src={c.pfp} />
										<AvatarFallback>{c.name}</AvatarFallback>
									</Avatar>
									<h2>{c.name}</h2>
									<Button variant="ghost" onClick={() => window.open(c.link)}>
										<GithubLogoIcon />
									</Button>
								</CollapsibleItem>
							))}
						</CollapsibleContent>
					</div>
				</div>
			</Collapsible>
		</div>
	);
}

Installation

npx shadcn@latest add https://raw.githubusercontent.com/FifthWit/ui/refs/heads/main/public/r/collapsible.json
pnpm dlx shadcn@latest add https://raw.githubusercontent.com/FifthWit/ui/refs/heads/main/public/r/collapsible.json
deno run -A npm:shadcn@latest add https://raw.githubusercontent.com/FifthWit/ui/refs/heads/main/public/r/collapsible.json
bunx shadcn@latest add https://raw.githubusercontent.com/FifthWit/ui/refs/heads/main/public/r/collapsible.json

Anatomy

import {
	Collapsible,
	CollapsibleContent,
	CollapsibleItem,
	CollapsibleTrigger,
} from "@/components/collapsible";

export default () => (
  <Collapsible>
    <CollapsibleTrigger></CollapsibleTrigger>
    <CollapsibleContent>
      <CollapsibleItem></CollapsibleItem>
    </CollapsibleContent>
  </Collapsible>
)

Examples

Scroll Area

wrapping collapsible in the shadcn ScrollArea

Next.js

Next.js

SSR + DX should be at the cost of using Vercel

export function CollapsibleNotificiationsDemo() {
	const [open, setOpen] = useState(false);

	const comments: {
		name: string;
		pfp: string;
		comment: string;
	}[] = [
		{
			name: "Next.js",
			pfp: "https://github.com/nextjs.png",
			comment: "SSR + DX should be at the cost of using Vercel",
		},
		{
			name: "TypeScript",
			pfp: "https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Typescript.svg/1280px-Typescript.svg.png",
			comment: "TypeScript > JSDoc",
		},
		{
			name: "React.js",
			pfp: "https://github.com/reactjs.png",
			comment: "We're a library, not a framework!!!!!!",
		},
		{
			name: "TailwindCSS",
			pfp: "https://github.com/tailwindlabs.png",
			comment:
				"If anyone is a recovering Tailwind addict, there is no hope, keep using it.",
		},
		{
			name: "Radix-UI",
			pfp: "https://github.com/radix-ui.png",
			comment: "Primitives are the way",
		},
		{
			name: "Fumadocs",
			pfp: "https://www.fumadocs.dev/icon.png?icon.f741d7a1.png",
			comment: "MDX is life.",
		},
	];

	return (
		<div className="flex flex-col bg-card p-4 rounded-lg w-sm aspect-3/4">
			<Collapsible open={open} onOpenChange={setOpen}>
				<CollapsibleTrigger
					className="flex flex-row justify-center items-center gap-1 w-fit min-h-12"
					asChild
				>
					<Button variant="ghost">
						ReactCord
						<span
							aria-hidden
							data-open={open}
							className="bg-accent p-1 rounded-full aspect-square text-accent-foreground flex data-open:-rotate-180 transition-all"
						>
							<CaretDownIcon />
						</span>
					</Button>
				</CollapsibleTrigger>
				<ScrollArea className="h-100">
					<CollapsibleContent>
						{comments.map((c) => (
							<CollapsibleItem
								key={c.name}
								className="flex flex-row items-center gap-2"
							>
								<Avatar>
									<AvatarImage src={c.pfp} />
									<AvatarFallback>{c.name}</AvatarFallback>
								</Avatar>
								<div className="w-full flex flex-col">
									<p className="text-xs text-muted-foreground">{c.name}</p>
									<p className="text-sm">{c.comment}</p>
								</div>
							</CollapsibleItem>
						))}
					</CollapsibleContent>
				</ScrollArea>
			</Collapsible>
		</div>
	);
}

Props

<Collapsible />

Prop

Type

<CollapsibleTrigger />

Prop

Type

<CollapsibleContent />

Prop

Type

<CollapsibleItem />

Prop

Type

On this page