Skip to content

Commit 125b740

Browse files
committed
fix(web): handle scrollable drawer in swipe actions
1 parent eb12bcf commit 125b740

File tree

1 file changed

+59
-18
lines changed

1 file changed

+59
-18
lines changed

src/components/common/navbar/NavbarComponent.vue

+59-18
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { NavbarService } from '~/services/navbar.service';
1111
import { useExtensionSettingsStoreRefs } from '~/stores/settings/extension.store';
1212
import { Header } from '~/styles/layout.style';
1313
import { useI18n } from '~/utils/i18n.utils';
14-
import { handleSwipe, SwipeDirection } from '~/utils/touch.utils';
14+
import { handleSwipe, SwipeDirection, type SwipeDirections } from '~/utils/touch.utils';
1515
1616
const props = defineProps({
1717
disabled: {
@@ -76,38 +76,78 @@ const showDrawer = computed(() => {
7676
});
7777
7878
const touchStart = ref<TouchEvent>();
79+
const drawerStart = ref<{
80+
scroll: number;
81+
width: number;
82+
}>();
7983
84+
const drawerRef = ref<HTMLElement>();
8085
const onTouchStart = (e: TouchEvent) => {
8186
touchStart.value = e;
87+
88+
const drawer = drawerRef.value?.firstElementChild;
89+
// if there is no drawer we can always navigate
90+
if (!drawer) return;
91+
drawerStart.value = {
92+
scroll: drawer.scrollLeft,
93+
width: drawer.scrollWidth - drawer.clientWidth,
94+
};
8295
};
8396
84-
const onTouchEnd = (e: TouchEvent) => {
85-
const _touchStart = touchStart.value?.targetTouches?.[0];
86-
const _touchEnd = e.changedTouches?.[0];
87-
if (!_touchStart) return;
88-
touchStart.value = undefined;
89-
const { clientWidth } = navElement.value || {};
90-
const swipe = handleSwipe(_touchStart, _touchEnd, {
91-
vertical: Header.totalHeight,
92-
up: Header.navbarHeight,
93-
left: clientWidth ? Math.min(clientWidth / 2, 200) : 200,
94-
right: clientWidth ? Math.min(clientWidth / 2, 200) : 200,
95-
});
97+
const isDrawerNotScrollable = (
98+
direction: typeof SwipeDirection.Right | typeof SwipeDirection.Left,
99+
start: Touch | undefined = touchStart.value?.targetTouches?.[0],
100+
) => {
101+
// if we start the swipe outside the drawer we can always navigate
102+
if (start && start?.clientY < Header.navbarHeight) return true;
103+
// if there is no drawer we can always navigate
104+
if (!drawerStart.value) return true;
105+
const { scroll, width } = drawerStart.value;
106+
// if the drawer is already at the end we can navigate right (swipe to the left)
107+
if (direction === SwipeDirection.Left) return width === scroll;
108+
// if the drawer is already at the start we can navigate left (swipe to the right)
109+
return scroll === 0;
110+
};
111+
112+
const handleSwipeDirection = (swipe: SwipeDirections) => {
96113
switch (swipe) {
97114
case SwipeDirection.Down:
98115
isHover.value = true;
99-
return swipe;
116+
break;
100117
case SwipeDirection.Up:
101118
isHover.value = false;
102-
return swipe;
119+
break;
103120
case SwipeDirection.Left:
104-
return nextRoute.value ? navigate(nextRoute.value) : undefined;
121+
if (nextRoute.value && isDrawerNotScrollable(swipe)) navigate(nextRoute.value);
122+
break;
105123
case SwipeDirection.Right:
106-
return prevRoute.value ? navigate(prevRoute.value) : undefined;
124+
if (prevRoute.value && isDrawerNotScrollable(swipe)) navigate(prevRoute.value);
125+
break;
107126
default:
108127
Logger.warn('Unknown swipe direction:', swipe);
109128
}
110129
};
130+
131+
const onTouchEnd = (e: TouchEvent) => {
132+
const _start = touchStart.value?.targetTouches?.[0];
133+
const _end = e.changedTouches?.[0];
134+
135+
if (!_start || !_end) return;
136+
137+
const { clientWidth } = navElement.value || {};
138+
const swipe = handleSwipe(_start, _end, {
139+
vertical: Header.totalHeight,
140+
up: Header.navbarHeight,
141+
left: clientWidth ? Math.min(clientWidth / 2, 200) : 200,
142+
right: clientWidth ? Math.min(clientWidth / 2, 200) : 200,
143+
});
144+
145+
if (swipe) handleSwipeDirection(swipe);
146+
147+
touchStart.value = undefined;
148+
drawerStart.value = undefined;
149+
return swipe;
150+
};
111151
</script>
112152

113153
<template>
@@ -117,8 +157,8 @@ const onTouchEnd = (e: TouchEvent) => {
117157
@mouseleave="isHover = false"
118158
@focusin="isFocus = true"
119159
@focusout="isFocus = false"
120-
@touchstart="onTouchStart"
121160
@touchend="onTouchEnd"
161+
@touchstart="onTouchStart"
122162
>
123163
<NTabs
124164
:key="enabledRoutes.join('-')"
@@ -163,6 +203,7 @@ const onTouchEnd = (e: TouchEvent) => {
163203
</NTab>
164204
</NTabs>
165205
<div
206+
ref="drawerRef"
166207
class="drawer"
167208
:class="{
168209
'has-drawer': hasDrawer,

0 commit comments

Comments
 (0)