Make Website Scanner discoverable in sidebar nav.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Deploy Recon was wired at /deploy-recon but buried at the bottom of a non-scrolling sidebar under an opaque label; move it after Crucible, rename to Website Scanner, enable nav scroll, and add route/nav smoke tests plus README.
This commit is contained in:
@@ -106,12 +106,16 @@
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
/* No flex-grow: let the matrix rain claim the remaining space */
|
||||
flex: 0 0 auto;
|
||||
/* Scroll when many nav items + matrix rain exceed viewport height */
|
||||
flex: 1 1 auto;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 1rem 0.75rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(0, 232, 245, 0.35) transparent;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
|
||||
17
server/web/src/components/Layout/Layout.nav.test.ts
Normal file
17
server/web/src/components/Layout/Layout.nav.test.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { operatorNavItems } from './Layout';
|
||||
|
||||
describe('operator sidebar nav', () => {
|
||||
it('includes Website Scanner linking to /deploy-recon', () => {
|
||||
const item = operatorNavItems.find((i) => i.to === '/deploy-recon');
|
||||
expect(item).toBeDefined();
|
||||
expect(item!.label).toBe('Website Scanner');
|
||||
expect(item!.icon).toBe('recon');
|
||||
});
|
||||
|
||||
it('places Website Scanner directly after Crucible for discoverability', () => {
|
||||
const scannerIdx = operatorNavItems.findIndex((i) => i.to === '/deploy-recon');
|
||||
const crucibleIdx = operatorNavItems.findIndex((i) => i.to === '/crucible');
|
||||
expect(scannerIdx).toBe(crucibleIdx + 1);
|
||||
});
|
||||
});
|
||||
@@ -51,6 +51,7 @@ type NavItem = { readonly to: string; readonly label: string; readonly icon: str
|
||||
const NAV_BASE: readonly NavItem[] = [
|
||||
{ to: '/dashboard', label: 'Command Deck', icon: 'deck' },
|
||||
{ to: '/crucible', label: 'Crucible', icon: 'crucible' },
|
||||
{ to: '/deploy-recon', label: 'Website Scanner', icon: 'recon' },
|
||||
{ to: '/activity', label: 'Activity Feed', icon: 'activity' },
|
||||
{ to: '/roi', label: 'ROI Intelligence', icon: 'roi' },
|
||||
{ to: '/lotl-timeline', label: 'Onion', icon: 'onion' },
|
||||
@@ -59,10 +60,12 @@ const NAV_BASE: readonly NavItem[] = [
|
||||
{ to: '/mission-deck', label: 'Mission Deck', icon: 'mission', glow: true },
|
||||
{ to: '/builds', label: 'Builds', icon: 'builds' },
|
||||
{ to: '/emberwake', label: 'Emberwake', icon: 'ember' },
|
||||
{ to: '/deploy-recon', label: 'Deploy Recon', icon: 'recon' },
|
||||
{ to: '/settings', label: 'Calibrate', icon: 'gear' },
|
||||
];
|
||||
|
||||
/** Exported for nav regression tests (route + label discoverability). */
|
||||
export const operatorNavItems = NAV_BASE;
|
||||
|
||||
const SEER_NAV: NavItem = { to: '/seer', label: 'Seer', icon: 'seer' };
|
||||
|
||||
function buildNav(aiControlEnabled: boolean): NavItem[] {
|
||||
@@ -340,6 +343,7 @@ export default function Layout({ children }: LayoutProps) {
|
||||
'/lotl-timeline': 'Onion',
|
||||
'/pathtracer': 'Tracer',
|
||||
'/forge': 'Forge',
|
||||
'/deploy-recon': 'Scanner',
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -369,6 +373,7 @@ export default function Layout({ children }: LayoutProps) {
|
||||
<NavLink
|
||||
key={item.to}
|
||||
to={item.to}
|
||||
title={item.to === '/deploy-recon' ? 'Deploy Recon — browser spread scanner (/browser-spread)' : undefined}
|
||||
className={({ isActive }) =>
|
||||
`nav-item${'glow' in item && item.glow ? ' nav-item--mission' : ''} ${isActive ? 'active' : ''}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user