import React, { useEffect, useRef } from "react"; import { Link } from "react-router-dom"; import { IoIosArrowDown } from "react-icons/io"; import styles from './SidebarStyles/SidebarItem.module.css'; import SidebarSubmenu from "./SidebarSubmenu"; import { SidebarItemProps } from "./sidebarTypes"; const SidebarItem: React.FC = React.memo(({ item, isOpen, onToggle, isActive, isMinimized }) => { const Icon = item.icon as React.ComponentType>; const hasSubItems = item.submenu && item.submenu.length > 0; const isDisabled = item.moduleEnabled === false; const iconContainerRef = useRef(null); // Fix SVG dimensions when minimized - react-icons uses 1em which can be invisible useEffect(() => { if (isMinimized && iconContainerRef.current) { const wrapper = iconContainerRef.current; const svg = wrapper.querySelector('svg'); if (svg) { // Force explicit pixel dimensions svg.setAttribute('width', '25'); svg.setAttribute('height', '25'); svg.style.cssText = 'width: 25px !important; height: 25px !important; display: block !important;'; // Get the actual color from parent li element const parentLi = wrapper.closest('li'); const parentColor = parentLi ? window.getComputedStyle(parentLi).color : '#000000'; // Force color directly - use black for now to ensure visibility const iconColor = '#000000'; // Force black for visibility svg.style.setProperty('color', iconColor, 'important'); svg.style.setProperty('fill', iconColor, 'important'); svg.style.setProperty('stroke', iconColor, 'important'); svg.setAttribute('fill', iconColor); svg.setAttribute('stroke', iconColor); // Set fill/stroke on all paths - use black const paths = svg.querySelectorAll('path'); paths.forEach(path => { const originalFill = path.getAttribute('fill'); const originalStroke = path.getAttribute('stroke'); const strokeWidth = path.getAttribute('stroke-width'); if (originalFill === 'none' || (!originalFill && originalStroke)) { path.removeAttribute('fill'); path.setAttribute('stroke', iconColor); if (!strokeWidth || strokeWidth === '0') { path.setAttribute('stroke-width', '2'); } path.style.setProperty('stroke', iconColor, 'important'); path.style.setProperty('stroke-width', '2px', 'important'); path.style.setProperty('fill', 'none', 'important'); } else { path.removeAttribute('fill'); path.setAttribute('fill', iconColor); path.style.setProperty('fill', iconColor, 'important'); path.style.setProperty('stroke', iconColor, 'important'); } }); // Debug: Check if wrapper is visible const wrapperRect = wrapper.getBoundingClientRect(); const wrapperComputed = window.getComputedStyle(wrapper); const button = wrapper.parentElement?.querySelector('button'); const buttonComputed = button ? window.getComputedStyle(button) : null; const svgRect = svg.getBoundingClientRect(); const svgComputed = window.getComputedStyle(svg); const firstPath = paths[0]; const pathComputed = firstPath ? window.getComputedStyle(firstPath) : null; const parentLiComputed = parentLi ? window.getComputedStyle(parentLi) : null; const parentMenu = wrapper.closest(`.${styles.menu}`); const parentMenuComputed = parentMenu ? window.getComputedStyle(parentMenu) : null; // Check what's actually at the icon position const centerX = wrapperRect.left + wrapperRect.width / 2; const centerY = wrapperRect.top + wrapperRect.height / 2; const elementsAtPoint = document.elementsFromPoint(centerX, centerY); const wrapperInElements = elementsAtPoint.includes(wrapper); console.log(`[${item.name}] Icon wrapper check:`, { hasSubItems, wrapperVisible: wrapperComputed.visibility === 'visible', wrapperOpacity: wrapperComputed.opacity, wrapperZIndex: wrapperComputed.zIndex, wrapperDisplay: wrapperComputed.display, wrapperBackgroundColor: wrapperComputed.backgroundColor, wrapperRect: wrapperRect ? `width: ${wrapperRect.width}, height: ${wrapperRect.height}, top: ${wrapperRect.top}, left: ${wrapperRect.left}` : 'no rect', svgExists: !!svg, svgRect: svgRect ? `width: ${svgRect.width}, height: ${svgRect.height}, top: ${svgRect.top}, left: ${svgRect.left}` : 'no rect', svgDisplay: svgComputed.display, svgVisibility: svgComputed.visibility, svgOpacity: svgComputed.opacity, svgColor: svgComputed.color, pathsCount: paths.length, firstPathFill: pathComputed?.fill, firstPathOpacity: pathComputed?.opacity, buttonExists: !!button, buttonZIndex: buttonComputed?.zIndex, buttonPosition: buttonComputed?.position, buttonRect: button ? button.getBoundingClientRect() : null, elementsAtIconCenter: elementsAtPoint.slice(0, 5).map(el => ({ tag: el.tagName, class: el.className?.split(' ')[0] || 'no-class', zIndex: window.getComputedStyle(el).zIndex })), wrapperInElements: wrapperInElements, parentLiOverflow: parentLiComputed?.overflow, parentLiClipPath: parentLiComputed?.clipPath, parentMenuOverflow: parentMenuComputed?.overflow, parentMenuClipPath: parentMenuComputed?.clipPath }); } else { console.error(`[${item.name}] SVG NOT FOUND in wrapper!`); } } }, [isMinimized, isActive, item.name, hasSubItems]); const toggleSubmenu = (e: React.MouseEvent) => { if (isDisabled) { e.preventDefault(); return; } e.preventDefault(); e.stopPropagation(); onToggle(); }; const handleLinkClick = (e: React.MouseEvent) => { if (isDisabled) { e.preventDefault(); return; } // If item has submenu, prevent navigation and only toggle submenu if (hasSubItems) { e.preventDefault(); e.stopPropagation(); onToggle(); return; } // Allow normal navigation for items without submenu }; return (
  • {/* Icon - always render, CSS handles positioning */} {Icon && !isMinimized && ( )} {/* Text and arrow - hidden when minimized */} {!isMinimized && ( <> {hasSubItems ? ( // For items with submenu, make the entire area clickable to toggle ) : ( // For items without submenu, use normal link <> {item.name} )} )} {/* Icon for minimized state - render directly as child of li */} {Icon && isMinimized && (
    )} {/* Clickable overlay for items without submenu */} {isMinimized && !isDisabled && !hasSubItems && ( )} {/* Clickable overlay for items with submenu */} {isMinimized && hasSubItems && !isDisabled && (
  • {hasSubItems && !isDisabled && }
    ); }); SidebarItem.displayName = 'SidebarItem'; export default SidebarItem;