From 56c2a4643c42c663dd7c0600d34691f18af97029 Mon Sep 17 00:00:00 2001 From: JSR Date: Sat, 28 Mar 2026 09:23:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E9=A1=B5=E5=85=A5=E5=8F=A3=E5=B9=B6=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AD=90=E9=A1=B5=E9=9D=A2=E8=BF=9B=E5=85=A5=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 105 +++++++++++++++++++++++++++------ src/assets/main.css | 73 +++++++++++++++++++++-- src/components/ContentArea.tsx | 89 ++++++++++++++++++---------- src/components/Settings.tsx | 57 +++++++++++++++++- 4 files changed, 269 insertions(+), 55 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b8637d5..c501b62 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { Layout, Modal, Input, message, ConfigProvider, theme as antTheme } from "antd" +import { HomeOutlined, SettingOutlined } from "@ant-design/icons" import { useEffect, useMemo, useRef, useState } from "react" import { HashRouter, useLocation, useNavigate, Routes, Route } from "react-router-dom" import { useTranslation } from "react-i18next" @@ -352,6 +353,7 @@ function MainContent(): React.JSX.Element { const isDark = currentTheme?.mode === "dark" const brandColor = currentTheme?.config?.tdesign?.brandColor || "#0052D9" + const showMobileBottomNav = isPortraitMode && !immersiveMode return ( {contextHolder} - -
- -
+ + {!isPortraitMode && ( +
+ +
+ )} + {showMobileBottomNav && ( +
+
+ + +
+
+ )} setWizardVisible(false)} /> diff --git a/src/assets/main.css b/src/assets/main.css index c889ddc..dac3a70 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -270,9 +270,74 @@ html.platform-macos #root { pointer-events: none; } -@media (prefers-reduced-motion: reduce) { - .ss-immersive-sidebar, - .ss-immersive-toolbar { - transition: none !important; +.ss-settings-mobile-nav-list { + display: flex; + flex-direction: column; +} + +.ss-settings-mobile-nav-item.ant-btn { + min-height: 48px; + width: 100%; + border-radius: 0; + justify-content: space-between; + align-items: center; + padding: 12px 16px; + color: var(--ss-text-main); + border-bottom: 1px solid var(--ss-divider, rgba(5, 5, 5, 0.06)); +} + +.ss-settings-mobile-nav-item.ant-btn:last-child { + border-bottom: none; +} + +.ss-settings-mobile-nav-item.ant-btn:hover, +.ss-settings-mobile-nav-item.ant-btn:focus-visible { + background: var(--ss-item-hover, rgba(0, 0, 0, 0.04)); +} + +.ss-settings-mobile-nav-item.ant-btn.is-active { + color: var(--ant-color-primary, #1677ff); + background: color-mix(in srgb, var(--ant-color-primary, #1677ff) 10%, transparent); +} + +.ss-settings-mobile-nav-item.ant-btn[disabled] { + color: var(--ss-text-secondary); + opacity: 0.65; +} + +.ss-settings-mobile-nav-item-label { + font-size: 15px; + font-weight: 500; +} + +.ss-settings-mobile-nav-item-arrow { + font-size: 12px; +} + +.ss-route-page { + min-height: 100%; +} + +.ss-route-page.is-subpage-enter { + animation: ss-subpage-enter 240ms cubic-bezier(0.22, 1, 0.36, 1); +} + +@keyframes ss-subpage-enter { + from { + opacity: 0; + transform: translate3d(20px, 0, 0); + } + to { + opacity: 1; + transform: translate3d(0, 0, 0); + } +} + +@media (prefers-reduced-motion: reduce) { + .ss-immersive-sidebar, + .ss-immersive-toolbar, + .ss-route-page.is-subpage-enter { + transition: none !important; + animation: none !important; } } diff --git a/src/components/ContentArea.tsx b/src/components/ContentArea.tsx index bfd617f..839827a 100644 --- a/src/components/ContentArea.tsx +++ b/src/components/ContentArea.tsx @@ -6,7 +6,7 @@ import { FullscreenOutlined, FullscreenExitOutlined, } from "@ant-design/icons" -import { Routes, Route, Navigate } from "react-router-dom" +import { Routes, Route, Navigate, useLocation } from "react-router-dom" import { useTranslation } from "react-i18next" import { WindowControls } from "./WindowControls" import appLogo from "../assets/logoHD.svg" @@ -67,6 +67,8 @@ interface ContentAreaProps { immersiveMode: boolean isHomePage: boolean onToggleImmersiveMode: () => void + showSidebarToggle?: boolean + bottomInset?: number } export function ContentArea({ @@ -83,8 +85,13 @@ export function ContentArea({ immersiveMode, isHomePage, onToggleImmersiveMode, + showSidebarToggle = true, + bottomInset = 0, }: ContentAreaProps): React.JSX.Element { const { t } = useTranslation() + const location = useLocation() + const isSubPage = location.pathname !== "/" && !location.pathname.startsWith("/home") + const shouldAnimateSubPage = isPortraitMode && isSubPage useEffect(() => { let cancelled = false @@ -156,7 +163,7 @@ export function ContentArea({ } as React.CSSProperties } > - {!immersiveMode && ( + {!immersiveMode && showSidebarToggle && ( + ))} + + + )} +