diff --git a/tools/public/assets/style.css b/tools/public/assets/style.css index 3936734..a962cbd 100644 --- a/tools/public/assets/style.css +++ b/tools/public/assets/style.css @@ -68,9 +68,6 @@ cds-side-nav[expanded] { pointer-events: auto; } .side-nav-brand { display: flex; align-items: center; gap: 0.75rem; padding: 2rem 1rem 1rem; color: var(--cds-text-primary, #161616); font-weight: 600; font-size: 14px; } .side-nav-brand img { display: block; } -/* separator between the service links and Help in the header nav */ -.header-nav-divider { width: 1px; align-self: stretch; margin: 0.7rem 0.25rem; background: var(--cds-border-subtle, #e0e0e0); } - /* ── layout ─────────────────────────────────────────────────────────────── */ .container { width: 100%; max-width: 1136px; margin: 0 auto; padding: 0 1.5rem; } main.container { flex: 1 0 auto; padding-top: 1.5rem; padding-bottom: 1.5rem; } diff --git a/tools/server.js b/tools/server.js index b6eca9c..148f883 100644 --- a/tools/server.js +++ b/tools/server.js @@ -134,10 +134,12 @@ const appHeader = (session, active) => { const sideLink = (href, label, key, icon) => `${icon || ''}${label}`; const name = session ? (session.firstName || session.phone || '') : ''; - // Auth is a menu item now, so the header's right side only carries identity. + // Help and the auth action are icon-only global header actions. + const headerAction = (href, label, svg, extra = '') => + `${svg.replace('slot="title-icon"', 'slot="icon"')}${label}`; const headerAuth = session - ? 'Sign out' - : 'Sign in'; + ? headerAction('/auth/logout', 'Sign out', SIDE_NAV_ICONS.logout, ' data-signout') + : headerAction('/auth/login', 'Sign in', SIDE_NAV_ICONS.login); const sideAuth = session ? `${SIDE_NAV_ICONS.logout}Sign out` : `${SIDE_NAV_ICONS.login}Sign in`; @@ -150,13 +152,14 @@ const appHeader = (session, active) => { ${toolLink('/', 'Home', 'home')} ${session ? `${toolLink('/cropper', 'Image Cropper', 'cropper')} - ${toolLink('/fingerprint', 'Fingerprint Agent', 'fingerprint')} - ` : ''} - ${toolLink('/help', 'Help', 'help')} - ${headerAuth} + ${toolLink('/fingerprint', 'Fingerprint Agent', 'fingerprint')}` : ''} ${active === 'fingerprint' ? 'Agent offline' : ''} - ${session ? `
${esc(name.trim().slice(0, 2).toUpperCase())}${esc(name)}
` : ''} +
+ ${headerAction('/help', 'Help', SIDE_NAV_ICONS.help)} + ${headerAuth} + ${session ? `${esc(name.trim().slice(0, 2).toUpperCase())}${esc(name)}` : ''} +
@@ -164,6 +167,7 @@ const appHeader = (session, active) => {
${sideLink('/', 'Home', 'home', SIDE_NAV_ICONS.home)} + ${session ? `${sideLink('/cropper', 'Image Cropper', 'cropper', SIDE_NAV_ICONS.crop)} ${sideLink('/fingerprint', 'Fingerprint Agent', 'fingerprint', SIDE_NAV_ICONS.fingerprint)} ` : ''} diff --git a/tools/test/server.test.js b/tools/test/server.test.js index c907f5c..6077e52 100644 --- a/tools/test/server.test.js +++ b/tools/test/server.test.js @@ -353,16 +353,20 @@ test('landing header is server-rendered for the session', async () => { const { base, stop } = await bootApp(); try { const anon = await (await fetch(`${base}/`)).text(); - assert.match(anon, /href="\/auth\/login">Sign in'), 'header marker is replaced'); - // signed out: no service links, but Help and Sign in are always there + // signed out: Home only in the header nav; Help and Sign in are icon-only + // global header actions + assert.match(anon, /cds-header-nav-item href="\/" aria-current="page"/); assert.ok(!anon.includes('cds-header-nav-item href="/cropper"'), 'no cropper in header nav when signed out'); assert.ok(!anon.includes('cds-header-nav-item href="/fingerprint"'), 'no fingerprint in header nav when signed out'); - assert.match(anon, /cds-header-nav-item href="\/help"/); + assert.match(anon, /cds-header-global-action href="\/help">Help<\/span>/); + assert.match(anon, /Sign in<\/span>/); + // side nav groups Home | Help, Sign in with a single divider assert.match(anon, /cds-side-nav-link href="\/help"/); - // the divider only groups the services, so it is absent when signed out - assert.ok(!anon.includes('cds-side-nav-divider'), 'no side nav divider without services'); - assert.ok(!anon.includes('header-nav-divider'), 'no header divider without services'); + assert.equal((anon.match(//g) || []).length, 1, 'one side nav divider when signed out'); // no identity or sign-out when signed out assert.ok(!anon.includes('user-chip'), 'no user chip when signed out'); assert.ok(!anon.includes('data-signout'), 'no sign-out when signed out'); @@ -378,16 +382,17 @@ test('landing header is server-rendered for the session', async () => { const authed = await (await fetch(`${base}/`, { headers: { cookie: cookies } })).text(); assert.match(authed, /Ada/); assert.match(authed, /user-chip/); - assert.match(authed, /href="\/auth\/logout"[^>]*>Sign outSign out<\/span>/); + // side nav groups Home | services | Help, Sign out with two dividers assert.match(authed, /cds-side-nav-link href="\/cropper"/); assert.match(authed, /cds-side-nav-link href="\/help"/); - assert.match(authed, /cds-side-nav-divider/); - assert.match(authed, /header-nav-divider/); + assert.equal((authed.match(//g) || []).length, 2, 'two side nav dividers when signed in'); // side nav items carry Carbon icons in the title-icon slot assert.match(authed, /cds-side-nav-link href="\/cropper"[^>]*>]*> { assert.match(html, /cds-accordion-item title="Image Cropper"/); assert.match(html, /cds-accordion-item title="Fingerprint Agent"/); assert.match(html, /accordion\.min\.js/); - assert.match(html, /cds-header-nav-item href="\/help" aria-current="page"/); + assert.match(html, /cds-header-global-action href="\/help"/); assert.match(html, /cds-side-nav-link href="\/help" aria-current="page"/); } finally { await stop();