fix(ui): restore missing UI transition animations (#408)

- Wrap `Routes` with `AnimatePresence` to enable framer-motion page transition exit animations and fix harsh route changes.
- Replace `tw-animate-css` with `tailwindcss-animate` to properly bundle transition classes (like `animate-in`, `animate-accordion-down`) under Tailwind v4.
- This restores animation to modals, accordions, and all page navigations.
- Fix accessibility warning on table cell span element.

Fixes #283
This commit is contained in:
sagit
2026-04-03 20:55:43 +08:00
committed by GitHub
parent 4e088afb29
commit 7b9b59644e
4 changed files with 118 additions and 111 deletions
+1 -1
View File
@@ -52,7 +52,7 @@
"tailwind-merge": "^2.5.5",
"tailwind-variants": "1.0.0",
"tailwindcss": "4.1.11",
"tw-animate-css": "^1.3.0"
"tailwindcss-animate": "^1.0.7"
},
"devDependencies": {
"@eslint/compat": "1.2.8",
+7 -2
View File
@@ -1,5 +1,6 @@
import { Route, Routes, useNavigate } from "react-router-dom";
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
import { useEffect } from "react";
import { AnimatePresence } from "framer-motion";
import IndexPage from "@/pages/index";
import ChangePasswordPage from "@/pages/change-password";
@@ -87,6 +88,8 @@ const LoginRoute = () => {
};
function App() {
const location = useLocation();
// 立即设置页面标题(使用已从缓存读取的配置)
useEffect(() => {
document.title = siteConfig.name;
@@ -105,7 +108,8 @@ function App() {
}, []);
return (
<Routes>
<AnimatePresence mode="wait">
<Routes key={location.pathname} location={location}>
<Route element={<LoginRoute />} path="/" />
<Route
element={
@@ -205,6 +209,7 @@ function App() {
/>
<Route element={<SettingsPage />} path="/settings" />
</Routes>
</AnimatePresence>
);
}
+6 -4
View File
@@ -973,12 +973,13 @@ const SortableCompactTableRow = ({
<TableCell
className={`whitespace-nowrap text-foreground ${selectedIds.has(forward.id) ? "bg-primary-50/70 dark:bg-primary-900/40" : ""}`}
>
<span
className="cursor-pointer hover:text-primary transition-colors"
<button
className="cursor-pointer hover:text-primary transition-colors text-left bg-transparent border-none p-0 outline-none focus:ring-2 focus:ring-primary focus:ring-offset-1 rounded-sm"
type="button"
onClick={() => copyToClipboard(forward.name, "规则名")}
>
{forward.name}
</span>
</button>
</TableCell>
<TableCell
className={`whitespace-nowrap ${selectedIds.has(forward.id) ? "bg-primary-50/70 dark:bg-primary-900/40" : ""}`}
@@ -987,7 +988,8 @@ const SortableCompactTableRow = ({
<span className="font-medium text-default-700 text-sm">
{forward.tunnelName}
</span>
{forward.tunnelTrafficRatio !== undefined && normalizeTunnelTrafficRatio(forward.tunnelTrafficRatio) !== 1 && (
{forward.tunnelTrafficRatio !== undefined &&
normalizeTunnelTrafficRatio(forward.tunnelTrafficRatio) !== 1 && (
<span className="text-success font-bold text-[12px] ml-1.5 border border-success/30 rounded px-1 bg-success/10">
{formatTunnelTrafficRatio(forward.tunnelTrafficRatio)}
</span>
+1 -1
View File
@@ -1,6 +1,6 @@
@import "tailwindcss";
@import "tw-animate-css";
@import "./tailwind-theme.pcss";
@plugin "tailwindcss-animate";
/* GPU acceleration helper - prevents font blurriness during transforms */
.gpu-accelerated {