feat(ui): animate navbar tab on new events

This commit is contained in:
josedario87
2025-06-11 03:57:57 -06:00
parent dce714e778
commit 94ff4ea726

View File

@@ -54,15 +54,26 @@ const hasBadge = (path, op) => {
return table && realtime.badges[table]?.[op] return table && realtime.badges[table]?.[op]
} }
const hasAnyBadge = (path) => {
const table = tableForPath(path)
if (!table) return false
const b = realtime.badges[table]
return b.INSERT || b.UPDATE || b.DELETE
}
// clases dinámicas p/ mostrar / ocultar barra // clases dinámicas p/ mostrar / ocultar barra
const sidebarClasses = computed(() => ui.sidebarOpen ? 'translate-x-0' : '-translate-x-full') const sidebarClasses = computed(() => ui.sidebarOpen ? 'translate-x-0' : '-translate-x-full')
const handleLinkClick = () => { const handleLinkClick = (path) => {
// Close sidebar if desktopNavbarPersistent is false or if it's mobile view (width < 768px) // Close sidebar if desktopNavbarPersistent is false or if it's mobile view (width < 768px)
// Assuming 768px is the 'md' breakpoint. // Assuming 768px is the 'md' breakpoint.
if (!ui.desktopNavbarPersistent || window.innerWidth < 768) { if (!ui.desktopNavbarPersistent || window.innerWidth < 768) {
ui.closeSidebar() ui.closeSidebar()
} }
// Clear badges for this module when the link is clicked
const table = tableForPath(path)
if (table) realtime.clearBadgesForTable(table)
// Otherwise, (desktopNavbarPersistent is true AND width >= 768px), do nothing to keep sidebar open. // Otherwise, (desktopNavbarPersistent is true AND width >= 768px), do nothing to keep sidebar open.
} }
</script> </script>
@@ -89,9 +100,9 @@ const handleLinkClick = () => {
<RouterLink <RouterLink
:to="l.to" :to="l.to"
class="nav-link flex items-center gap-3 w-full px-3 py-2 rounded-md font-medium transition group" class="nav-link flex items-center gap-3 w-full px-3 py-2 rounded-md font-medium transition group"
:class="activePath.startsWith(l.to) ? 'active' : ''" :class="[activePath.startsWith(l.to) ? 'active' : '', hasAnyBadge(l.to) ? 'notified' : '']"
:style="{ '--accent-color': accentColorForPath(l.to) }" :style="{ '--accent-color': accentColorForPath(l.to) }"
@click="handleLinkClick" @click="handleLinkClick(l.to)"
> >
<span class="text-lg" aria-hidden="true">{{ l.icon }}</span> <span class="text-lg" aria-hidden="true">{{ l.icon }}</span>
<span class="truncate flex-1">{{ l.label }}</span> <span class="truncate flex-1">{{ l.label }}</span>
@@ -117,7 +128,7 @@ ul { list-style: none; padding-left: 0; }
border: 1px solid var(--accent-color); border: 1px solid var(--accent-color);
overflow: hidden; overflow: hidden;
border-radius: 0.375rem; border-radius: 0.375rem;
transition: background-color 0.3s ease, color 0.3s ease; transition: background-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
z-index: 0; z-index: 0;
} }
@@ -159,6 +170,10 @@ ul { list-style: none; padding-left: 0; }
box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px 0 rgba(0,0,0,0.06); box-shadow: 0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px 0 rgba(0,0,0,0.06);
} }
.nav-link.notified {
transform: translateX(4px);
}
/* Scrollbar styling using primary color */ /* Scrollbar styling using primary color */
.custom-scroll::-webkit-scrollbar { width: 8px; } .custom-scroll::-webkit-scrollbar { width: 8px; }
.custom-scroll::-webkit-scrollbar-track { background: transparent; } .custom-scroll::-webkit-scrollbar-track { background: transparent; }