51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { type ReactNode, useState } from "react";
|
|
|
|
import { ChevronDown } from "lucide-react";
|
|
|
|
import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger } from "@common/components";
|
|
|
|
import { useSectionCollapsibleGroup } from "./section-collapsible-group";
|
|
|
|
interface SectionCollapsibleProps {
|
|
title: ReactNode;
|
|
defaultOpen?: boolean;
|
|
children: ReactNode;
|
|
}
|
|
|
|
function SectionCollapsible({ title, defaultOpen = true, children }: SectionCollapsibleProps) {
|
|
const group = useSectionCollapsibleGroup();
|
|
const [open, setOpen] = useState(group?.batchOpen ?? defaultOpen);
|
|
const [seenVersion, setSeenVersion] = useState(group?.batchVersion ?? 0);
|
|
|
|
if (group && group.batchVersion !== seenVersion) {
|
|
setSeenVersion(group.batchVersion);
|
|
setOpen(group.batchOpen);
|
|
}
|
|
|
|
const collapsibleProps = group ? { open, onOpenChange: setOpen } : { defaultOpen };
|
|
|
|
return (
|
|
<Collapsible {...collapsibleProps} className="mx-4 rounded-sm border bg-background">
|
|
<CollapsibleTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className="group flex w-full cursor-pointer items-center justify-between border-b p-4 text-left data-[state=closed]:border-b-0"
|
|
>
|
|
<h2 className="text-2xl font-bold">{title}</h2>
|
|
<ChevronDown
|
|
className={cn(
|
|
"size-6 shrink-0 text-muted-foreground transition-transform",
|
|
"group-data-[state=open]:rotate-180",
|
|
)}
|
|
/>
|
|
</button>
|
|
</CollapsibleTrigger>
|
|
<CollapsibleContent className="p-2">{children}</CollapsibleContent>
|
|
</Collapsible>
|
|
);
|
|
}
|
|
|
|
export { SectionCollapsible };
|