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 { 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) => {
|
||||
setExpandedItems((prev) =>
|
||||
prev.includes(itemId)
|
||||
? prev.filter((id) => id !== itemId)
|
||||
: [...prev, itemId],
|
||||
);
|
||||
setExpandedItems((prev) => {
|
||||
// If trying to collapse, check if any child is active
|
||||
if (prev.includes(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[]) => {
|
||||
|
|
@ -165,7 +200,10 @@ export function Sidebar({
|
|||
|
||||
const renderMenuItem = (item: MenuItem, level = 0) => {
|
||||
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 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 (
|
||||
<div key={item.id} className="relative">
|
||||
{item.href && item.id !== "logout" ? (
|
||||
<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>
|
||||
) : (
|
||||
<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 */}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user