Spaces:
Sleeping
Sleeping
feat: drawer tap to close on left
Browse files
src/lib/components/MobileNav.svelte
CHANGED
|
@@ -23,6 +23,9 @@
|
|
| 23 |
let panStart: number | undefined = $state(undefined);
|
| 24 |
let panStartTime: number | undefined = undefined;
|
| 25 |
|
|
|
|
|
|
|
|
|
|
| 26 |
const tween = Spring.of(
|
| 27 |
() => {
|
| 28 |
if (panX !== undefined) {
|
|
@@ -55,6 +58,12 @@
|
|
| 55 |
openEl?.focus();
|
| 56 |
}
|
| 57 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
</script>
|
| 59 |
|
| 60 |
<nav
|
|
@@ -79,6 +88,17 @@
|
|
| 79 |
>
|
| 80 |
</nav>
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
<nav
|
| 83 |
use:pan={() => ({ delay: 0, preventdefault: true, touchAction: "pan-left" })}
|
| 84 |
onpanup={(e: GestureCustomEvent) => {
|
|
@@ -86,7 +106,7 @@
|
|
| 86 |
return;
|
| 87 |
}
|
| 88 |
// measure the pan velocity to determine if the menu should snap open or closed
|
| 89 |
-
const drawerWidth = window.innerWidth;
|
| 90 |
|
| 91 |
const trueX = e.detail.x + (panX / 100) * drawerWidth;
|
| 92 |
|
|
@@ -113,7 +133,7 @@
|
|
| 113 |
panStart ??= e.detail.x;
|
| 114 |
panStartTime ??= Date.now();
|
| 115 |
|
| 116 |
-
const drawerWidth = window.innerWidth;
|
| 117 |
|
| 118 |
const trueX = e.detail.x + (panX / 100) * drawerWidth;
|
| 119 |
const percentage = ((trueX - panStart) / drawerWidth) * 100;
|
|
@@ -121,9 +141,12 @@
|
|
| 121 |
panX = Math.max(-100, Math.min(0, percentage));
|
| 122 |
tween.set(panX, { instant: true });
|
| 123 |
}}
|
| 124 |
-
style="transform: translateX({Math.max(
|
| 125 |
-
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
| 127 |
>
|
| 128 |
{#if page.url.pathname === base + "/"}
|
| 129 |
<button
|
|
|
|
| 23 |
let panStart: number | undefined = $state(undefined);
|
| 24 |
let panStartTime: number | undefined = undefined;
|
| 25 |
|
| 26 |
+
// Define the width for the drawer (less than 100% to create the gap)
|
| 27 |
+
const drawerWidthPercentage = 85;
|
| 28 |
+
|
| 29 |
const tween = Spring.of(
|
| 30 |
() => {
|
| 31 |
if (panX !== undefined) {
|
|
|
|
| 58 |
openEl?.focus();
|
| 59 |
}
|
| 60 |
});
|
| 61 |
+
|
| 62 |
+
// Function to close the drawer when background is tapped
|
| 63 |
+
function closeDrawer() {
|
| 64 |
+
isOpen = false;
|
| 65 |
+
panX = undefined;
|
| 66 |
+
}
|
| 67 |
</script>
|
| 68 |
|
| 69 |
<nav
|
|
|
|
| 88 |
>
|
| 89 |
</nav>
|
| 90 |
|
| 91 |
+
<!-- Mobile drawer overlay - shows when drawer is open -->
|
| 92 |
+
{#if isOpen}
|
| 93 |
+
<button
|
| 94 |
+
type="button"
|
| 95 |
+
class="fixed inset-0 z-20 cursor-default bg-black/30 md:hidden"
|
| 96 |
+
style="opacity: {Math.max(0, Math.min(1, (100 + tween.current) / 100))};"
|
| 97 |
+
onclick={closeDrawer}
|
| 98 |
+
aria-label="Close mobile navigation"
|
| 99 |
+
></button>
|
| 100 |
+
{/if}
|
| 101 |
+
|
| 102 |
<nav
|
| 103 |
use:pan={() => ({ delay: 0, preventdefault: true, touchAction: "pan-left" })}
|
| 104 |
onpanup={(e: GestureCustomEvent) => {
|
|
|
|
| 106 |
return;
|
| 107 |
}
|
| 108 |
// measure the pan velocity to determine if the menu should snap open or closed
|
| 109 |
+
const drawerWidth = window.innerWidth * (drawerWidthPercentage / 100);
|
| 110 |
|
| 111 |
const trueX = e.detail.x + (panX / 100) * drawerWidth;
|
| 112 |
|
|
|
|
| 133 |
panStart ??= e.detail.x;
|
| 134 |
panStartTime ??= Date.now();
|
| 135 |
|
| 136 |
+
const drawerWidth = window.innerWidth * (drawerWidthPercentage / 100);
|
| 137 |
|
| 138 |
const trueX = e.detail.x + (panX / 100) * drawerWidth;
|
| 139 |
const percentage = ((trueX - panStart) / drawerWidth) * 100;
|
|
|
|
| 141 |
panX = Math.max(-100, Math.min(0, percentage));
|
| 142 |
tween.set(panX, { instant: true });
|
| 143 |
}}
|
| 144 |
+
style="transform: translateX({Math.max(
|
| 145 |
+
-100,
|
| 146 |
+
Math.min(0, tween.current)
|
| 147 |
+
)}%); width: {drawerWidthPercentage}%;"
|
| 148 |
+
class="fixed bottom-0 left-0 top-0 z-30 grid max-h-screen
|
| 149 |
+
grid-cols-1 grid-rows-[auto,1fr,auto,auto] bg-white pt-4 shadow-lg dark:bg-gray-900 md:hidden"
|
| 150 |
>
|
| 151 |
{#if page.url.pathname === base + "/"}
|
| 152 |
<button
|