feat: amber wordmark and NavRail active indicator
This commit is contained in:
74
src/components/NavRail.vue
Normal file
74
src/components/NavRail.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useTimerStore } from '../stores/timer'
|
||||
import {
|
||||
LayoutDashboard,
|
||||
Clock,
|
||||
FolderKanban,
|
||||
List,
|
||||
BarChart3,
|
||||
FileText,
|
||||
Settings
|
||||
} from 'lucide-vue-next'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const timerStore = useTimerStore()
|
||||
|
||||
const navItems = [
|
||||
{ name: 'Dashboard', path: '/', icon: LayoutDashboard },
|
||||
{ name: 'Timer', path: '/timer', icon: Clock },
|
||||
{ name: 'Projects', path: '/projects', icon: FolderKanban },
|
||||
{ name: 'Entries', path: '/entries', icon: List },
|
||||
{ name: 'Reports', path: '/reports', icon: BarChart3 },
|
||||
{ name: 'Invoices', path: '/invoices', icon: FileText },
|
||||
{ name: 'Settings', path: '/settings', icon: Settings }
|
||||
]
|
||||
|
||||
const currentPath = computed(() => route.path)
|
||||
|
||||
function navigate(path: string) {
|
||||
router.push(path)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="w-12 flex flex-col items-center bg-bg-surface border-r border-border-subtle shrink-0">
|
||||
<!-- Navigation icons -->
|
||||
<div class="flex-1 flex flex-col items-center pt-2 gap-1">
|
||||
<button
|
||||
v-for="item in navItems"
|
||||
:key="item.path"
|
||||
@click="navigate(item.path)"
|
||||
class="relative w-12 h-12 flex items-center justify-center transition-colors duration-150 group"
|
||||
:class="currentPath === item.path
|
||||
? 'text-text-primary'
|
||||
: 'text-text-tertiary hover:text-text-secondary'"
|
||||
:title="item.name"
|
||||
>
|
||||
<!-- Active indicator (left border) -->
|
||||
<div
|
||||
v-if="currentPath === item.path"
|
||||
class="absolute left-0 top-2 bottom-2 w-[2px] bg-accent"
|
||||
/>
|
||||
|
||||
<component :is="item.icon" class="w-[18px] h-[18px]" :stroke-width="1.5" />
|
||||
|
||||
<!-- Tooltip -->
|
||||
<div class="absolute left-full ml-2 px-2 py-1 bg-bg-elevated border border-border-subtle rounded text-[0.6875rem] text-text-primary whitespace-nowrap opacity-0 pointer-events-none group-hover:opacity-100 transition-opacity duration-150 z-50">
|
||||
<div class="absolute -left-1 top-1/2 -translate-y-1/2 w-0 h-0 border-y-4 border-y-transparent border-r-4" style="border-right-color: var(--color-bg-elevated)"></div>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Timer running indicator (bottom) -->
|
||||
<div class="pb-4">
|
||||
<div
|
||||
v-if="timerStore.isRunning"
|
||||
class="w-2 h-2 rounded-full bg-status-running animate-pulse-dot"
|
||||
/>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
Reference in New Issue
Block a user