Optimize BottomNav: instant visual feedback and ultra-low debounce for better responsiveness
This commit is contained in:
@ -15,11 +15,14 @@ const navItems = [
|
||||
]
|
||||
|
||||
const isNavigating = ref(false)
|
||||
const optimisticActivePath = ref('')
|
||||
|
||||
const navigateTo = async (path: string) => {
|
||||
// Prevent rapid multiple navigations (debounce guard)
|
||||
if (isNavigating.value) return
|
||||
if (route.path === path) return
|
||||
if (isNavigating.value) return
|
||||
|
||||
// Instant visual feedback
|
||||
optimisticActivePath.value = path
|
||||
|
||||
try {
|
||||
isNavigating.value = true
|
||||
@ -28,13 +31,18 @@ const navigateTo = async (path: string) => {
|
||||
if (e?.name !== 'NavigationDuplicated') {
|
||||
console.error('SIBU | Error de navegación en el menú inferior:', e)
|
||||
}
|
||||
// Revert on error
|
||||
optimisticActivePath.value = ''
|
||||
} finally {
|
||||
// Add a small delay to prevent rapid double-taps
|
||||
setTimeout(() => { isNavigating.value = false }, 300)
|
||||
// Ultra-short lock to avoid mechanical double-taps only
|
||||
setTimeout(() => { isNavigating.value = false }, 50)
|
||||
}
|
||||
}
|
||||
|
||||
const isActive = (path: string) => {
|
||||
if (optimisticActivePath.value) {
|
||||
return optimisticActivePath.value === path
|
||||
}
|
||||
return route.path === path || route.path.startsWith(path + '/')
|
||||
}
|
||||
|
||||
@ -67,9 +75,8 @@ onUnmounted(() => {
|
||||
v-for="item in navItems"
|
||||
:key="item.name"
|
||||
class="nav-item"
|
||||
:class="{ active: isActive(item.path), 'opacity-50 pointer-events-none': isNavigating }"
|
||||
@click.prevent="navigateTo(item.path)"
|
||||
@touchend.prevent="navigateTo(item.path)"
|
||||
:class="{ active: isActive(item.path) }"
|
||||
@click.stop="navigateTo(item.path)"
|
||||
>
|
||||
<span class="material-icons">{{ item.icon }}</span>
|
||||
<span class="nav-label">{{ t('navigation.' + item.name) }}</span>
|
||||
|
||||
Reference in New Issue
Block a user