fix(ui): refine glassmorphism and page transition animations

- Added custom light/dark background images to replace unsplash URLs.
- Enhanced active sidebar item shadow and backdrop blur for better visibility.
- Fixed double loading flickers on user, node, group, and panel-sharing pages.
- Removed opacity transitions from AnimatedPage to prevent backdrop-filter rendering issues during page navigation.
This commit is contained in:
sagitchu
2026-04-06 12:26:29 +08:00
parent 74ed74ba00
commit b42516cea1
10 changed files with 26 additions and 30 deletions
+12 -10
View File
@@ -1,6 +1,8 @@
import { useCallback, useEffect, useMemo, useState } from "react";
import toast from "react-hot-toast";
import { AnimatedPage } from "@/components/animated-page";
import { PageLoadingState } from "@/components/page-state";
import { Card, CardBody, CardHeader } from "@/shadcn-bridge/heroui/card";
import { Button } from "@/shadcn-bridge/heroui/button";
import { Input } from "@/shadcn-bridge/heroui/input";
@@ -22,7 +24,7 @@ import {
TableRow,
} from "@/shadcn-bridge/heroui/table";
import { Chip } from "@/shadcn-bridge/heroui/chip";
import { Spinner } from "@/shadcn-bridge/heroui/spinner";
import {
assignGroupPermission,
assignTunnelsToGroup,
@@ -469,14 +471,12 @@ export default function GroupPage() {
}
return (
<div className="px-3 lg:px-6 py-8 space-y-6">
{loading && (
<div className="flex justify-center py-10">
<Spinner size="lg" />
</div>
)}
<Card>
<AnimatedPage className="px-3 lg:px-6 py-8 space-y-6">
{loading ? (
<PageLoadingState message="正在加载..." />
) : (
<>
<Card>
<CardHeader className="flex flex-row items-center gap-3 pb-2">
<h3 className="text-lg font-semibold">隧道分组</h3>
<Button
@@ -922,6 +922,8 @@ export default function GroupPage() {
</ModalFooter>
</ModalContent>
</Modal>
</div>
</>
)}
</AnimatedPage>
);
}
+1 -1
View File
@@ -288,7 +288,7 @@ const SortableItem = ({
export default function NodePage() {
const [nodeList, setNodeList] = useState<Node[]>([]);
const [nodeOrder, setNodeOrder] = useState<number[]>([]);
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const [localSearchKeyword, setLocalSearchKeyword] = useLocalStorageState(
"node-search-keyword-local",
"",
+1 -1
View File
@@ -89,7 +89,7 @@ export default function PanelSharingPage() {
[],
);
const [nodes, setNodes] = useState<Node[]>([]);
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const [remoteUsageLoading, setRemoteUsageLoading] = useState(false);
// Modals
+1 -5
View File
@@ -185,7 +185,7 @@ const normalizeUserTunnelItem = (item: Partial<UserTunnel>): UserTunnel => {
export default function UserPage() {
// 状态管理
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(true);
const [searchKeyword, setSearchKeyword] = useLocalStorageState(
"user-search-keyword",
"",
@@ -466,10 +466,6 @@ export default function UserPage() {
void loadMonitorPermissions();
}, [loadMonitorPermissions, loadSpeedLimits, loadTunnels, loadUserGroups]);
useEffect(() => {
void loadUsers();
}, [loadUsers]);
useEffect(() => {
if (searchDebounceRef.current) {
clearTimeout(searchDebounceRef.current);