From fbdf31426cd9bffdde1622ea9b7a0fa39e632388 Mon Sep 17 00:00:00 2001 From: roundaboutluke Date: Mon, 2 Feb 2026 23:27:30 +0000 Subject: [PATCH 1/8] chore: switch mobile drawer to diadem-vaul-svelte --- package.json | 2 +- pnpm-lock.yaml | 71 ++++++-------------------- src/components/menus/MobileMenu.svelte | 2 +- 3 files changed, 19 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index ee62d21..c4ea447 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "tailwind-merge": "^2.5.5", "toml": "^3.0.0", "uicons.js": "^2.2.0", - "vaul-svelte": "^0.3.2", + "diadem-vaul-svelte": "^0.1.3", "winston": "^3.18.3", "winston-daily-rotate-file": "^5.0.0", "zod": "^4.1.12" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48fa1ea..2cf489f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,6 +55,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + diadem-vaul-svelte: + specifier: ^0.1.3 + version: 0.1.3(@internationalized/date@3.10.1)(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8) drizzle-orm: specifier: ^0.40.0 version: 0.40.1(@cloudflare/workers-types@4.20250517.0)(gel@2.1.0)(kysely@0.27.6)(mysql2@3.14.1) @@ -91,9 +94,6 @@ importers: uicons.js: specifier: ^2.2.0 version: 2.2.0 - vaul-svelte: - specifier: ^0.3.2 - version: 0.3.2(svelte@5.45.8) winston: specifier: ^3.18.3 version: 3.18.3 @@ -1278,11 +1278,6 @@ packages: '@maplibre/vt-pbf@4.1.0': resolution: {integrity: sha512-9LjFAoWtxdGRns8RK9vG3Fcw/fb3eHMxvAn2jffwn3jnVO1k49VOv6+FEza70rK7WzF8GnBiKa0K39RyfevKUw==} - '@melt-ui/svelte@0.76.2': - resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==} - peerDependencies: - svelte: '>=3 <5' - '@napi-rs/wasm-runtime@0.2.10': resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==} @@ -2114,11 +2109,6 @@ packages: bignumber.js@9.3.0: resolution: {integrity: sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==} - bits-ui@0.21.16: - resolution: {integrity: sha512-XFZ7/bK7j/K+5iktxX/ZpmoFHjYjpPzP5EOO/4bWiaFg5TG1iMcfjDhlBTQnJxD6BoVoHuqeZPHZvaTgF4Iv3Q==} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.118 - bits-ui@2.14.4: resolution: {integrity: sha512-W6kenhnbd/YVvur+DKkaVJ6GldE53eLewur5AhUCqslYQ0vjZr8eWlOfwZnMiPB+PF5HMVqf61vXBvmyrAmPWg==} engines: {node: '>=20'} @@ -2268,6 +2258,12 @@ packages: devalue@5.6.0: resolution: {integrity: sha512-BaD1s81TFFqbD6Uknni42TrolvEWA1Ih5L+OiHWmi4OYMJVwAYPGtha61I9KxTf52OvVHozHyjPu8zljqdF3uA==} + diadem-vaul-svelte@0.1.3: + resolution: {integrity: sha512-zf4TdgFVg30ybCnS6uE+OqBaPtHBsL5DihsmLGFqjrr+RBjjAGS4uKskAbD42b7YQ3NLMKHwbyxDQ6v4KBew+w==} + engines: {node: '>=18', pnpm: '>=8.7.0'} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.1 + drizzle-kit@0.30.5: resolution: {integrity: sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA==} hasBin: true @@ -2459,9 +2455,6 @@ packages: fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - focus-trap@7.7.0: - resolution: {integrity: sha512-DJJDHpEgoSbP8ZE1MNeU2IzCpfFyFdNZZRilqmfH2XiQsPK6PtD8AfJqWzEBudUQB2yHwZc5iq54rjTaGQ+ljw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2762,11 +2755,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@5.1.6: - resolution: {integrity: sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==} - engines: {node: ^18 || >=20} - hasBin: true - object-hash@3.0.0: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} @@ -3158,11 +3146,6 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true - vaul-svelte@0.3.2: - resolution: {integrity: sha512-X4OGWttSTVUl417qGDsSFgOvIx24DoiMRY/jaP9z0v9FL8LQQJ0RQ1ZM0QpdyQPRlNd24ewjNQHh5EgYDtfNpw==} - peerDependencies: - svelte: ^4.0.0 || ^5.0.0-next.1 - vite@5.4.19: resolution: {integrity: sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -4004,16 +3987,6 @@ snapshots: pbf: 4.0.1 supercluster: 8.0.1 - '@melt-ui/svelte@0.76.2(svelte@5.45.8)': - dependencies: - '@floating-ui/core': 1.7.3 - '@floating-ui/dom': 1.7.4 - '@internationalized/date': 3.10.1 - dequal: 2.0.3 - focus-trap: 7.7.0 - nanoid: 5.1.6 - svelte: 5.45.8 - '@napi-rs/wasm-runtime@0.2.10': dependencies: '@emnapi/core': 1.4.3 @@ -5528,13 +5501,6 @@ snapshots: bignumber.js@9.3.0: {} - bits-ui@0.21.16(svelte@5.45.8): - dependencies: - '@internationalized/date': 3.10.1 - '@melt-ui/svelte': 0.76.2(svelte@5.45.8) - nanoid: 5.1.6 - svelte: 5.45.8 - bits-ui@2.14.4(@internationalized/date@3.10.1)(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8): dependencies: '@floating-ui/core': 1.7.3 @@ -5662,6 +5628,14 @@ snapshots: devalue@5.6.0: {} + diadem-vaul-svelte@0.1.3(@internationalized/date@3.10.1)(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8): + dependencies: + bits-ui: 2.14.4(@internationalized/date@3.10.1)(@sveltejs/kit@2.49.2(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8)(vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2)))(svelte@5.45.8) + svelte: 5.45.8 + transitivePeerDependencies: + - '@internationalized/date' + - '@sveltejs/kit' + drizzle-kit@0.30.5(patch_hash=4b2e0a386094133d8f3fb3ba1c1582018d375414422d222a657302b3104a77cd): dependencies: '@drizzle-team/brocli': 0.10.2 @@ -5863,10 +5837,6 @@ snapshots: fn.name@1.1.0: {} - focus-trap@7.7.0: - dependencies: - tabbable: 6.3.0 - fsevents@2.3.3: optional: true @@ -6146,8 +6116,6 @@ snapshots: nanoid@3.3.11: {} - nanoid@5.1.6: {} - object-hash@3.0.0: {} ohash@2.0.11: {} @@ -6581,11 +6549,6 @@ snapshots: uuid@10.0.0: {} - vaul-svelte@0.3.2(svelte@5.45.8): - dependencies: - bits-ui: 0.21.16(svelte@5.45.8) - svelte: 5.45.8 - vite@5.4.19(@types/node@18.19.100)(lightningcss@1.30.2): dependencies: esbuild: 0.21.5 diff --git a/src/components/menus/MobileMenu.svelte b/src/components/menus/MobileMenu.svelte index 71907f9..3b76365 100644 --- a/src/components/menus/MobileMenu.svelte +++ b/src/components/menus/MobileMenu.svelte @@ -4,7 +4,7 @@ import MenuContainer from '@/components/menus/MenuContainer.svelte'; import CloseButton from '@/components/ui/CloseButton.svelte'; import * as m from '@/lib/paraglide/messages'; - import { Drawer } from 'vaul-svelte'; + import { Drawer } from 'diadem-vaul-svelte'; Date: Mon, 2 Feb 2026 23:30:16 +0000 Subject: [PATCH 2/8] fix: allow iOS map pan above Scout drawer --- src/components/menus/MobileMenu.svelte | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/menus/MobileMenu.svelte b/src/components/menus/MobileMenu.svelte index 3b76365..fb98e36 100644 --- a/src/components/menus/MobileMenu.svelte +++ b/src/components/menus/MobileMenu.svelte @@ -5,6 +5,8 @@ import CloseButton from '@/components/ui/CloseButton.svelte'; import * as m from '@/lib/paraglide/messages'; import { Drawer } from 'diadem-vaul-svelte'; + + const isScout = $derived(getOpenedMenu() === 'scout');
From e21df1e7e62a594ea628f97740b4f22e6c946b20 Mon Sep 17 00:00:00 2001 From: roundaboutluke Date: Mon, 2 Feb 2026 23:57:50 +0000 Subject: [PATCH 3/8] fix: improve Scout drawer interactions --- src/components/menus/MobileMenu.svelte | 63 +++++++++++++++++++-- src/components/menus/scout/ScoutMenu.svelte | 32 ++++++----- 2 files changed, 74 insertions(+), 21 deletions(-) diff --git a/src/components/menus/MobileMenu.svelte b/src/components/menus/MobileMenu.svelte index fb98e36..0a769c5 100644 --- a/src/components/menus/MobileMenu.svelte +++ b/src/components/menus/MobileMenu.svelte @@ -6,18 +6,69 @@ import * as m from '@/lib/paraglide/messages'; import { Drawer } from 'diadem-vaul-svelte'; - const isScout = $derived(getOpenedMenu() === 'scout'); + type OpenedMenu = ReturnType; + + let open = $state(false); + let renderedMenu: OpenedMenu = $state(null); + let lastMenu: OpenedMenu = $state(null); + let closeTimer: ReturnType | null = null; + + const isScout = $derived(renderedMenu === 'scout'); + + function finalizeClose() { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = null; + } + renderedMenu = null; + openMenu(null); + } + + function requestClose() { + open = false; + + // Fallback: if `onOpenChangeComplete` doesn't fire reliably, still clear state after the close transition. + if (closeTimer) clearTimeout(closeTimer); + closeTimer = setTimeout(() => { + finalizeClose(); + }, 600); + } + + $effect(() => { + const menu = getOpenedMenu(); + if (menu === lastMenu) return; + + lastMenu = menu; + + if (menu) { + if (closeTimer) { + clearTimeout(closeTimer); + closeTimer = null; + } + renderedMenu = menu; + open = true; + } else { + if (open) requestClose(); + else renderedMenu = null; + } + }); openMenu(null)} + open={open} + onOpenChange={(next) => { + open = next; + if (!next) requestClose(); + }} + onOpenChangeComplete={(next) => { + if (!next) finalizeClose(); + }} closeOnOutsideClick={false} >
- {m['nav_' + getOpenedMenu()]()} + {renderedMenu ? m['nav_' + renderedMenu]() : ''} openMenu(null)} + onclick={requestClose} class="mr-1 hover:bg-accent/90! active:bg-accent/90!" />
diff --git a/src/components/menus/scout/ScoutMenu.svelte b/src/components/menus/scout/ScoutMenu.svelte index 40dbe54..4bbec02 100644 --- a/src/components/menus/scout/ScoutMenu.svelte +++ b/src/components/menus/scout/ScoutMenu.svelte @@ -89,20 +89,22 @@ - -
- - -
+ +
+ +
+ +
+

