/******************************************************************************** * Copyright (c) 2020 TypeFox and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 ********************************************************************************/ import { FunctionComponent, PropsWithChildren, ReactNode, useContext, useRef, useState } from 'react'; import { Collapse, List, ListItemButton, ListItemIcon, ListItemText, Popover, Tooltip, } from '@mui/material'; import ExpandLess from '@mui/icons-material/ExpandLess'; import ExpandMore from '@mui/icons-material/ExpandMore'; import { useNavigate } from 'react-router'; import { SidebarContext } from './sidebar-context'; const EXPANDED_CONTEXT = { collapsed: false }; export const NavigationItem: FunctionComponent> = props => { const [groupExpanded, setGroupExpanded] = useState(false); const [popoverOpen, setPopoverOpen] = useState(false); const anchorRef = useRef(null); const { collapsed } = useContext(SidebarContext); const navigate = useNavigate(); const isGroup = !!props.children; const handleClick = () => { if (isGroup) { if (collapsed) { setPopoverOpen(true); } else { setGroupExpanded(prev => !prev); } } else if (props.route) { navigate(props.route); } }; const button = ( {props.icon && ( {props.icon} )} {!collapsed && } {!collapsed && isGroup && (groupExpanded ? : )} ); return ( <> {collapsed ? ( {button} ) : ( button )} {/* Inline expand for groups when sidebar is open */} {!collapsed && isGroup && ( {props.children} )} {/* Floating popover for groups when sidebar is collapsed */} {isGroup && ( setPopoverOpen(false)} anchorOrigin={{ vertical: 'top', horizontal: 'right' }} transformOrigin={{ vertical: 'top', horizontal: 'left' }} disableRestoreFocus elevation={2} > setPopoverOpen(false)}> {props.children} )} ); }; export interface NavigationProps { route?: string; icon?: ReactNode; label: string; active?: boolean; }