feat(ui): ui-shell header with tool links, mobile side nav, Youreka logo

- header: Carbon ui-shell (cds-header) with the Youreka logo (from
  idid-enterprise-portal), Image Cropper / Fingerprint Agent nav items
  (aria-current on the active tool), the agent status tag on the wizard,
  and the operator chip + Sign out on desktop
- mobile: cds-side-nav (logo above the items, both tools, a divider, then
  Sign out) toggled by the ui-shell menu button; account actions move out
  of the header below 1056px, the nav is hidden at desktop widths
- the header is built once in server.js (appHeader) and injected into the
  landing, both tools and error pages — no per-page duplication
- removed my duplicate menu-button toggle: ui-shell coordinates the menu
  button and side nav itself (the duplicate cancelled it out)
- fixes: 'cds-header' was hidden by a selector-list typo
  (cds-header, cds-side-nav:not(:defined)); the collapsed side nav no
  longer captures taps

Tools banner logo asset added (public/assets/youreka-logo.png).
This commit is contained in:
2026-10-01 03:53:24 +01:00
parent 22735c0709
commit 340d8da19d
9 changed files with 115 additions and 111 deletions
+9 -1
View File
@@ -317,7 +317,15 @@ test('landing header is server-rendered for the session', async () => {
try {
const anon = await (await fetch(`${base}/`)).text();
assert.match(anon, /href="\/auth\/login">Sign in</);
assert.ok(!anon.includes('<!--session-nav-->'), 'marker is replaced');
assert.ok(!anon.includes('<!--app-header-->'), 'header marker is replaced');
// tools live in the header nav and in the mobile side nav
assert.match(anon, /cds-header-nav-item href="\/cropper"/);
assert.match(anon, /cds-header-nav-item href="\/fingerprint"/);
assert.match(anon, /cds-side-nav-link href="\/cropper"/);
assert.match(anon, /cds-side-nav-divider/);
assert.match(anon, /cds-side-nav-link href="\/auth\/logout"/);
assert.match(anon, /youreka-logo\.png/);
assert.match(anon, /header-menu-button/);
const cookies = await login(base);
const authed = await (await fetch(`${base}/`, { headers: { cookie: cookies } })).text();