refactor: use shadcn sidebar
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
import Icon from "./Icon";
|
||||
|
||||
type ActivePage = "home" | "scripts" | "schedules" | "system";
|
||||
|
||||
type SidebarProps = {
|
||||
activePage: ActivePage;
|
||||
collapsed: boolean;
|
||||
onNavigate: (page: ActivePage) => void;
|
||||
onToggleCollapse: () => void;
|
||||
onEndEditing?: () => void;
|
||||
onSelectScript?: (scriptId: null) => void;
|
||||
editSessionRef?: React.RefObject<unknown | null>;
|
||||
isSystemAdmin?: boolean;
|
||||
};
|
||||
|
||||
type NavigationItem = {
|
||||
label: string;
|
||||
icon: "home" | "script" | "schedule" | "settings";
|
||||
page: ActivePage;
|
||||
};
|
||||
|
||||
export function Sidebar({
|
||||
activePage,
|
||||
collapsed,
|
||||
onNavigate,
|
||||
onToggleCollapse,
|
||||
onEndEditing,
|
||||
onSelectScript,
|
||||
editSessionRef,
|
||||
isSystemAdmin = false,
|
||||
}: SidebarProps) {
|
||||
const handleNavigationClick = (page: ActivePage) => {
|
||||
if (page !== "scripts") {
|
||||
if (editSessionRef?.current) {
|
||||
onEndEditing?.();
|
||||
} else {
|
||||
onSelectScript?.(null);
|
||||
}
|
||||
}
|
||||
onNavigate(page);
|
||||
};
|
||||
|
||||
const navigation: NavigationItem[] = [
|
||||
{ label: "工作台", icon: "home", page: "home" },
|
||||
{ label: "构建脚本", icon: "script", page: "scripts" },
|
||||
{ label: "调度配置", icon: "schedule", page: "schedules" },
|
||||
];
|
||||
|
||||
if (isSystemAdmin) {
|
||||
navigation.push({ label: "系统管理", icon: "settings", page: "system" });
|
||||
}
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={`sidebar-shell relative z-[3] flex min-h-screen flex-col text-[#c9d7e7] shadow-[5px_0_18px_rgb(19_47_77_/_9%)] transition-[width,min-width] duration-200 ease-in-out ${
|
||||
collapsed
|
||||
? "w-[70px] min-w-[70px]"
|
||||
: "w-[210px] min-w-[210px] max-xl:w-[184px] max-xl:min-w-[184px]"
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className={`flex h-[70px] items-center gap-2.5 border-b border-white/8 text-white ${
|
||||
collapsed ? "justify-center px-0" : "px-[17px]"
|
||||
}`}
|
||||
>
|
||||
<span className="grid size-9 shrink-0 place-items-center text-[#5ca9ff]">
|
||||
<Icon name="brand" size={31} />
|
||||
</span>
|
||||
{!collapsed && (
|
||||
<span className="whitespace-nowrap text-[15px] font-bold tracking-[0.01em] max-xl:text-[13px]">
|
||||
模型实验开发平台
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!collapsed && (
|
||||
<nav
|
||||
className="flex flex-col gap-[7px] px-[9px] py-[19px]"
|
||||
aria-label="主导航"
|
||||
>
|
||||
{navigation.map((item) => {
|
||||
const isActive = item.page === activePage;
|
||||
return (
|
||||
<button
|
||||
className={`flex h-12 w-full items-center gap-[13px] rounded-md border-0 px-[17px] text-left text-sm transition-[color,background] duration-[180ms] ease-in-out ${
|
||||
isActive
|
||||
? "bg-gradient-to-br from-[#1479e8] to-[#1267ca] text-white shadow-[0_7px_18px_rgb(7_96_193_/_26%)]"
|
||||
: "bg-transparent text-[#b9cade] hover:bg-white/6 hover:text-white"
|
||||
}`}
|
||||
key={item.label}
|
||||
type="button"
|
||||
onClick={() => handleNavigationClick(item.page)}
|
||||
>
|
||||
<Icon name={item.icon} size={19} />
|
||||
<span>{item.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
)}
|
||||
|
||||
<button
|
||||
className={`mt-auto mb-[17px] flex h-12 cursor-pointer items-center gap-[13px] rounded-md border-0 bg-transparent text-sm text-[#b9cade] transition-[color,background] duration-[180ms] ease-in-out hover:bg-white/6 hover:text-white ${
|
||||
collapsed
|
||||
? "mx-auto w-[calc(100%-18px)] justify-center px-[17px]"
|
||||
: "mx-[9px] w-[calc(100%-18px)] px-[17px]"
|
||||
}`}
|
||||
type="button"
|
||||
onClick={onToggleCollapse}
|
||||
aria-label={collapsed ? "展开菜单" : "收起菜单"}
|
||||
>
|
||||
<Icon name="menu" size={19} />
|
||||
{!collapsed && <span>收起菜单</span>}
|
||||
</button>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user