feat(ui): add left menu lock/unlock with reorder mode and context menu (#5168)

* feat: free menu

* feat(ui): add left menu lock/unlock with reorder mode and context menu

* docs: UPDATELOG.md
This commit is contained in:
Sline
2025-10-22 21:39:12 +08:00
committed by GitHub
parent 3bedf7ec35
commit 4f7d069f19
8 changed files with 376 additions and 28 deletions

View File

@@ -1,3 +1,7 @@
import type {
DraggableAttributes,
DraggableSyntheticListeners,
} from "@dnd-kit/core";
import {
alpha,
ListItem,
@@ -5,24 +9,46 @@ import {
ListItemText,
ListItemIcon,
} from "@mui/material";
import type { CSSProperties, ReactNode } from "react";
import { useMatch, useResolvedPath, useNavigate } from "react-router";
import { useVerge } from "@/hooks/use-verge";
interface SortableProps {
setNodeRef?: (element: HTMLElement | null) => void;
attributes?: DraggableAttributes;
listeners?: DraggableSyntheticListeners;
style?: CSSProperties;
isDragging?: boolean;
disabled?: boolean;
}
interface Props {
to: string;
children: string;
icon: React.ReactNode[];
icon: ReactNode[];
sortable?: SortableProps;
}
export const LayoutItem = (props: Props) => {
const { to, children, icon } = props;
const { to, children, icon, sortable } = props;
const { verge } = useVerge();
const { menu_icon } = verge ?? {};
const resolved = useResolvedPath(to);
const match = useMatch({ path: resolved.pathname, end: true });
const navigate = useNavigate();
const { setNodeRef, attributes, listeners, style, isDragging } =
sortable ?? {};
return (
<ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "4px 0px" }}>
<ListItem
ref={setNodeRef}
style={style}
sx={[
{ py: 0.5, maxWidth: 250, mx: "auto", padding: "4px 0px" },
isDragging ? { opacity: 0.78 } : {},
]}
>
<ListItemButton
selected={!!match}
sx={[
@@ -32,6 +58,7 @@ export const LayoutItem = (props: Props) => {
paddingLeft: 1,
paddingRight: 1,
marginRight: 1.25,
cursor: sortable && !sortable.disabled ? "grab" : "pointer",
"& .MuiListItemText-primary": {
color: "text.primary",
fontWeight: "700",
@@ -52,6 +79,8 @@ export const LayoutItem = (props: Props) => {
},
]}
onClick={() => navigate(to)}
{...(attributes ?? {})}
{...(listeners ?? {})}
>
{(menu_icon === "monochrome" || !menu_icon) && (
<ListItemIcon sx={{ color: "text.primary", marginLeft: "6px" }}>