import { useCallback, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { useAppTranslation } from '@features/localization/renderer'; import { useStore } from '@renderer/store'; import { ChevronDown, Columns3, History, MessageSquare, Terminal, Users } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; interface TeamTabSectionNavProps { teamName: string; onActivate?: () => void; } const SECTIONS: readonly { id: string; labelKey: TeamSectionLabelKey; icon: LucideIcon }[] = [ { id: 'team', labelKey: 'team', icon: Users }, { id: 'sessions', labelKey: 'sessions', icon: History }, { id: 'kanban', labelKey: 'kanban', icon: Columns3 }, { id: 'claude-logs', labelKey: 'claudeLogs', icon: Terminal }, { id: 'messages', labelKey: 'messages', icon: MessageSquare }, ]; type TeamSectionLabelKey = 'team' | 'sessions' | 'kanban' | 'claudeLogs' | 'messages'; export const TeamTabSectionNav = ({ teamName, onActivate, }: TeamTabSectionNavProps): React.JSX.Element => { const { t } = useAppTranslation('common'); const messagesPanelMode = useStore((s) => s.messagesPanelMode); const [open, setOpen] = useState(false); const [hoveredId, setHoveredId] = useState(null); const buttonRef = useRef(null); const menuRef = useRef(null); const [menuPos, setMenuPos] = useState({ top: 0, left: 0, width: 0 }); const visibleSections = SECTIONS.filter((section) => { if (messagesPanelMode === 'sidebar') { return section.id !== 'messages' && section.id !== 'claude-logs'; } if (messagesPanelMode === 'bottom-sheet' || messagesPanelMode === 'floating-composer') { return section.id !== 'messages'; } return true; }); const handleNavigate = useCallback( (sectionId: string) => { onActivate?.(); const el = document.querySelector( `[data-team-name="${CSS.escape(teamName)}"] [data-section-id="${sectionId}"]` ); if (el) { el.dispatchEvent(new CustomEvent('team-section-navigate')); } setOpen(false); }, [teamName, onActivate] ); useEffect(() => { if (!open) return; if (buttonRef.current) { const rect = buttonRef.current.getBoundingClientRect(); setMenuPos({ top: rect.bottom + 4, left: rect.left, width: Math.max(rect.width, 120), }); } const handleDismiss = (e: MouseEvent): void => { const target = e.target as Node; if (buttonRef.current?.contains(target) || menuRef.current?.contains(target)) { return; } setOpen(false); }; const handleEscape = (e: KeyboardEvent): void => { if (e.key === 'Escape') setOpen(false); }; document.addEventListener('mousedown', handleDismiss); document.addEventListener('keydown', handleEscape); return () => { document.removeEventListener('mousedown', handleDismiss); document.removeEventListener('keydown', handleEscape); }; }, [open]); return (
e.stopPropagation()}> {open && createPortal(
e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()} onKeyDown={(e) => { if (e.key === 'Escape') setOpen(false); }} > {visibleSections.map((section) => { const SectionIcon = section.icon; return ( ); })}
, document.body )}
); };