import { useCallback, useEffect, useRef, useState } from 'react'; import { Badge } from '@renderer/components/ui/badge'; import { cn } from '@renderer/lib/utils'; import { ChevronRight } from 'lucide-react'; function scrollAfterExpand(el: HTMLElement): void { requestAnimationFrame(() => { requestAnimationFrame(() => { el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }); }); } interface CollapsibleTeamSectionProps { title: string; /** Icon rendered before the title text. */ icon?: React.ReactNode; badge?: string | number; /** Secondary badge (e.g. unread count). Shown next to main badge when defined. */ secondaryBadge?: number; /** Element rendered immediately after secondary badge (e.g. mark-all-read button). */ afterBadge?: React.ReactNode; /** Extra element rendered inline after badges (e.g. notification icon). */ headerExtra?: React.ReactNode; defaultOpen?: boolean; forceOpen?: boolean; onOpenChange?: (isOpen: boolean) => void; action?: React.ReactNode; /** Stable identifier used for programmatic section navigation. */ sectionId?: string; /** Extra classes applied to the content wrapper (e.g. padding). */ contentClassName?: string; /** Extra classes for the outer content wrapper (e.g. remove default top/bottom gaps). */ contentWrapperClassName?: string; /** Extra classes for the header bar (e.g. "-mx-6 w-[calc(100%+3rem)]" to match parent padding). */ headerClassName?: string; /** Extra classes for the inner header content (e.g. "pl-6" to match parent padding). */ headerContentClassName?: string; /** Extra classes for the clickable header surface itself (e.g. override rounded corners). */ headerSurfaceClassName?: string; /** When true, children stay mounted (hidden via CSS) when collapsed. Useful when children drive header state (e.g. online indicators). */ keepMounted?: boolean; children: React.ReactNode; } export const CollapsibleTeamSection = ({ title, icon, badge, secondaryBadge, afterBadge, headerExtra, defaultOpen = true, forceOpen, onOpenChange, action, sectionId, contentClassName, contentWrapperClassName, headerClassName, headerContentClassName, headerSurfaceClassName, keepMounted, children, }: CollapsibleTeamSectionProps): React.JSX.Element => { const [open, setOpen] = useState(defaultOpen); const isOpen = forceOpen ? true : open; const sectionRef = useRef(null); const handleNavigate = useCallback((): void => { setOpen(true); if (sectionRef.current) scrollAfterExpand(sectionRef.current); }, []); useEffect(() => { const el = sectionRef.current; if (!el) return; el.addEventListener('team-section-navigate', handleNavigate); return () => el.removeEventListener('team-section-navigate', handleNavigate); }, [handleNavigate]); useEffect(() => { onOpenChange?.(isOpen); }, [isOpen, onOpenChange]); return (
{keepMounted ? (
{children}
) : ( isOpen && (
{children}
) )}
); };