/**
* 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 (
);
}