53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import React, { useState } from "react";
|
||
|
|
import { ChevronDown, ChevronRight } from "lucide-react";
|
||
|
|
import { ConfigSectionDefinition } from "./ConfigPanelTypes";
|
||
|
|
|
||
|
|
interface ConfigSectionProps {
|
||
|
|
section: ConfigSectionDefinition;
|
||
|
|
children: React.ReactNode;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function ConfigSection({ section, children }: ConfigSectionProps) {
|
||
|
|
const [isOpen, setIsOpen] = useState(section.defaultOpen ?? true);
|
||
|
|
|
||
|
|
if (section.collapsible) {
|
||
|
|
return (
|
||
|
|
<div className="border-b pb-3">
|
||
|
|
<button
|
||
|
|
onClick={() => setIsOpen(!isOpen)}
|
||
|
|
className="flex w-full items-center gap-1.5 py-1 text-left"
|
||
|
|
>
|
||
|
|
{isOpen ? (
|
||
|
|
<ChevronDown className="h-3.5 w-3.5 shrink-0" />
|
||
|
|
) : (
|
||
|
|
<ChevronRight className="h-3.5 w-3.5 shrink-0" />
|
||
|
|
)}
|
||
|
|
<span className="text-sm font-medium">{section.title}</span>
|
||
|
|
{section.description && (
|
||
|
|
<span className="text-muted-foreground ml-auto text-[10px]">
|
||
|
|
{section.description}
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
</button>
|
||
|
|
{isOpen && <div className="mt-2 space-y-3">{children}</div>}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="border-b pb-3">
|
||
|
|
<div className="mb-2">
|
||
|
|
<h4 className="text-sm font-medium">{section.title}</h4>
|
||
|
|
{section.description && (
|
||
|
|
<p className="text-muted-foreground text-[10px]">
|
||
|
|
{section.description}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
<div className="space-y-3">{children}</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|