Files
codetutor/frontend/src/components/ui/collapsible.tsx
T

55 lines
1.5 KiB
TypeScript

"use client";
import { useState, useId } from "react";
import { ChevronDown } from "lucide-react";
import { cn } from "@/lib/utils";
interface CollapsibleProps {
children: React.ReactNode;
title: React.ReactNode;
defaultOpen?: boolean;
className?: string;
}
export function Collapsible({
children,
title,
defaultOpen = false,
className,
}: CollapsibleProps) {
const [isOpen, setIsOpen] = useState(defaultOpen);
const contentId = useId();
return (
<div className={cn("border border-[var(--border)] rounded-lg", className)}>
<button
type="button"
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
aria-controls={contentId}
className="w-full flex items-center justify-between p-4 text-left hover:bg-[var(--secondary)] transition-colors rounded-lg focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-inset"
>
<span className="font-medium">{title}</span>
<ChevronDown
className={cn(
"h-5 w-5 text-[var(--muted-foreground)] transition-transform duration-200",
isOpen && "rotate-180"
)}
aria-hidden="true"
/>
</button>
<div
id={contentId}
role="region"
aria-labelledby={contentId}
className={cn(
"overflow-hidden transition-all duration-200 ease-in-out",
isOpen ? "max-h-[2000px] opacity-100" : "max-h-0 opacity-0"
)}
>
<div className="p-4 pt-0">{children}</div>
</div>
</div>
);
}