From 0d9f1882b9e3a3d9bbe6f99bb4ccc2f11b15ddc4 Mon Sep 17 00:00:00 2001 From: kangfenmao Date: Wed, 11 Jun 2025 19:43:14 +0800 Subject: [PATCH] feat: add route animation feat: add route animation --- package.json | 1 + src/renderer/src/App.tsx | 2 - src/renderer/src/Routes.tsx | 99 ++++++++++++++++--- src/renderer/src/components/app/Navbar.tsx | 18 +++- src/renderer/src/pages/apps/App.tsx | 8 ++ src/renderer/src/pages/home/ChatNavbar.tsx | 15 ++- src/renderer/src/pages/home/HomePage.tsx | 17 ++-- .../pages/home/MainSidebar/MainSidebar.tsx | 12 +-- .../home/MainSidebar/MainSidebarStyles.tsx | 1 + .../pages/settings/ProviderSettings/index.tsx | 15 ++- yarn.lock | 39 ++++++++ 11 files changed, 182 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index adb3764281..050d52de02 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "electron-window-state": "^5.0.3", "epub": "patch:epub@npm%3A1.3.0#~/.yarn/patches/epub-npm-1.3.0-8325494ffe.patch", "fast-xml-parser": "^5.2.0", + "framer-motion": "^12.17.0", "franc-min": "^6.2.0", "fs-extra": "^11.2.0", "jsdom": "^26.0.0", diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index a327cef59d..94d3a564be 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -12,7 +12,6 @@ import { NotificationProvider } from './context/NotificationProvider' import StyleSheetManager from './context/StyleSheetManager' import { ThemeProvider } from './context/ThemeProvider' import NavigationHandler from './handler/NavigationHandler' -import MainSidebar from './pages/home/MainSidebar/MainSidebar' import Routes from './Routes' function App(): React.ReactElement { @@ -27,7 +26,6 @@ function App(): React.ReactElement { - diff --git a/src/renderer/src/Routes.tsx b/src/renderer/src/Routes.tsx index 410ce8d036..805cee726b 100644 --- a/src/renderer/src/Routes.tsx +++ b/src/renderer/src/Routes.tsx @@ -1,4 +1,7 @@ +import { AnimatePresence, motion } from 'framer-motion' +import { useEffect, useState } from 'react' import { Route, Routes, useLocation } from 'react-router-dom' +import styled from 'styled-components' import AgentsPage from './pages/agents/AgentsPage' import AppsPage from './pages/apps/AppsPage' @@ -10,27 +13,93 @@ import PaintingsRoutePage from './pages/paintings/PaintingsRoutePage' import SettingsPage from './pages/settings/SettingsPage' import TranslatePage from './pages/translate/TranslatePage' +const WILDCARD_ROUTES = ['/settings', '/paintings', '/mcp-servers'] + const RouteContainer = () => { const location = useLocation() const isHomePage = location.pathname === '/' + const [isReady, setIsReady] = useState(false) + + // 获取当前路径的主路由部分 + const mainPath = WILDCARD_ROUTES.find((route) => location.pathname.startsWith(route)) + + // 使用主路由作为 key,这样同一主路由下的切换不会触发动画 + const animationKey = mainPath || location.pathname + + // 路由变化时重置状态 + useEffect(() => { + setIsReady(false) + // 给一个很短的延迟,确保组件已经渲染 + const timer = setTimeout(() => setIsReady(true), 300) + return () => clearTimeout(timer) + }, [location.pathname]) return ( -
- -
- - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - -
-
+ + + + {!isHomePage && ( + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + )} + + ) } +const Container = styled.div` + position: relative; + width: 100%; + height: 100%; + min-width: 0; + overflow: hidden; +` + +const HomePageWrapper = styled(HomePage)` + display: flex; + width: 100%; + height: 100%; +` + +const PageContainer = styled(motion.div)` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: var(--color-base); + display: flex; + width: 100%; + height: 100%; + z-index: 10; +` + +const pageTransition = { + type: 'tween', + duration: 0.25, + ease: 'easeInOut' +} + +const pageVariants = { + initial: { y: '100%' }, + animate: { y: 0 }, + exit: { y: '100%' } +} + export default RouteContainer diff --git a/src/renderer/src/components/app/Navbar.tsx b/src/renderer/src/components/app/Navbar.tsx index 384622c96f..d78b347194 100644 --- a/src/renderer/src/components/app/Navbar.tsx +++ b/src/renderer/src/components/app/Navbar.tsx @@ -5,7 +5,7 @@ import { CircleArrowLeft, X } from 'lucide-react' import type { FC, PropsWithChildren } from 'react' import type { HTMLAttributes } from 'react' import { useNavigate } from 'react-router-dom' -import styled from 'styled-components' +import styled, { keyframes } from 'styled-components' type Props = PropsWithChildren & HTMLAttributes @@ -38,6 +38,19 @@ export const NavbarMain: FC = ({ children, ...props }) => { ) } +const rotateAnimation = keyframes` + from { + transform: rotate(-180deg); + } + to { + transform: rotate(0); + } +` + +const AnimatedButton = styled(Button)` + animation: ${rotateAnimation} 0.4s ease-out; +` + const MacCloseIcon = () => { const navigate = useNavigate() @@ -45,7 +58,7 @@ const MacCloseIcon = () => { return null } - return