Skip to content

Commit 961e06d

Browse files
committed
feat(039): reorganize sidebar, add collapse + tooltips
Sidebar restructure: - Group navigation into Workspace / System sections with subtle uppercase labels — Dashboard sits solo at the top as the landing. - Workspace section holds the four priority items (Servers, Secrets, Activity Log, Security Scanners) with Agent Tokens nested as a second-level child under Secrets. - System section holds Repositories and Configuration, rendered at reduced weight (text-[13px], text-base-content/70) to signal they are secondary. - Remove Search entry — the top header already exposes a tools/servers search input. - Move Feedback out of the main nav to an icon button in the footer row next to the Theme dropdown, sized appropriately (h-9, w-5 icon) and flex-centered so it aligns correctly in both expanded and collapsed states. - Add inline SVG icons for every personal-edition nav item so the collapsed rail is recognisable at a glance. Collapsible sidebar: - New sidebarCollapsed state + toggleSidebar action in the system store, persisted to localStorage under mcpproxy-sidebar-collapsed. - Sidebar animates between w-64 (expanded) and w-14 (icon rail). The main content padding in App.vue animates in lockstep. - Collapse chevron sits in the logo row when expanded; a separate expand chevron appears in the rail when collapsed. - Labels hide in collapsed mode; titles fall back to native tooltips for discoverability. ServerCard tooltip: - Wrap the security scan badge in a DaisyUI tooltip that explains the current state (clean / N warnings / dangerous / failed / scanning / not scanned). Every variant includes the disclaimer that the score is an experimental heuristic and findings should be verified manually — so users don't over-trust a "Clean" label. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0b20146 commit 961e06d

4 files changed

Lines changed: 353 additions & 79 deletions

File tree

frontend/src/App.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@
22
<div id="app" class="drawer lg:drawer-open">
33
<input id="sidebar-drawer" type="checkbox" class="drawer-toggle" />
44

5-
<!-- Main content area -->
6-
<div class="drawer-content grid grid-rows-[auto_1fr] h-screen bg-base-200 lg:pl-64">
5+
<!-- Main content area. The left padding is bound to sidebar collapsed
6+
state so the content fluidly reclaims space when the sidebar shrinks
7+
to its icon rail. -->
8+
<div
9+
class="drawer-content grid grid-rows-[auto_1fr] h-screen bg-base-200 transition-[padding] duration-200 ease-out"
10+
:class="systemStore.sidebarCollapsed ? 'lg:pl-14' : 'lg:pl-64'"
11+
>
712
<!-- Top Header -->
813
<TopHeader />
914

frontend/src/components/ServerCard.vue

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,14 @@
5656
</div>
5757
</div>
5858

59-
<!-- Security scan badge (Spec 039) -->
59+
<!-- Security scan badge (Spec 039)
60+
Wrapped in a DaisyUI tooltip that explains the state and carries a
61+
disclaimer that the risk score is an experimental heuristic. -->
6062
<div v-if="server.security_scan" class="flex items-center gap-2 mb-4">
61-
<div class="flex items-center gap-1.5 text-sm">
63+
<div
64+
class="flex items-center gap-1.5 text-sm tooltip tooltip-right tooltip-bottom max-w-xs"
65+
:data-tip="securityBadgeTooltip"
66+
>
6267
<!-- Shield icon -->
6368
<svg
6469
class="w-4 h-4 flex-shrink-0"
@@ -376,6 +381,35 @@ const securityBadgeText = computed(() => {
376381
}
377382
})
378383
384+
// Hover explanation for the security badge. Every state carries the
385+
// experimental-heuristic disclaimer so users don't over-trust the label.
386+
const securityBadgeTooltip = computed(() => {
387+
const scan = props.server.security_scan
388+
if (!scan) return ''
389+
const disclaimer =
390+
'Experimental heuristic — verify findings manually; results may not be precise.'
391+
switch (scan.status) {
392+
case 'clean':
393+
return `Clean: no findings above the warning threshold in the most recent scan. ${disclaimer}`
394+
case 'warnings': {
395+
const count = scan.finding_counts?.warning ?? 0
396+
return `${count} warning${count !== 1 ? 's' : ''} found — review the Security tab for details. ${disclaimer}`
397+
}
398+
case 'dangerous': {
399+
const dangerous = scan.finding_counts?.dangerous ?? 0
400+
return `${dangerous} dangerous finding${dangerous !== 1 ? 's' : ''} detected. Review before approving. ${disclaimer}`
401+
}
402+
case 'failed':
403+
return `The last scan failed to produce a verdict. Re-run from the Security tab. ${disclaimer}`
404+
case 'not_scanned':
405+
return 'This server has not been scanned yet.'
406+
case 'scanning':
407+
return 'Security scan in progress…'
408+
default:
409+
return disclaimer
410+
}
411+
})
412+
379413
// Determine if error message should be shown (FR-018, FR-019)
380414
// Suppress verbose last_error when health.action already conveys the issue
381415
const shouldShowError = computed(() => {

0 commit comments

Comments
 (0)