/** * Collapsible (web). A titled region that expands and collapses — the * building block for accordions and expandable resume sections. Height * animates via the grid-template-rows 0fr→1fr technique (real height, * no magic max-height guess), and the chevron rotates. * * * */ import { useState, type CSSProperties, type ReactNode } from "react"; import { useTheme } from "@plyxui/styles"; import { spacing } from "@plyxui/core"; export interface CollapsibleProps { title: ReactNode; /** Optional right-aligned adornment in the header (a count, a badge). */ aside?: ReactNode; open?: boolean; defaultOpen?: boolean; onOpenChange?: (open: boolean) => void; disabled?: boolean; className?: string; style?: CSSProperties; children?: ReactNode; } export function Collapsible({ title, aside, open, defaultOpen, onOpenChange, disabled, className, style, children, }: CollapsibleProps) { const { colors } = useTheme(); const [internal, setInternal] = useState(defaultOpen ?? false); const isControlled = open !== undefined; const isOpen = isControlled ? open : internal; const toggle = () => { if (disabled) return; if (!isControlled) setInternal(!isOpen); onOpenChange?.(!isOpen); }; return (
{children}
); }