From 4db6cbef2220b81d636d5ea9c522ab64b1a4c66e Mon Sep 17 00:00:00 2001 From: Maurice Date: Sat, 18 Apr 2026 17:39:15 +0200 Subject: [PATCH] add Emil-style UI polish pass (animations, shared components, feel) --- client/package-lock.json | 75 ----- client/src/components/Admin/GitHubPanel.tsx | 12 +- client/src/components/Budget/BudgetPanel.tsx | 13 +- client/src/components/Layout/Navbar.tsx | 41 ++- .../Packing/ApplyTemplateButton.tsx | 102 +++++++ .../components/Packing/PackingListPanel.tsx | 172 ++++++++--- .../src/components/Planner/DayPlanSidebar.tsx | 8 +- .../src/components/Planner/PlacesSidebar.tsx | 3 +- client/src/components/Settings/AboutTab.tsx | 12 +- client/src/components/Vacay/VacayCalendar.tsx | 4 +- client/src/components/Vacay/VacayPersons.tsx | 10 +- client/src/components/Vacay/VacayStats.tsx | 5 +- .../src/components/shared/ConfirmDialog.tsx | 15 +- client/src/components/shared/ContextMenu.tsx | 5 +- client/src/components/shared/CopyButton.tsx | 65 ++++ client/src/components/shared/CustomSelect.tsx | 12 +- client/src/components/shared/LoadingImage.tsx | 36 +++ client/src/components/shared/Modal.tsx | 15 +- client/src/components/shared/Skeleton.tsx | 70 +++++ client/src/components/shared/SlidingTabs.tsx | 126 ++++++++ client/src/components/shared/Tooltip.tsx | 2 + client/src/hooks/useCountUp.ts | 29 ++ client/src/index.css | 284 ++++++++++++++++++ client/src/pages/AdminPage.tsx | 28 +- client/src/pages/AtlasPage.tsx | 2 +- client/src/pages/DashboardPage.tsx | 90 +++--- client/src/pages/JourneyDetailPage.tsx | 8 +- client/src/pages/JourneyPage.tsx | 10 +- client/src/pages/LoginPage.tsx | 24 +- client/src/pages/RegisterPage.tsx | 8 +- client/src/pages/TripPlannerPage.tsx | 122 ++++---- client/src/pages/VacayPage.tsx | 6 +- client/tests/setup.ts | 9 + 33 files changed, 1103 insertions(+), 320 deletions(-) create mode 100644 client/src/components/Packing/ApplyTemplateButton.tsx create mode 100644 client/src/components/shared/CopyButton.tsx create mode 100644 client/src/components/shared/LoadingImage.tsx create mode 100644 client/src/components/shared/Skeleton.tsx create mode 100644 client/src/components/shared/SlidingTabs.tsx create mode 100644 client/src/hooks/useCountUp.ts diff --git a/client/package-lock.json b/client/package-lock.json index ddd545a3..459af33c 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2367,9 +2367,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2387,9 +2384,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2407,9 +2401,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2427,9 +2418,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2447,9 +2435,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2467,9 +2452,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -2487,9 +2469,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2513,9 +2492,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2539,9 +2515,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2565,9 +2538,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2591,9 +2561,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -2617,9 +2584,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -3399,9 +3363,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3416,9 +3377,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3433,9 +3391,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3450,9 +3405,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3467,9 +3419,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3484,9 +3433,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3501,9 +3447,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3518,9 +3461,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3535,9 +3475,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3552,9 +3489,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -3569,9 +3503,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3586,9 +3517,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -3603,9 +3531,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ diff --git a/client/src/components/Admin/GitHubPanel.tsx b/client/src/components/Admin/GitHubPanel.tsx index 2dcc16ce..7cc3f421 100644 --- a/client/src/components/Admin/GitHubPanel.tsx +++ b/client/src/components/Admin/GitHubPanel.tsx @@ -130,7 +130,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://ko-fi.com/mauriceboe" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#ff5e5b'; e.currentTarget.style.boxShadow = '0 0 0 1px #ff5e5b22' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} @@ -148,7 +148,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://buymeacoffee.com/mauriceboe" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#ffdd00'; e.currentTarget.style.boxShadow = '0 0 0 1px #ffdd0022' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} @@ -166,7 +166,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://discord.gg/NhZBDSd4qW" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#5865F2'; e.currentTarget.style.boxShadow = '0 0 0 1px #5865F222' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} @@ -187,7 +187,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://github.com/mauriceboe/TREK/issues/new?template=bug_report.yml" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#ef4444'; e.currentTarget.style.boxShadow = '0 0 0 1px #ef444422' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} @@ -205,7 +205,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://github.com/mauriceboe/TREK/discussions/new?category=feature-requests" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#f59e0b'; e.currentTarget.style.boxShadow = '0 0 0 1px #f59e0b22' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} @@ -223,7 +223,7 @@ export default function GitHubPanel({ isPrerelease = false }: { isPrerelease?: b href="https://github.com/mauriceboe/TREK/wiki" target="_blank" rel="noopener noreferrer" - className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-all" + className="rounded-xl border overflow-hidden flex items-center gap-4 px-5 py-4 transition-[border-color,box-shadow] duration-200 ease-[cubic-bezier(0.23,1,0.32,1)]" style={{ background: 'var(--bg-card)', borderColor: 'var(--border-primary)', textDecoration: 'none' }} onMouseEnter={e => { e.currentTarget.style.borderColor = '#6366f1'; e.currentTarget.style.boxShadow = '0 0 0 1px #6366f122' }} onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border-primary)'; e.currentTarget.style.boxShadow = 'none' }} diff --git a/client/src/components/Budget/BudgetPanel.tsx b/client/src/components/Budget/BudgetPanel.tsx index 0caa0570..1d9616ec 100644 --- a/client/src/components/Budget/BudgetPanel.tsx +++ b/client/src/components/Budget/BudgetPanel.tsx @@ -529,11 +529,14 @@ function PieChart({ segments, size = 200, totalLabel }: PieChartProps) { return (
-
+
(false) + const [scrolled, setScrolled] = useState(false) const darkMode = settings.dark_mode const dark = darkMode === true || darkMode === 'dark' || (darkMode === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) + useEffect(() => { + const onScroll = () => setScrolled(window.scrollY > 8 || (document.body.scrollTop || 0) > 8) + onScroll() + window.addEventListener('scroll', onScroll, { passive: true }) + document.body.addEventListener('scroll', onScroll, { passive: true }) + return () => { + window.removeEventListener('scroll', onScroll) + document.body.removeEventListener('scroll', onScroll) + } + }, []) + // Only show 'global' type addons in the navbar — 'integration' addons have no dedicated page const globalAddons = allAddons.filter((a: Addon) => a.type === 'global' && a.enabled) @@ -50,7 +62,11 @@ export default function Navbar({ tripTitle, tripId, onBack, showBack, onShare }: } const toggleDarkMode = () => { + document.documentElement.classList.add('trek-theme-transitioning') updateSetting('dark_mode', dark ? 'light' : 'dark').catch(() => {}) + window.setTimeout(() => { + document.documentElement.classList.remove('trek-theme-transitioning') + }, 360) } const getAddonName = (addon: Addon): string => { @@ -61,23 +77,29 @@ export default function Navbar({ tripTitle, tripId, onBack, showBack, onShare }: return (