update and fix the styles in sidebard
This commit is contained in:
parent
a14aa13ecf
commit
2fd6726f08
|
|
@ -145,12 +145,47 @@ export function Sidebar({
|
||||||
const [expandedItems, setExpandedItems] = useState<string[]>([]);
|
const [expandedItems, setExpandedItems] = useState<string[]>([]);
|
||||||
const { logout } = useAuth();
|
const { logout } = useAuth();
|
||||||
|
|
||||||
|
// Auto-expand parent sections when their children are active
|
||||||
|
React.useEffect(() => {
|
||||||
|
const autoExpandParents = () => {
|
||||||
|
const newExpandedItems: string[] = [];
|
||||||
|
|
||||||
|
menuItems.forEach((item) => {
|
||||||
|
if (item.children) {
|
||||||
|
const hasActiveChild = item.children.some(
|
||||||
|
(child) => child.href && location.pathname === child.href
|
||||||
|
);
|
||||||
|
if (hasActiveChild) {
|
||||||
|
newExpandedItems.push(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setExpandedItems(newExpandedItems);
|
||||||
|
};
|
||||||
|
|
||||||
|
autoExpandParents();
|
||||||
|
}, [location.pathname]);
|
||||||
|
|
||||||
const toggleExpanded = (itemId: string) => {
|
const toggleExpanded = (itemId: string) => {
|
||||||
setExpandedItems((prev) =>
|
setExpandedItems((prev) => {
|
||||||
prev.includes(itemId)
|
// If trying to collapse, check if any child is active
|
||||||
? prev.filter((id) => id !== itemId)
|
if (prev.includes(itemId)) {
|
||||||
: [...prev, itemId],
|
const item = menuItems.find(menuItem => menuItem.id === itemId);
|
||||||
);
|
if (item?.children) {
|
||||||
|
const hasActiveChild = item.children.some(
|
||||||
|
(child) => child.href && location.pathname === child.href
|
||||||
|
);
|
||||||
|
// Don't collapse if a child is active
|
||||||
|
if (hasActiveChild) {
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prev.filter((id) => id !== itemId);
|
||||||
|
} else {
|
||||||
|
return [...prev, itemId];
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const isActiveRoute = (href?: string, children?: MenuItem[]) => {
|
const isActiveRoute = (href?: string, children?: MenuItem[]) => {
|
||||||
|
|
@ -165,7 +200,10 @@ export function Sidebar({
|
||||||
|
|
||||||
const renderMenuItem = (item: MenuItem, level = 0) => {
|
const renderMenuItem = (item: MenuItem, level = 0) => {
|
||||||
const isActive = isActiveRoute(item.href, item.children);
|
const isActive = isActiveRoute(item.href, item.children);
|
||||||
const isExpanded = expandedItems.includes(item.id);
|
const isExpanded = expandedItems.includes(item.id) ||
|
||||||
|
(item.children && item.children.some(child =>
|
||||||
|
child.href && location.pathname === child.href
|
||||||
|
));
|
||||||
const hasChildren = item.children && item.children.length > 0;
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
|
|
||||||
const ItemIcon = item.icon;
|
const ItemIcon = item.icon;
|
||||||
|
|
@ -178,61 +216,113 @@ export function Sidebar({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const menuItemContent = (
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"flex items-center justify-between w-full py-2 px-3 rounded-lg transition-all duration-200 group",
|
|
||||||
level === 0 ? "mb-1" : "mb-0.5 mr-4",
|
|
||||||
isActive
|
|
||||||
? " text-emerald-400 border-r-2 border-emerald-400"
|
|
||||||
: "text-gray-300 hover:bg-gradient-to-r hover:from-emerald-500/10 hover:to-teal-500/10 hover:text-emerald-300",
|
|
||||||
isCollapsed && level === 0 && "justify-center px-2",
|
|
||||||
item.id === "logout" && "hover:bg-red-500/10 hover:text-red-400",
|
|
||||||
)}
|
|
||||||
onClick={handleClick}
|
|
||||||
>
|
|
||||||
<div className="flex items-center gap-3 min-w-0 flex-1">
|
|
||||||
<ItemIcon
|
|
||||||
className={cn(
|
|
||||||
"w-5 h-5 flex-shrink-0",
|
|
||||||
isActive ? "text-emerald-400" : "text-current",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
{!isCollapsed && (
|
|
||||||
<span className="font-persian text-sm font-medium truncate">
|
|
||||||
{item.label}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!isCollapsed && (
|
|
||||||
<div className="flex items-center gap-2 flex-shrink-0">
|
|
||||||
{item.badge && (
|
|
||||||
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
|
|
||||||
{item.badge}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{hasChildren && (
|
|
||||||
<ChevronDown
|
|
||||||
className={cn(
|
|
||||||
"w-4 h-4 transition-transform duration-200",
|
|
||||||
isExpanded ? "rotate-180" : "rotate-0",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.id} className="relative">
|
<div key={item.id} className="relative">
|
||||||
{item.href && item.id !== "logout" ? (
|
{item.href && item.id !== "logout" ? (
|
||||||
<Link to={item.href} className="block">
|
<Link to={item.href} className="block">
|
||||||
{menuItemContent}
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex items-center justify-between w-full py-2 px-3 rounded-lg transition-all duration-200 group",
|
||||||
|
level === 0 ? "mb-1" : "mb-0.5 mr-4",
|
||||||
|
isActive
|
||||||
|
? " text-emerald-400 border-r-2 border-emerald-400"
|
||||||
|
: "text-gray-300 hover:bg-gradient-to-r hover:from-emerald-500/10 hover:to-teal-500/10 hover:text-emerald-300",
|
||||||
|
isCollapsed && level === 0 && "justify-center px-2",
|
||||||
|
item.id === "logout" && "hover:bg-red-500/10 hover:text-red-400",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3 min-w-0 flex-1">
|
||||||
|
<ItemIcon
|
||||||
|
className={cn(
|
||||||
|
"w-5 h-5 flex-shrink-0",
|
||||||
|
isActive ? "text-emerald-400" : "text-current",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{!isCollapsed && (
|
||||||
|
<span className="font-persian text-sm font-medium truncate">
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isCollapsed && (
|
||||||
|
<div className="flex items-center gap-2 flex-shrink-0">
|
||||||
|
{item.badge && (
|
||||||
|
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/20 text-emerald-400 text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
|
||||||
|
{item.badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{hasChildren && (
|
||||||
|
<ChevronDown
|
||||||
|
className={cn(
|
||||||
|
"w-4 h-4 transition-transform duration-200",
|
||||||
|
isExpanded ? "rotate-180" : "rotate-0",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<button className="w-full text-right">{menuItemContent}</button>
|
<button
|
||||||
|
className={cn(
|
||||||
|
"w-full text-right",
|
||||||
|
// Disable pointer cursor when child is active (cannot collapse)
|
||||||
|
item.children && item.children.some(child =>
|
||||||
|
child.href && location.pathname === child.href
|
||||||
|
) && "cursor-not-allowed"
|
||||||
|
)}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex items-center justify-between w-full py-2 px-3 rounded-lg transition-all duration-200 group",
|
||||||
|
level === 0 ? "mb-1" : "mb-0.5 mr-4",
|
||||||
|
isActive
|
||||||
|
? " text-emerald-400 border-r-2 border-emerald-400"
|
||||||
|
: "text-gray-300 hover:bg-gradient-to-r hover:from-emerald-500/10 hover:to-teal-500/10 hover:text-emerald-300",
|
||||||
|
isCollapsed && level === 0 && "justify-center px-2",
|
||||||
|
item.id === "logout" && "hover:bg-red-500/10 hover:text-red-400",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3 min-w-0 flex-1">
|
||||||
|
<ItemIcon
|
||||||
|
className={cn(
|
||||||
|
"w-5 h-5 flex-shrink-0",
|
||||||
|
isActive ? "text-emerald-400" : "text-current",
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{!isCollapsed && (
|
||||||
|
<span className="font-persian text-sm font-medium truncate">
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!isCollapsed && (
|
||||||
|
<div className="flex items-center gap-2 flex-shrink-0">
|
||||||
|
{item.badge && (
|
||||||
|
<span className="bg-gradient-to-r from-emerald-500/20 to-teal-500/10 text-emerald-400 text-xs font-medium px-1.5 py-0.5 rounded-full min-w-[20px] text-center font-persian">
|
||||||
|
{item.badge}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{hasChildren && (
|
||||||
|
<ChevronDown
|
||||||
|
className={cn(
|
||||||
|
"w-4 h-4 transition-transform duration-200",
|
||||||
|
isExpanded ? "rotate-180" : "rotate-0",
|
||||||
|
// Show different color when child is active (cannot collapse)
|
||||||
|
item.children && item.children.some(child =>
|
||||||
|
child.href && location.pathname === child.href
|
||||||
|
) ? "text-emerald-400" : "text-current"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Submenu */}
|
{/* Submenu */}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user