Skip to content

Commit 407959d

Browse files
refactor(devtools): replace <a> tags with <StxLink> for router-managed navigation
Converts all static internal links to StxLink components which provide automatic active class management via the stx router and prefetching on hover. Removes manual updateActiveLinks() JS from layout — the router handles it via data-stx-link/data-stx-active-class attributes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 404d71a commit 407959d

File tree

7 files changed

+25
-59
lines changed

7 files changed

+25
-59
lines changed

packages/devtools/src/layouts/app.stx

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@
1818
.sidebar.collapsed .nav-item-text { display: none; }
1919
.sidebar.collapsed ~ .main-wrapper { margin-left: 56px !important; }
2020

21-
/* Override router inline styles on nav items — sidebar manages its own active state */
22-
#sidebar .nav-item { background: unset !important; color: unset !important; font-weight: unset !important; }
23-
24-
/* Active state */
21+
/* Active state — managed by StxLink + router via data-stx-active-class="active" */
2522
#sidebar .nav-item.active { background: #6366f1 !important; color: white !important; }
2623
#sidebar .nav-item.active svg { opacity: 1; }
2724
</style>
@@ -42,41 +39,10 @@
4239

4340
<script client>
4441
const collapsed = useLocalStorage<boolean>('sidebar-collapsed', false)
45-
const currentPath = state<string>(location.pathname)
4642

4743
function toggle(): void {
4844
collapsed.set(!collapsed())
4945
}
50-
51-
function isActive(href: string): boolean {
52-
const cur: string = currentPath()
53-
if (href === '/') return cur === '/'
54-
return cur === href || cur.startsWith(href + '/')
55-
}
56-
57-
function updateActiveLinks(): void {
58-
const cur: string = currentPath()
59-
const links: HTMLElement | null = useRef<HTMLElement>('sidebar-nav').current
60-
if (!links) return
61-
links.querySelectorAll('.nav-item').forEach((a: Element) => {
62-
const href: string = a.getAttribute('href') || ''
63-
const active: boolean = href === '/' ? cur === '/' : (cur === href || cur.startsWith(href + '/'))
64-
if (active) a.classList.add('active')
65-
else a.classList.remove('active')
66-
})
67-
}
68-
69-
onMount((): void => { updateActiveLinks() })
70-
71-
useEventListener('stx:navigate', (): void => {
72-
currentPath.set(location.pathname)
73-
updateActiveLinks()
74-
})
75-
76-
useEventListener('popstate', (): void => {
77-
currentPath.set(location.pathname)
78-
updateActiveLinks()
79-
})
8046
</script>
8147

8248
</body>

packages/devtools/src/pages/batch-details.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Batch Details — bun-queue
1414

1515
@section('content')
1616
<div class="max-w-[1200px] mx-auto p-6">
17-
<a href="/batches" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
17+
<StxLink to="/batches" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
1818
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
1919
Back to Batches
20-
</a>
20+
</StxLink>
2121

2222
<div class="flex items-center justify-between mb-6">
2323
<div>

packages/devtools/src/pages/group-details.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ Group Details — bun-queue
66

77
@section('content')
88
<div class="max-w-[1200px] mx-auto p-6">
9-
<a href="/groups" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
9+
<StxLink to="/groups" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
1010
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
1111
Back to Groups
12-
</a>
12+
</StxLink>
1313

1414
<div class="flex items-center justify-between mb-6">
1515
<div>

packages/devtools/src/pages/index.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ bun-queue Dashboard
8585
<div class="bg-[#141419] border border-zinc-800 rounded-lg p-6">
8686
<div class="flex items-center justify-between mb-4">
8787
<span class="text-sm font-semibold text-zinc-50">Recent Jobs</span>
88-
<a href="/jobs" class="inline-flex items-center px-3 py-1.5 rounded-md text-sm font-medium border border-zinc-800 bg-[#1e1e26] text-zinc-400 no-underline cursor-pointer hover:border-indigo-500 hover:text-zinc-50 transition-all duration-150">View All</a>
88+
<StxLink to="/jobs" class="inline-flex items-center px-3 py-1.5 rounded-md text-sm font-medium border border-zinc-800 bg-[#1e1e26] text-zinc-400 no-underline cursor-pointer hover:border-indigo-500 hover:text-zinc-50 transition-all duration-150">View All</StxLink>
8989
</div>
9090

9191
<!-- Loading state -->
@@ -123,7 +123,7 @@ bun-queue Dashboard
123123
<div class="bg-[#141419] border border-zinc-800 rounded-lg p-6">
124124
<div class="flex items-center justify-between mb-4">
125125
<span class="text-sm font-semibold text-zinc-50">Queue List</span>
126-
<a href="/queues" class="inline-flex items-center px-3 py-1.5 rounded-md text-sm font-medium border border-zinc-800 bg-[#1e1e26] text-zinc-400 no-underline cursor-pointer hover:border-indigo-500 hover:text-zinc-50 transition-all duration-150">View All</a>
126+
<StxLink to="/queues" class="inline-flex items-center px-3 py-1.5 rounded-md text-sm font-medium border border-zinc-800 bg-[#1e1e26] text-zinc-400 no-underline cursor-pointer hover:border-indigo-500 hover:text-zinc-50 transition-all duration-150">View All</StxLink>
127127
</div>
128128

