diff --git a/Changelog.md b/Changelog.md index 476895eb7..3daa89fad 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ - 允许代理页面允许高级过滤搜索 - 备份设置页面新增导入备份按钮 - 允许修改通知弹窗位置(「界面设置」->「通知位置」) +- 支持收起导航栏(「界面设置」->「收起导航栏」) diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index 5c50529cc..8e2553d5d 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -70,6 +70,9 @@ pub struct IVerge { #[serde(skip_serializing_if = "Option::is_none")] pub notice_position: Option, + /// collapse navigation bar + pub collapse_navbar: Option, + /// sysproxy tray icon pub sysproxy_tray_icon: Option, @@ -396,6 +399,7 @@ impl IVerge { tray_icon: Some("monochrome".into()), menu_icon: Some("monochrome".into()), notice_position: Some("top-right".into()), + collapse_navbar: Some(false), common_tray_icon: Some(false), sysproxy_tray_icon: Some(false), tun_tray_icon: Some(false), @@ -481,6 +485,7 @@ impl IVerge { patch!(menu_icon); patch!(menu_order); patch!(notice_position); + patch!(collapse_navbar); patch!(common_tray_icon); patch!(sysproxy_tray_icon); patch!(tun_tray_icon); diff --git a/src/assets/styles/layout.scss b/src/assets/styles/layout.scss index d328a30d9..cdeaf43f7 100644 --- a/src/assets/styles/layout.scss +++ b/src/assets/styles/layout.scss @@ -158,3 +158,103 @@ } } } + +.layout.layout--nav-collapsed { + --layout-nav-collapsed-width: 72px; + --layout-nav-item-size: 52px; + --layout-nav-item-radius: 12px; + --layout-nav-logo-size: 56px; + + .layout-content { + &__left { + flex: 0 0 var(--layout-nav-collapsed-width) !important; + width: var(--layout-nav-collapsed-width) !important; + min-width: var(--layout-nav-collapsed-width) !important; + max-width: var(--layout-nav-collapsed-width) !important; + border-right: none !important; + + .the-traffic { + display: none !important; + } + + > .MuiBox-root { + display: none !important; + } + + .the-logo { + flex: 0 0 var(--layout-nav-logo-size) !important; + height: var(--layout-nav-logo-size) !important; + margin: 8px 0 4px !important; + padding: 0 !important; + align-items: center !important; + justify-content: center !important; + } + + .the-logo > div { + width: 100% !important; + height: 100% !important; + align-items: center !important; + justify-content: center !important; + } + + .the-logo > div > svg:last-child { + display: none !important; + } + + .the-logo .MuiSvgIcon-root { + margin: 0 !important; + } + + .the-logo .the-newbtn { + display: none !important; + } + + .the-menu { + width: var(--layout-nav-collapsed-width) !important; + overflow-x: hidden; + + scrollbar-width: none; + &::-webkit-scrollbar { + width: 0; + height: 0; + } + + li:last-child { + border-bottom: none; + } + + .MuiListItem-root { + max-width: 100% !important; + padding: 0 !important; + } + + .MuiListItemButton-root { + justify-content: center !important; + width: var(--layout-nav-item-size) !important; + height: var(--layout-nav-item-size) !important; + min-height: var(--layout-nav-item-size) !important; + max-width: var(--layout-nav-item-size) !important; + flex: 0 0 var(--layout-nav-item-size) !important; + flex-grow: 0 !important; + flex-shrink: 0 !important; + margin: 6px auto !important; + padding: 0 !important; + border-radius: var(--layout-nav-item-radius) !important; + } + + .MuiListItemIcon-root { + min-width: auto !important; + margin: 0 !important; + margin-left: 0 !important; + display: flex !important; + align-items: center !important; + justify-content: center !important; + } + + .MuiListItemText-root { + display: none !important; + } + } + } + } +} diff --git a/src/components/layout/layout-item.tsx b/src/components/layout/layout-item.tsx index 6c6d23828..23dc8e70a 100644 --- a/src/components/layout/layout-item.tsx +++ b/src/components/layout/layout-item.tsx @@ -33,10 +33,14 @@ export const LayoutItem = (props: Props) => { const { to, children, icon, sortable } = props; const { verge } = useVerge(); const { menu_icon } = verge ?? {}; + const navCollapsed = verge?.collapse_navbar ?? false; const resolved = useResolvedPath(to); const match = useMatch({ path: resolved.pathname, end: true }); const navigate = useNavigate(); + const effectiveMenuIcon = + navCollapsed && menu_icon === "disable" ? "monochrome" : menu_icon; + const { setNodeRef, attributes, listeners, style, isDragging, disabled } = sortable ?? {}; @@ -84,9 +88,11 @@ export const LayoutItem = (props: Props) => { }; }, ]} + title={navCollapsed ? children : undefined} + aria-label={navCollapsed ? children : undefined} onClick={() => navigate(to)} > - {(menu_icon === "monochrome" || !menu_icon) && ( + {(effectiveMenuIcon === "monochrome" || !effectiveMenuIcon) && ( { {icon[0]} )} - {menu_icon === "colorful" && ( + {effectiveMenuIcon === "colorful" && ( {icon[1]} @@ -105,7 +111,7 @@ export const LayoutItem = (props: Props) => { diff --git a/src/components/setting/mods/layout-viewer.tsx b/src/components/setting/mods/layout-viewer.tsx index a95b72640..8d698ece7 100644 --- a/src/components/setting/mods/layout-viewer.tsx +++ b/src/components/setting/mods/layout-viewer.tsx @@ -338,6 +338,24 @@ export const LayoutViewer = forwardRef((_, ref) => { + + + onChangeData({ collapse_navbar: e })} + onGuard={(e) => patchVerge({ collapse_navbar: e })} + > + + + + {OS === "macos" && ( { const { theme } = useCustomTheme(); const { verge, mutateVerge, patchVerge } = useVerge(); const { language } = verge ?? {}; + const navCollapsed = verge?.collapse_navbar ?? false; const { switchLanguage } = useI18n(); const navigate = useNavigate(); const themeReady = useMemo(() => Boolean(theme), [theme]); @@ -281,7 +282,7 @@ const Layout = () => {