@@ -114,4 +116,4 @@ {m.scout_start()} - \ No newline at end of file + From 6dec796f3974d02757e96629392876d2dd67352d Mon Sep 17 00:00:00 2001 From: roundaboutluke Date: Tue, 3 Feb 2026 12:54:01 +0000 Subject: [PATCH 4/8] fix: allow map pan behind drawer on Chrome Only force "pointer-events-none!" on non-iOS (mobile WebKit keeps the default behavior to avoid breaking scroll). --- src/components/menus/MobileMenu.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/menus/MobileMenu.svelte b/src/components/menus/MobileMenu.svelte index 0a769c5..fc9ce4c 100644 --- a/src/components/menus/MobileMenu.svelte +++ b/src/components/menus/MobileMenu.svelte @@ -1,5 +1,6 @@ { - open = next; - if (!next) requestClose(); - }} - onOpenChangeComplete={(next) => { - if (!next) finalizeClose(); - }} + open={Boolean(getOpenedMenu())} + onClose={() => openMenu(null)} closeOnOutsideClick={false} + snapPoints={[0.62, 1]} + bind:activeSnapPoint > -

-
-
- - {renderedMenu ? m['nav_' + renderedMenu]() : ''} - - -
+
+
+ + {m['nav_' + getOpenedMenu()]()} + + openMenu(null)} + class="mr-1 hover:bg-accent/90! active:bg-accent/90!" + />
+
+
+ + \ No newline at end of file diff --git a/src/components/menus/MobileMenuOld.svelte b/src/components/menus/MobileMenuOld.svelte new file mode 100644 index 0000000..a181601 --- /dev/null +++ b/src/components/menus/MobileMenuOld.svelte @@ -0,0 +1,132 @@ + + + { + open = next; + if (!next) requestClose(); + }} + onOpenChangeComplete={(next) => { + if (!next) finalizeClose(); + }} + closeOnOutsideClick={false} +> + + +
+
+
+ + {renderedMenu ? m['nav_' + renderedMenu]() : ''} + + +
+
+ + +
+
+
+
+ + \ No newline at end of file diff --git a/src/components/menus/profile/ProfileMenu.svelte b/src/components/menus/profile/ProfileMenu.svelte index 61be71b..d7621c8 100644 --- a/src/components/menus/profile/ProfileMenu.svelte +++ b/src/components/menus/profile/ProfileMenu.svelte @@ -7,7 +7,7 @@ import SignInButton from "@/components/ui/user/SignInButton.svelte"; -
+
{#if isSupportedFeature("auth")} diff --git a/src/components/ui/BottomNav.svelte b/src/components/ui/BottomNav.svelte index 6bcfca4..428772d 100644 --- a/src/components/ui/BottomNav.svelte +++ b/src/components/ui/BottomNav.svelte @@ -48,9 +48,7 @@ {@const Icon = btn.icon} {#snippet icon()} -
- -
+ {/snippet}