Files
xiaoxia-saas/apps/web/src/components/layout/Sidebar.tsx
T
DevOps Bot b86a9c2af2
CI/CD Pipeline / Deploy Staging (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Failing after 75h41m6s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 75h41m16s
chore: 统一代码格式 - black + prettier 全量格式化
2026-07-06 09:13:03 +08:00

73 lines
2.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Sidebar - 侧边栏导航组件(Task 1.3
*
* 功能:
* - 分组导航菜单(创作工具 / 资源管理 / 系统)
* - 每个菜单项:图标 + 文字
* - 当前页面对应菜单项高亮(基于路由匹配)
* - 点击跳转路由
* - 折叠态:仅显示图标,隐藏文字(通过 SidebarContext 读取 collapsed 状态)
* - 响应式:移动端自动折叠
*/
import React, { useContext } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { SidebarContext } from "./MainLayout";
import { NAV_GROUPS } from "@/config/navigation";
import "./Sidebar.css";
/** 判断菜单项是否激活 */
const isMenuItemActive = (pathname: string, path: string): boolean => {
// 首页特殊处理:/ 和 /app/dashboard 都算激活
if (path === "/app/dashboard") {
return (
pathname === "/" || pathname === "/app" || pathname === "/app/dashboard"
);
}
return pathname.startsWith(path);
};
const Sidebar: React.FC = () => {
const { collapsed } = useContext(SidebarContext);
const location = useLocation();
const navigate = useNavigate();
const handleNavigate = (path: string) => {
navigate(path);
};
return (
<div
className={`xx-sidebar-nav${collapsed ? " xx-sidebar-nav--collapsed" : ""}`}
>
{NAV_GROUPS.map((group) => (
<div className="xx-sidebar-group" key={group.title}>
{!collapsed && (
<div className="xx-sidebar-group-title">{group.title}</div>
)}
<ul className="xx-sidebar-menu" role="menu">
{group.items.map((item) => {
const active = isMenuItemActive(location.pathname, item.path);
return (
<li
key={item.key}
className={`xx-sidebar-menu-item${active ? " xx-active" : ""}`}
role="menuitem"
title={collapsed ? item.label : undefined}
onClick={() => handleNavigate(item.path)}
>
<span className="xx-sidebar-menu-icon">{item.icon}</span>
{!collapsed && (
<span className="xx-sidebar-menu-label">{item.label}</span>
)}
</li>
);
})}
</ul>
</div>
))}
</div>
);
};
export default Sidebar;