diff --git a/frontend/src/components/BottomNav.vue b/frontend/src/components/BottomNav.vue index db5e520..e06c027 100644 --- a/frontend/src/components/BottomNav.vue +++ b/frontend/src/components/BottomNav.vue @@ -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)" > {{ item.icon }} {{ t('navigation.' + item.name) }}