129129
<!-- Loading state -->

packages/devtools/src/pages/job-details.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ Job Details — bun-queue
66

77
@section('content')
88
<div class="max-w-[1200px] mx-auto p-6">
9-
<a href="/jobs" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
9+
<StxLink to="/jobs" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
1010
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
1111
Back to Jobs
12-
</a>
12+
</StxLink>
1313

1414
<div class="flex items-center justify-between mb-6">
1515
<div>

packages/devtools/src/pages/queue-details.stx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ Queue Details — bun-queue
1616

1717
@section('content')
1818
<div class="max-w-[1200px] mx-auto p-6">
19-
<a href="/queues" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
19+
<StxLink to="/queues" class="inline-flex items-center gap-1.5 text-zinc-500 no-underline text-[0.8125rem] mb-4 transition-colors duration-150 hover:text-indigo-500">
2020
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
2121
Back to Queues
22-
</a>
22+
</StxLink>
2323

2424
<div class="flex items-center justify-between mb-6">
2525
<div>
Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
<!-- Sidebar -->
22
<aside class="sidebar fixed top-0 left-0 bottom-0 flex flex-col z-[100] overflow-hidden bg-[#141419] border-r border-zinc-800 transition-all duration-200 ease-in-out" :class="{ collapsed: collapsed() }" id="sidebar" ref="sidebar" style="width: 240px;">
33
<div class="flex items-center justify-between p-4 border-b border-zinc-800 min-h-[56px]">
4-
<a href="/" class="flex items-center gap-2.5 no-underline text-zinc-50 font-bold text-[0.9375rem] whitespace-nowrap overflow-hidden">
4+
<StxLink to="/" class="flex items-center gap-2.5 no-underline text-zinc-50 font-bold text-[0.9375rem] whitespace-nowrap overflow-hidden">
55
<div class="w-6 h-6 bg-indigo-500 rounded-md flex items-center justify-center shrink-0 text-xs text-white font-extrabold">Q</div>
66
<span class="sidebar-brand-text">bun-queue</span>
7-
</a>
7+
</StxLink>
88
<button class="sidebar-toggle-btn bg-transparent border-none text-zinc-500 cursor-pointer p-1 rounded flex items-center justify-center transition-colors duration-150 shrink-0 hover:text-zinc-50" @click="toggle()" ref="sidebar-toggle" title="Toggle sidebar">
99
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M3 4h10M3 8h10M3 12h10"/></svg>
1010
</button>
1111
</div>
1212
<nav class="flex-1 p-2 overflow-y-auto overflow-x-hidden" id="sidebar-nav" ref="sidebar-nav">
1313
<div class="nav-label text-[0.625rem] font-semibold text-zinc-500 uppercase tracking-wider px-3 pt-3 pb-1.5 whitespace-nowrap overflow-hidden">Navigation</div>
14-
<a href="/" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
14+
<StxLink to="/" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
1515
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
1616
<span class="nav-item-text">Dashboard</span>
17-
</a>
18-
<a href="/monitoring" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
17+
</StxLink>
18+
<StxLink to="/monitoring" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
1919
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
2020
<span class="nav-item-text">Monitoring</span>
21-
</a>
22-
<a href="/metrics" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
21+
</StxLink>
22+
<StxLink to="/metrics" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
2323
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>
2424
<span class="nav-item-text">Metrics</span>
25-
</a>
25+
</StxLink>
2626
<div class="nav-label text-[0.625rem] font-semibold text-zinc-500 uppercase tracking-wider px-3 pt-3 pb-1.5 whitespace-nowrap overflow-hidden">Management</div>
27-
<a href="/groups" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
27+
<StxLink to="/groups" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
2828
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
2929
<span class="nav-item-text">Groups</span>
30-
</a>
31-
<a href="/batches" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
30+
</StxLink>
31+
<StxLink to="/batches" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
3232
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2" ry="2"/><path d="M16 3H8l-2 4h12l-2-4z"/></svg>
3333
<span class="nav-item-text">Batches</span>
34-
</a>
35-
<a href="/jobs" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" data-stx-prefetch>
34+
</StxLink>
35+
<StxLink to="/jobs" class="nav-item flex items-center gap-3 px-3 py-2 rounded-md text-zinc-400 text-sm font-medium no-underline whitespace-nowrap overflow-hidden mb-px hover:bg-[#1e1e26] hover:text-zinc-50 transition-all duration-150" activeClass="active" prefetch>
3636
<svg class="w-[18px] h-[18px] shrink-0 opacity-70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
3737
<span class="nav-item-text">Jobs</span>
38-
</a>
38+
</StxLink>
3939
</nav>
4040
</aside>

0 commit comments

Comments
 (0)