Skip to content

Commit f91df20

Browse files
committed
fix: 🐛 Fix AdaptiveDropdown not responding to touch on mobile
1 parent 3c68c2e commit f91df20

File tree

3 files changed

+67
-39
lines changed

3 files changed

+67
-39
lines changed

components/composer/modal.client.vue

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ useListen("composer:open", () => {
4646
useListen("composer:close", () => {
4747
open.value = false;
4848
});
49-
const log = console.log;
5049
const tokenData = useTokenData();
5150
const instance = useInstance();
5251
</script>

components/dropdowns/AdaptiveDropdown.vue

+49-17
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,27 @@
55
<Menu.Trigger>
66
<slot name="button"></slot>
77
</Menu.Trigger>
8-
<div @mousedown="open = false" @touchstart="open = false" v-if="open" class="fixed inset-0 z-10 bg-black/50">
9-
</div>
10-
<Menu.Positioner :class="isSmallScreen && '!bottom-0 !top-[unset] fixed inset-x-0 w-full !translate-y-0'">
11-
<transition enter-active-class="transition ease-in duration-100"
12-
enter-from-class="transform opacity-0 translate-y-full sm:translate-y-0 scale-95"
13-
enter-to-class="transform translate-y-0 opacity-100 scale-100"
14-
leave-active-class="transition ease-out duration-75" leave-from-class="transform opacity-100 scale-100"
15-
leave-to-class="transform opacity-0 scale-95">
16-
<Menu.Content v-if="open"
17-
:class="['z-20 mt-2 rounded overflow-hidden p-1 space-y-1 bg-dark-700 shadow-lg ring-1 ring-white/10 focus:outline-none min-w-56']">
18-
<div v-if="isSmallScreen" class="w-full py-2">
19-
<div class="rounded-full h-1 bg-gray-400 w-12 mx-auto"></div>
20-
</div>
21-
<slot name="items"></slot>
22-
</Menu.Content>
23-
</transition>
24-
</Menu.Positioner>
8+
9+
<Teleport to="body">
10+
<div @mousedown="open = false" @touchstart="open = false" v-if="open"
11+
class="fixed inset-0 z-10 bg-black/50">
12+
</div>
13+
<Menu.Positioner :class="isSmallScreen && '!bottom-0 !top-[unset] fixed inset-x-0 w-full !translate-y-0'">
14+
<transition enter-active-class="transition ease-in duration-100"
15+
enter-from-class="transform opacity-0 translate-y-full sm:translate-y-0 scale-95"
16+
enter-to-class="transform translate-y-0 opacity-100 scale-100"
17+
leave-active-class="transition ease-out duration-75"
18+
leave-from-class="transform opacity-100 scale-100" leave-to-class="transform opacity-0 scale-95">
19+
<Menu.Content v-if="open"
20+
:class="['z-20 mt-2 rounded overflow-hidden p-1 space-y-1 bg-dark-700 shadow-lg ring-1 ring-white/10 focus:outline-none min-w-56', id]">
21+
<div v-if="isSmallScreen" class="w-full py-2">
22+
<div class="rounded-full h-1 bg-gray-400 w-12 mx-auto"></div>
23+
</div>
24+
<slot name="items"></slot>
25+
</Menu.Content>
26+
</transition>
27+
</Menu.Positioner>
28+
</Teleport>
2529
</Menu.Root>
2630
</template>
2731

@@ -31,4 +35,32 @@ const { width } = useWindowSize();
3135
const isSmallScreen = computed(() => width.value < 768);
3236
3337
const open = ref(false);
38+
const id = useId();
39+
40+
// HACK: Fix the menu children not reacting to touch events as click for some reason
41+
const registerClickHandlers = () => {
42+
const targetElement = document.querySelector(`.${id}`);
43+
if (targetElement) {
44+
for (const el of targetElement.children) {
45+
el.addEventListener("pointerdown", (e) => {
46+
e.stopPropagation();
47+
e.preventDefault();
48+
// Click all element children
49+
for (const elChild of Array.from(el.children)) {
50+
if (elChild instanceof HTMLElement) {
51+
elChild.click();
52+
}
53+
}
54+
});
55+
}
56+
}
57+
};
58+
59+
// When opening, register click handlers
60+
watch(open, async (o) => {
61+
if (o) {
62+
await nextTick();
63+
registerClickHandlers();
64+
}
65+
});
3466
</script>

components/sidebars/navigation.vue

+18-21
Original file line numberDiff line numberDiff line change
@@ -106,27 +106,25 @@
106106
</template>
107107

108108
<template #items>
109-
<ClientOnly>
110-
<Menu.Item value="" v-if="tokenData">
111-
<ButtonsDropdownElement icon="tabler:logout" class="w-full"
112-
@click="signOut().finally(() => loadingAuth = false)" :loading="loadingAuth">
113-
Sign Out
114-
</ButtonsDropdownElement>
115-
</Menu.Item>
116-
<Menu.Item value="" v-if="!tokenData">
117-
<ButtonsDropdownElement icon="tabler:login" class="w-full"
118-
@click="signIn().finally(() => loadingAuth = false)" :loading="loadingAuth">
119-
Sign In
109+
<Menu.Item value="" v-if="tokenData">
110+
<ButtonsDropdownElement icon="tabler:logout" class="w-full"
111+
@click="signOut().finally(() => loadingAuth = false)" :loading="loadingAuth">
112+
Sign Out
113+
</ButtonsDropdownElement>
114+
</Menu.Item>
115+
<Menu.Item value="" v-if="!tokenData">
116+
<ButtonsDropdownElement icon="tabler:login" class="w-full"
117+
@click="signIn().finally(() => loadingAuth = false)" :loading="loadingAuth">
118+
Sign In
119+
</ButtonsDropdownElement>
120+
</Menu.Item>
121+
<Menu.Item value="" v-if="!tokenData">
122+
<NuxtLink href="/register">
123+
<ButtonsDropdownElement icon="tabler:certificate" class="w-full">
124+
Register
120125
</ButtonsDropdownElement>
121-
</Menu.Item>
122-
<Menu.Item value="" v-if="!tokenData">
123-
<NuxtLink href="/register">
124-
<ButtonsDropdownElement icon="tabler:certificate" class="w-full">
125-
Register
126-
</ButtonsDropdownElement>
127-
</NuxtLink>
128-
</Menu.Item>
129-
</ClientOnly>
126+
</NuxtLink>
127+
</Menu.Item>
130128
</template>
131129
</DropdownsAdaptiveDropdown>
132130
<button @click="compose" v-if="tokenData"
@@ -165,7 +163,6 @@ const timelines = ref([
165163
requiresAuth: true,
166164
},
167165
]);
168-
const log = console.log;
169166
170167
const visibleTimelines = computed(() =>
171168
timelines.value.filter(

0 commit comments

Comments
 (0)