Step 7: UI foundation #3

Open
opened 2026-09-21 17:13:42 +00:00 by kayg · 17 comments
Owner

packages/ui tokens and primitives per docs/UI.md, app shell, editable sidebar (in memory), inbox panel, account and version, Dashboard with honest empty states, svelte-sonner.

Step 7 in docs/PLAN.md. Done when: merged to dev, browser-verified

packages/ui tokens and primitives per docs/UI.md, app shell, editable sidebar (in memory), inbox panel, account and version, Dashboard with honest empty states, svelte-sonner. Step 7 in docs/PLAN.md. Done when: merged to dev, browser-verified
Author
Owner

Started step 7 UI foundation on branch ui-foundation, base head fac2890c93276e645d6ba439ff2291ba93f0eec4.

Scope: packages/ui tokens/primitives/tests, packages/web app shell/sidebar/inbox/dashboard/routes/sonner, browser verification and initial-route gzip measurement. Required UI skills and docs loaded before implementation.

Started step 7 UI foundation on branch `ui-foundation`, base head `fac2890c93276e645d6ba439ff2291ba93f0eec4`. Scope: `packages/ui` tokens/primitives/tests, `packages/web` app shell/sidebar/inbox/dashboard/routes/sonner, browser verification and initial-route gzip measurement. Required UI skills and docs loaded before implementation.
Author
Owner

Fast gate completed on ui-foundation at the current implementation head.

Verbatim output:

PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: OpenAPI and TypeScript client drift

The UI package tests cover the non-chart/table primitives' accessible roles/names and interaction behavior; the web package still passes its existing health tests.

Fast gate completed on `ui-foundation` at the current implementation head. Verbatim output: ```text PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: Vitest PASS fast: UI package Vitest PASS fast: OpenAPI and TypeScript client drift ``` The UI package tests cover the non-chart/table primitives' accessible roles/names and interaction behavior; the web package still passes its existing health tests.
Author
Owner

UI foundation findings worth keeping:

  • The first release-browser run exposed $state is not defined from navigation.ts: Svelte runes require the .svelte.ts module treatment. The store now lives in navigation.svelte.ts, and the web Vite resolver recognizes that extension.
  • The overlap check initially counted sidebar text clipped behind the fixed footer. It now checks the center hit-test before comparing visible text boxes, so covered text is excluded while real overlap remains a failure.
  • Applying container-type to intrinsic inline controls made StatusDot collapse to zero width under size containment. Containment remains on block/layout primitives; intrinsic controls stay content-sized.
UI foundation findings worth keeping: - The first release-browser run exposed `$state is not defined` from `navigation.ts`: Svelte runes require the `.svelte.ts` module treatment. The store now lives in `navigation.svelte.ts`, and the web Vite resolver recognizes that extension. - The overlap check initially counted sidebar text clipped behind the fixed footer. It now checks the center hit-test before comparing visible text boxes, so covered text is excluded while real overlap remains a failure. - Applying `container-type` to intrinsic inline controls made `StatusDot` collapse to zero width under size containment. Containment remains on block/layout primitives; intrinsic controls stay content-sized.
Author
Owner

UI foundation finished on branch ui-foundation.

Head: fb63985

Final scripts/verify fast output:

PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: OpenAPI and TypeScript client drift

Final scripts/verify browser output:

PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: build web app
PASS browser: build release binary
PASS browser: Playwright against release server

Initial dashboard route JS is 54,121 bytes gzip, measured as the sum of the gzip-9 sizes of the JS assets referenced by packages/web/build/index.html.

Screenshots:

  • /mnt/hdd/infraternal/artifacts/ui-foundation/desktop-light.png
  • /mnt/hdd/infraternal/artifacts/ui-foundation/desktop-dark.png
  • /mnt/hdd/infraternal/artifacts/ui-foundation/mobile-light.png
  • /mnt/hdd/infraternal/artifacts/ui-foundation/mobile-dark.png

Additional verification: the 1024×900 icon-rail spot check reported rail: true, overflow: false, triggerFits: true, and no browser errors.

UI foundation finished on branch `ui-foundation`. Head: `fb63985` Final `scripts/verify fast` output: ```text PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: Vitest PASS fast: UI package Vitest PASS fast: OpenAPI and TypeScript client drift ``` Final `scripts/verify browser` output: ```text PASS browser: JavaScript dependencies PASS browser: install Chromium and system dependencies PASS browser: build web app PASS browser: build release binary PASS browser: Playwright against release server ``` Initial dashboard route JS is 54,121 bytes gzip, measured as the sum of the gzip-9 sizes of the JS assets referenced by `packages/web/build/index.html`. Screenshots: - `/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-light.png` - `/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-dark.png` - `/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-light.png` - `/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-dark.png` Additional verification: the 1024×900 icon-rail spot check reported `rail: true`, `overflow: false`, `triggerFits: true`, and no browser errors.
Author
Owner

Build job ui-foundation (gpt-5.6-luna/max) finished. Author's report:

ISSUE UPDATE kayg/infraternal#3  
branch: ui-foundation  
head: fb63985ab8c53c0a320aee1c05af5711f66bdd0d  
done:
- UI tokens/primitives, tests, Toaster
- Responsive shell, editable sidebar, drawer/icon rail
- Dashboard, empty states, routes, inbox/account/version
- Browser verification and screenshots

skill rules applied:
- Motion limited to transform/opacity with reduced-motion support.
- Shared spacing, type, color, radius, layout, and accessibility tokens.
- Keyboard reorder actions, live announcements, focus handling, and named controls.
- Honest, concise empty-state copy and deliberate truncation/wrapping.
- Contrast measured; light subtle text is 4.67:1 on canvas.

initial route JS gzip: 54,121 bytes

gates:
  PASS fast: JavaScript dependencies
  PASS fast: build web app
  PASS fast: cargo fmt --check
  PASS fast: cargo clippy
  PASS fast: cargo test
  PASS fast: svelte-check
  PASS fast: UI package svelte-check
  PASS fast: Vitest
  PASS fast: UI package Vitest
  PASS fast: OpenAPI and TypeScript client drift
  PASS browser: JavaScript dependencies
  PASS browser: install Chromium and system dependencies
  PASS browser: build web app
  PASS browser: build release binary
  PASS browser: Playwright against release server

screenshots:
- [desktop-light.png](/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-light.png)
- [desktop-dark.png](/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-dark.png)
- [mobile-light.png](/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-light.png)
- [mobile-dark.png](/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-dark.png)

open problems:
- Safari/iOS manual checklist remains for the owner; no code blocker.```
Independent review `ui-review` running.
Build job `ui-foundation` (gpt-5.6-luna/max) finished. Author's report: ``` ISSUE UPDATE kayg/infraternal#3 branch: ui-foundation head: fb63985ab8c53c0a320aee1c05af5711f66bdd0d done: - UI tokens/primitives, tests, Toaster - Responsive shell, editable sidebar, drawer/icon rail - Dashboard, empty states, routes, inbox/account/version - Browser verification and screenshots skill rules applied: - Motion limited to transform/opacity with reduced-motion support. - Shared spacing, type, color, radius, layout, and accessibility tokens. - Keyboard reorder actions, live announcements, focus handling, and named controls. - Honest, concise empty-state copy and deliberate truncation/wrapping. - Contrast measured; light subtle text is 4.67:1 on canvas. initial route JS gzip: 54,121 bytes gates: PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: Vitest PASS fast: UI package Vitest PASS fast: OpenAPI and TypeScript client drift PASS browser: JavaScript dependencies PASS browser: install Chromium and system dependencies PASS browser: build web app PASS browser: build release binary PASS browser: Playwright against release server screenshots: - [desktop-light.png](/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-light.png) - [desktop-dark.png](/mnt/hdd/infraternal/artifacts/ui-foundation/desktop-dark.png) - [mobile-light.png](/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-light.png) - [mobile-dark.png](/mnt/hdd/infraternal/artifacts/ui-foundation/mobile-dark.png) open problems: - Safari/iOS manual checklist remains for the owner; no code blocker.``` Independent review `ui-review` running.
Author
Owner

Review started: independent UI foundation review in detached worktree at fb63985ab8; base dev at a9961a2198. Scope is read-only review of git diff dev...HEAD plus production-browser verification.

Review started: independent UI foundation review in detached worktree at fb63985ab8c53c0a320aee1c05af5711f66bdd0d; base dev at a9961a2198ca94bf9db1650efe5c56ee247229c1. Scope is read-only review of git diff dev...HEAD plus production-browser verification.
Author
Owner

Review findings recorded so far (all reproduced on release binary fb63985): HIGH: at 1024x768/768x1024 the icon rail hides dashboard/group labels and exposes unnamed links/buttons in the accessibility tree; HIGH: entering Edit sidebar in the rail hides item/group actions while rename/create controls clip past the 68px rail (screenshots /mnt/hdd/infraternal/artifacts/ui-review/light-normal-1024x768-edit.png and light-normal-768x1024-edit.png); HIGH: mobile Navigation aria-modal has no focus trap—after 18 Tab presses focus reaches BODY, Skip to content, header controls outside the drawer; HIGH: account-menu Sign out leaves URL/menu unchanged and emits no action. Further primitive/motion findings are in progress.

Review findings recorded so far (all reproduced on release binary fb63985): HIGH: at 1024x768/768x1024 the icon rail hides dashboard/group labels and exposes unnamed links/buttons in the accessibility tree; HIGH: entering Edit sidebar in the rail hides item/group actions while rename/create controls clip past the 68px rail (screenshots /mnt/hdd/infraternal/artifacts/ui-review/light-normal-1024x768-edit.png and light-normal-768x1024-edit.png); HIGH: mobile Navigation aria-modal has no focus trap—after 18 Tab presses focus reaches BODY, Skip to content, header controls outside the drawer; HIGH: account-menu Sign out leaves URL/menu unchanged and emits no action. Further primitive/motion findings are in progress.
Author
Owner

ISSUE UPDATE kayg/infraternal#3\nreview of: ui-foundation @ fb63985ab8c53c0a320aee1c05af5711f66bdd0d\nverdict: merge after fixes\n\ngates:\nPASS fast: JavaScript dependencies\nPASS fast: build web app\nPASS fast: cargo fmt --check\nPASS fast: cargo clippy\nPASS fast: cargo test\nPASS fast: svelte-check\nPASS fast: UI package svelte-check\nPASS fast: Vitest\nPASS fast: UI package Vitest\nPASS fast: OpenAPI and TypeScript client drift\nPASS browser: JavaScript dependencies\nPASS browser: install Chromium and system dependencies\nPASS browser: build web app\nPASS browser: build release binary\nPASS browser: Playwright against release server\n\nscreenshots: /mnt/hdd/infraternal/artifacts/ui-review/\n\nfindings:\n1. [HIGH][Accessibility] The icon rail hides Dashboard/group labels without supplying accessible names; the 1024px accessibility snapshot exposes unnamed links/buttons (packages/web/src/lib/shell/Sidebar.svelte:77-97,217).\n2. [HIGH][Layout] Edit sidebar at 1024x768 and 768x1024 hides item/group actions while rename/create controls clip past the 68px rail (Sidebar.svelte:98-112,122-147,216-223); evidence: light-normal-1024x768-edit.png and light-normal-768x1024-edit.png.\n3. [HIGH][Accessibility] The custom mobile aria-modal has no focus trap; after 19 Tabs focus is BODY/outside and Escape does not close it (packages/web/src/lib/shell/AppShell.svelte:115,120-125).\n4. [HIGH][Accessibility/Security] Account-menu Sign out is a visible no-op: click leaves the URL/menu unchanged and emits no toast (packages/web/src/lib/shell/Sidebar.svelte:158-162).\n5. [HIGH][Accessibility] Popover opens a role=dialog panel without moving focus into it, so its Escape handler is unreachable when content is non-focusable (packages/ui/src/lib/Popover.svelte:22-29); the test only asserts open text (primitives.test.ts:62-64).\n6. [HIGH][Accessibility] Field makes the label target optional and never associates hint/error IDs or aria-invalid/aria-describedby with the child control (packages/ui/src/lib/Field.svelte:7-24).\n7. [MEDIUM][Layout] AppShell responsive hide rules lose to IconButton scoped display: hamburger and rail-toggle render at every width; rail-toggle is a no-op on mobile and squeezes/truncates the 320px breadcrumb (AppShell.svelte:95,103,150,158-162; screenshots light-normal-1440x900-dashboard.png and light-normal-320x640-dashboard.png).\n8. [MEDIUM][Accessibility] Menu button omits ArrowDown/ArrowUp opening behavior required by its role; focused Account + ArrowDown leaves the menu closed (packages/ui/src/lib/Menu.svelte:36-42).\n9. [MEDIUM][Accessibility] SPA navigation does not move focus to the new heading or close transient menu state; Profile navigation leaves focus on BODY with the Account menu still visible (AppShell.svelte:40-53, Sidebar.svelte:160-161).\n10. [MEDIUM][Color] Manual theme switching changes data-theme but Toaster remains theme=system; in a light OS context, the dark app produced a white toast (AppShell.svelte:71-76, Toaster.svelte:8; light-manual-dark-toast.png).\n11. [MEDIUM][UI/Performance] svelte-sonner default toast transition animates height and box-shadow in addition to transform/opacity (Toaster.svelte:8; computed normal-motion transition: transform 0.4s, opacity 0.4s, height 0.4s, box-shadow 0.2s), contrary to the UI motion contract.\n12. [MEDIUM][UI/Accessibility] Touch hover states are not gated and active scale also runs during keyboard Space activation (Sidebar.svelte:189, Menu.svelte:52, AppShell.svelte:147, Button.svelte:57, IconButton.svelte:55; keyboard computed transform matrix was 0.96).\n13. [MEDIUM][Accessibility] Tooltip puts aria-describedby on a non-focusable wrapper instead of the wrapped control, so the tooltip description is not reliably announced (packages/ui/src/lib/Tooltip.svelte:9-11).\n14. [MEDIUM][Reuse] Dashboard and PlaceholderPage duplicate page-intro/eyebrow/lede styling instead of extending a shared primitive (packages/web/src/routes/+page.svelte:67-82, packages/web/src/lib/PlaceholderPage.svelte:24-28).\n15. [MEDIUM][Typography] The Inter token is declared but no font face/import is shipped; on this Debian VM fc-match Inter resolves to WenQuanYi Zen Hei (packages/ui/src/tokens.css:19-20).

ISSUE UPDATE kayg/infraternal#3\nreview of: ui-foundation @ fb63985ab8c53c0a320aee1c05af5711f66bdd0d\nverdict: merge after fixes\n\ngates:\nPASS fast: JavaScript dependencies\nPASS fast: build web app\nPASS fast: cargo fmt --check\nPASS fast: cargo clippy\nPASS fast: cargo test\nPASS fast: svelte-check\nPASS fast: UI package svelte-check\nPASS fast: Vitest\nPASS fast: UI package Vitest\nPASS fast: OpenAPI and TypeScript client drift\nPASS browser: JavaScript dependencies\nPASS browser: install Chromium and system dependencies\nPASS browser: build web app\nPASS browser: build release binary\nPASS browser: Playwright against release server\n\nscreenshots: /mnt/hdd/infraternal/artifacts/ui-review/\n\nfindings:\n1. [HIGH][Accessibility] The icon rail hides Dashboard/group labels without supplying accessible names; the 1024px accessibility snapshot exposes unnamed links/buttons (packages/web/src/lib/shell/Sidebar.svelte:77-97,217).\n2. [HIGH][Layout] Edit sidebar at 1024x768 and 768x1024 hides item/group actions while rename/create controls clip past the 68px rail (Sidebar.svelte:98-112,122-147,216-223); evidence: light-normal-1024x768-edit.png and light-normal-768x1024-edit.png.\n3. [HIGH][Accessibility] The custom mobile aria-modal has no focus trap; after 19 Tabs focus is BODY/outside and Escape does not close it (packages/web/src/lib/shell/AppShell.svelte:115,120-125).\n4. [HIGH][Accessibility/Security] Account-menu Sign out is a visible no-op: click leaves the URL/menu unchanged and emits no toast (packages/web/src/lib/shell/Sidebar.svelte:158-162).\n5. [HIGH][Accessibility] Popover opens a role=dialog panel without moving focus into it, so its Escape handler is unreachable when content is non-focusable (packages/ui/src/lib/Popover.svelte:22-29); the test only asserts open text (primitives.test.ts:62-64).\n6. [HIGH][Accessibility] Field makes the label target optional and never associates hint/error IDs or aria-invalid/aria-describedby with the child control (packages/ui/src/lib/Field.svelte:7-24).\n7. [MEDIUM][Layout] AppShell responsive hide rules lose to IconButton scoped display: hamburger and rail-toggle render at every width; rail-toggle is a no-op on mobile and squeezes/truncates the 320px breadcrumb (AppShell.svelte:95,103,150,158-162; screenshots light-normal-1440x900-dashboard.png and light-normal-320x640-dashboard.png).\n8. [MEDIUM][Accessibility] Menu button omits ArrowDown/ArrowUp opening behavior required by its role; focused Account + ArrowDown leaves the menu closed (packages/ui/src/lib/Menu.svelte:36-42).\n9. [MEDIUM][Accessibility] SPA navigation does not move focus to the new heading or close transient menu state; Profile navigation leaves focus on BODY with the Account menu still visible (AppShell.svelte:40-53, Sidebar.svelte:160-161).\n10. [MEDIUM][Color] Manual theme switching changes data-theme but Toaster remains theme=system; in a light OS context, the dark app produced a white toast (AppShell.svelte:71-76, Toaster.svelte:8; light-manual-dark-toast.png).\n11. [MEDIUM][UI/Performance] svelte-sonner default toast transition animates height and box-shadow in addition to transform/opacity (Toaster.svelte:8; computed normal-motion transition: transform 0.4s, opacity 0.4s, height 0.4s, box-shadow 0.2s), contrary to the UI motion contract.\n12. [MEDIUM][UI/Accessibility] Touch hover states are not gated and active scale also runs during keyboard Space activation (Sidebar.svelte:189, Menu.svelte:52, AppShell.svelte:147, Button.svelte:57, IconButton.svelte:55; keyboard computed transform matrix was 0.96).\n13. [MEDIUM][Accessibility] Tooltip puts aria-describedby on a non-focusable wrapper instead of the wrapped control, so the tooltip description is not reliably announced (packages/ui/src/lib/Tooltip.svelte:9-11).\n14. [MEDIUM][Reuse] Dashboard and PlaceholderPage duplicate page-intro/eyebrow/lede styling instead of extending a shared primitive (packages/web/src/routes/+page.svelte:67-82, packages/web/src/lib/PlaceholderPage.svelte:24-28).\n15. [MEDIUM][Typography] The Inter token is declared but no font face/import is shipped; on this Debian VM fc-match Inter resolves to WenQuanYi Zen Hei (packages/ui/src/tokens.css:19-20).
Author
Owner

Independent Playwright route matrix against target/release/infraternal: 14 routes x 5 viewports (1440x900, 1024x768, 768x1024, 390x844, 320x640) x 4 passes (light/dark, reduce/no-preference); result { routes: 14, viewports: 5, passes: 4, failures: [] }. Focused probes additionally recorded unnamed rail controls, 0 Move Hosts button at 1024/768 edit mode, drawer focus escape after 19 Tabs, Sign out no-op, white manual-dark toast, and 56,418 gzip bytes for the 10 initial JS responses (under the 120 KB budget; author claim 54,121 not reproduced).

Independent Playwright route matrix against target/release/infraternal: 14 routes x 5 viewports (1440x900, 1024x768, 768x1024, 390x844, 320x640) x 4 passes (light/dark, reduce/no-preference); result { routes: 14, viewports: 5, passes: 4, failures: [] }. Focused probes additionally recorded unnamed rail controls, 0 Move Hosts button at 1024/768 edit mode, drawer focus escape after 19 Tabs, Sign out no-op, white manual-dark toast, and 56,418 gzip bytes for the 10 initial JS responses (under the 120 KB budget; author claim 54,121 not reproduced).
Author
Owner

Orchestrator: review accepted (15 findings). Fix job ui-fix launched with all of them plus 7 visual findings from the orchestrator: duplicated status captions, a green dot claiming health on a zero count, unlabeled header chevrons, placeholder-looking empty-state icons, eyebrow labels on every section, marketing intro copy, and a dead "Add host" primary action.

Orchestrator: review accepted (15 findings). Fix job `ui-fix` launched with all of them plus 7 visual findings from the orchestrator: duplicated status captions, a green dot claiming health on a zero count, unlabeled header chevrons, placeholder-looking empty-state icons, eyebrow labels on every section, marketing intro copy, and a dead "Add host" primary action.
Author
Owner

Started UI foundation review fixes on branch ui-foundation at base fb63985ab8c53c0a320aee1c05af5711f66bdd0d.

Scope: fix every finding from the independent review plus the seven orchestrator visual findings, add the requested browser checks, verify with scripts/verify fast and scripts/verify browser, capture the required screenshots, and report route JS/font byte sizes.

Started UI foundation review fixes on branch `ui-foundation` at base `fb63985ab8c53c0a320aee1c05af5711f66bdd0d`. Scope: fix every finding from the independent review plus the seven orchestrator visual findings, add the requested browser checks, verify with `scripts/verify fast` and `scripts/verify browser`, capture the required screenshots, and report route JS/font byte sizes.
Author
Owner

Recon at fb63985 confirms the review repros in source and artifacts: rail CSS sets labels/edit actions to display:none; the mobile drawer only listens on its container and has no Tab loop; Popover never focuses its panel; Field only forwards an optional caller for; Tooltip describes its wrapper; Menu handles arrows only after opening; Sonner is theme="system" and ships height/box-shadow transitions; the dashboard duplicates status copy, shows a green zero Inbox state, keeps dead host actions, eyebrows, marketing copy and dash empty marks. The account menu also exposes a no-op Sign out before auth exists. Fixing these at the shared primitive/shell seams keeps behavior reusable and avoids route-specific patches.

Recon at `fb63985` confirms the review repros in source and artifacts: rail CSS sets labels/edit actions to `display:none`; the mobile drawer only listens on its container and has no Tab loop; Popover never focuses its panel; Field only forwards an optional caller `for`; Tooltip describes its wrapper; Menu handles arrows only after opening; Sonner is `theme="system"` and ships `height`/`box-shadow` transitions; the dashboard duplicates status copy, shows a green zero Inbox state, keeps dead host actions, eyebrows, marketing copy and dash empty marks. The account menu also exposes a no-op Sign out before auth exists. Fixing these at the shared primitive/shell seams keeps behavior reusable and avoids route-specific patches.
Author
Owner

ISSUE UPDATE kayg/infraternal#3
branch: ui-foundation
base: fb63985
head: 2007c16
fixed:

  • Sidebar rail accessible names → retained labels through aria-labels on dashboard, group, item, inbox, account and version controls.
  • Sidebar rail edit layout → expanded an icon rail to the full editor width while edit mode is active; verified at 1024×768 and 768×1024.
  • AppShell drawer focus trap/Escape → added inert background, global Tab/Shift+Tab trapping, Escape close and trigger focus restoration.
  • Sidebar sign out no-op → removed the unusable account menu and show an honest “Not signed in” account area until authentication exists.
  • Popover focus → focus enters the dialog on open and returns to the trigger on Escape/close.
  • Field associations → generate IDs and wire label, hint/error ids, aria-describedby and aria-invalid.
  • Responsive shell controls/breadcrumb → hide mobile-only desktop actions, expose the rail action with a visible label, and prevent narrow breadcrumb clipping.
  • Menu arrow keys → ArrowDown/ArrowUp open the menu at the first/last item; Home/End and Escape are handled in the menu.
  • SPA route focus → close transient UI and focus the new page h1 after route changes.
  • Toaster theme → observe the app data-theme and pass the resolved light/dark theme to Sonner.
  • Toaster motion → override svelte-sonner transitions to transform/opacity only and document the 1.2.1 default behavior.
  • Pointer/input motion → gate hover/press scaling by fine-pointer input and exclude focus-visible keyboard actions.
  • Tooltip association → attach aria-describedby to the focusable child rather than the wrapper.
  • Duplicated intro styles → add and reuse the shared PageIntro primitive in dashboard and placeholder pages.
  • Inter/monospace fonts → ship self-hosted Inter Variable and JetBrains Mono Variable WOFF2 with font-display: swap.
  • Repeated status text → retain each card label, number and one short factual caption; remove duplicate status detail indicators.
  • Inbox zero-state color → use neutral copy and no green health dot when the count is zero.
  • Header chevrons → replace unlabeled chevrons with the visible “Expand sidebar”/“Collapse sidebar” action and remove it from mobile.
  • Empty-state dash → remove the misleading grey dash icon; empty states use no icon.
  • Eyebrows → remove the uppercase section eyebrows from the operator dashboard and route intros.
  • Dashboard marketing copy → remove the “A quiet view…” line and keep the intro factual.
  • Dead Add host action → remove dashboard and fixture Add host actions until host creation exists.
    rules applied: emil-design-eng; better-ui; better-layout; better-typography; better-colors; better-accessibility; better-writing; better-interface.
    gates:
    PASS fast: JavaScript dependencies
    PASS fast: build web app
    PASS fast: cargo fmt --check
    PASS fast: cargo clippy
    PASS fast: cargo test
    PASS fast: svelte-check
    PASS fast: UI package svelte-check
    PASS fast: Vitest
    PASS fast: UI package Vitest
    PASS fast: OpenAPI and TypeScript client drift
    PASS browser: JavaScript dependencies
    PASS browser: install Chromium and system dependencies
    PASS browser: build web app
    PASS browser: build release binary
    PASS browser: Playwright against release server
    initial route JS gzip: 57309 bytes; fonts: 302728 bytes shipped WOFF2
    screenshots:
  • /mnt/hdd/infraternal/artifacts/ui-fix/light-1440x900.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/dark-1440x900.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/light-1024x768.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/dark-1024x768.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/light-390x844.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/dark-390x844.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/light-320x640.png
  • /mnt/hdd/infraternal/artifacts/ui-fix/dark-320x640.png
    open problems: none
ISSUE UPDATE kayg/infraternal#3 branch: ui-foundation base: fb63985 head: 2007c16 fixed: - Sidebar rail accessible names → retained labels through aria-labels on dashboard, group, item, inbox, account and version controls. - Sidebar rail edit layout → expanded an icon rail to the full editor width while edit mode is active; verified at 1024×768 and 768×1024. - AppShell drawer focus trap/Escape → added inert background, global Tab/Shift+Tab trapping, Escape close and trigger focus restoration. - Sidebar sign out no-op → removed the unusable account menu and show an honest “Not signed in” account area until authentication exists. - Popover focus → focus enters the dialog on open and returns to the trigger on Escape/close. - Field associations → generate IDs and wire label, hint/error ids, aria-describedby and aria-invalid. - Responsive shell controls/breadcrumb → hide mobile-only desktop actions, expose the rail action with a visible label, and prevent narrow breadcrumb clipping. - Menu arrow keys → ArrowDown/ArrowUp open the menu at the first/last item; Home/End and Escape are handled in the menu. - SPA route focus → close transient UI and focus the new page h1 after route changes. - Toaster theme → observe the app data-theme and pass the resolved light/dark theme to Sonner. - Toaster motion → override svelte-sonner transitions to transform/opacity only and document the 1.2.1 default behavior. - Pointer/input motion → gate hover/press scaling by fine-pointer input and exclude focus-visible keyboard actions. - Tooltip association → attach aria-describedby to the focusable child rather than the wrapper. - Duplicated intro styles → add and reuse the shared PageIntro primitive in dashboard and placeholder pages. - Inter/monospace fonts → ship self-hosted Inter Variable and JetBrains Mono Variable WOFF2 with font-display: swap. - Repeated status text → retain each card label, number and one short factual caption; remove duplicate status detail indicators. - Inbox zero-state color → use neutral copy and no green health dot when the count is zero. - Header chevrons → replace unlabeled chevrons with the visible “Expand sidebar”/“Collapse sidebar” action and remove it from mobile. - Empty-state dash → remove the misleading grey dash icon; empty states use no icon. - Eyebrows → remove the uppercase section eyebrows from the operator dashboard and route intros. - Dashboard marketing copy → remove the “A quiet view…” line and keep the intro factual. - Dead Add host action → remove dashboard and fixture Add host actions until host creation exists. rules applied: emil-design-eng; better-ui; better-layout; better-typography; better-colors; better-accessibility; better-writing; better-interface. gates: PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: Vitest PASS fast: UI package Vitest PASS fast: OpenAPI and TypeScript client drift PASS browser: JavaScript dependencies PASS browser: install Chromium and system dependencies PASS browser: build web app PASS browser: build release binary PASS browser: Playwright against release server initial route JS gzip: 57309 bytes; fonts: 302728 bytes shipped WOFF2 screenshots: - /mnt/hdd/infraternal/artifacts/ui-fix/light-1440x900.png - /mnt/hdd/infraternal/artifacts/ui-fix/dark-1440x900.png - /mnt/hdd/infraternal/artifacts/ui-fix/light-1024x768.png - /mnt/hdd/infraternal/artifacts/ui-fix/dark-1024x768.png - /mnt/hdd/infraternal/artifacts/ui-fix/light-390x844.png - /mnt/hdd/infraternal/artifacts/ui-fix/dark-390x844.png - /mnt/hdd/infraternal/artifacts/ui-fix/light-320x640.png - /mnt/hdd/infraternal/artifacts/ui-fix/dark-320x640.png open problems: none
Author
Owner

Fix job ui-fix finished at 2007c16: all 22 findings addressed, gates green, initial JS 57,309 B gzip, fonts 302,728 B WOFF2 (likely full charset; measured in verify). Verify job ui-verify running.

Fix job `ui-fix` finished at 2007c16: all 22 findings addressed, gates green, initial JS 57,309 B gzip, fonts 302,728 B WOFF2 (likely full charset; measured in verify). Verify job `ui-verify` running.
Author
Owner

Verification started: worktree /mnt/hdd/infraternal/.worktrees/ui-review, requested detached head 2007c16 (ui-foundation), fix range fb63985..2007c16. Verification-only job; no tracked-file edits or commits. Required UI skills and repo docs loaded; gates and Playwright evidence will be recorded here.

Verification started: worktree /mnt/hdd/infraternal/.worktrees/ui-review, requested detached head 2007c16 (ui-foundation), fix range fb63985..2007c16. Verification-only job; no tracked-file edits or commits. Required UI skills and repo docs loaded; gates and Playwright evidence will be recorded here.
Author
Owner

ISSUE UPDATE kayg/infraternal#3
verify of: ui-foundation @ 2007c16
verdict: merge

gates:

PASS fast: JavaScript dependencies
PASS fast: build web app
PASS fast: cargo fmt --check
PASS fast: cargo clippy
PASS fast: cargo test
PASS fast: svelte-check
PASS fast: UI package svelte-check
PASS fast: Vitest
PASS fast: UI package Vitest
PASS fast: OpenAPI and TypeScript client drift
PASS browser: JavaScript dependencies
PASS browser: install Chromium and system dependencies
PASS browser: build web app
PASS browser: build release binary
PASS browser: Playwright against release server

Targeted production-browser verification: 20 contexts (1440×900, 1024×768, 768×1024, 390×844, 320×640 × light/dark × reduced-motion on/off), 20 screenshots, 0 page errors, 0 console errors, no horizontal overflow or visible text overlap.

findings:

  • fixed — Sidebar rail controls retained accessible names; 17 visible rail controls were named in every desktop/tablet context.
  • fixed — Sidebar edit mode expanded the rail to 248px; clipping was [] at 1440px, 1024px and 768px.
  • fixed — Mobile drawer trapped Tab/Shift+Tab, closed on Escape and restored the trigger; verified at 390px and 320px in all theme/motion modes.
  • fixed — No-op Sign out was removed; the unauthenticated shell now exposes “Not signed in” with no Sign out control.
  • fixed — Popover moved focus into its dialog and restored focus after Escape; verified in the primitive fixture.
  • fixed — Field generated ids and associated hint/error text with aria-describedby/aria-invalid; browser and UI Vitest checks passed.
  • fixed — Mobile hid the rail toggle and the 320px long breadcrumb stayed within the viewport.
  • fixed — Menu ArrowUp/ArrowDown opened on the expected first/last item and cycled menu items.
  • fixed — SPA navigation focused the new h1 and drawer navigation closed before focusing the destination heading.
  • fixed — Sonner followed both system and manually toggled themes.
  • fixed — Sonner transitions were limited to transform/opacity; no height or box-shadow transitions were computed.
  • fixed — Hover and active motion were modality-gated; keyboard transforms were none and touch reported hover:false/fine:false.
  • fixed — Tooltip aria-describedby was wired to the focusable child; the UI primitive test passed.
  • fixed — Dashboard and PlaceholderPage use the shared PageIntro primitive.
  • fixed — Inter and JetBrains Mono WOFF2 assets were bundled and requested; no system-font fallback was observed in the first-load network.
  • fixed — Dashboard status cards each have one status caption and no duplicate status caption.
  • fixed — Zero-count dashboard cards have no green StatusDot.
  • fixed — Header/sidebar chevron controls have accessible names.
  • fixed — Empty states contain no dash placeholder icon.
  • fixed — Repeated eyebrow labels were removed.
  • fixed — Marketing intro copy was removed from the operator dashboard.
  • fixed — Dead “Add host” primary actions were removed.

fonts on first load: 88,660 bytes, inter-latin-wght-normal.Dx4kXJAl.woff2 48,256 bytes + jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2 40,404 bytes. This is Latin-only normal-weight WOFF2, not the full character set. The installed Fontsource 5.3.0 normal-weight shard totals are Inter 218,512 + JetBrains Mono 86,244 = 304,756 bytes; Latin + Latin Extended would be Inter 133,324 + JetBrains Mono 55,600 = 188,924 bytes. The 302,728-byte fix estimate is not the first-load network figure and is approximately the all-normal-shard total with the 2,028-byte JetBrains Mono Cyrillic-ext shard omitted.

metrics: initial route JS gzip 56,704 bytes (within the 120 KiB budget).
artifacts: /mnt/hdd/infraternal/artifacts/ui-verify/evidence.json and the 20 *.png screenshots in that directory.
blocks-merge: none
later: none

ISSUE UPDATE kayg/infraternal#3 verify of: ui-foundation @ 2007c16 verdict: merge gates: ```text PASS fast: JavaScript dependencies PASS fast: build web app PASS fast: cargo fmt --check PASS fast: cargo clippy PASS fast: cargo test PASS fast: svelte-check PASS fast: UI package svelte-check PASS fast: Vitest PASS fast: UI package Vitest PASS fast: OpenAPI and TypeScript client drift PASS browser: JavaScript dependencies PASS browser: install Chromium and system dependencies PASS browser: build web app PASS browser: build release binary PASS browser: Playwright against release server ``` Targeted production-browser verification: 20 contexts (1440×900, 1024×768, 768×1024, 390×844, 320×640 × light/dark × reduced-motion on/off), 20 screenshots, 0 page errors, 0 console errors, no horizontal overflow or visible text overlap. findings: - fixed — Sidebar rail controls retained accessible names; 17 visible rail controls were named in every desktop/tablet context. - fixed — Sidebar edit mode expanded the rail to 248px; clipping was [] at 1440px, 1024px and 768px. - fixed — Mobile drawer trapped Tab/Shift+Tab, closed on Escape and restored the trigger; verified at 390px and 320px in all theme/motion modes. - fixed — No-op Sign out was removed; the unauthenticated shell now exposes “Not signed in” with no Sign out control. - fixed — Popover moved focus into its dialog and restored focus after Escape; verified in the primitive fixture. - fixed — Field generated ids and associated hint/error text with aria-describedby/aria-invalid; browser and UI Vitest checks passed. - fixed — Mobile hid the rail toggle and the 320px long breadcrumb stayed within the viewport. - fixed — Menu ArrowUp/ArrowDown opened on the expected first/last item and cycled menu items. - fixed — SPA navigation focused the new h1 and drawer navigation closed before focusing the destination heading. - fixed — Sonner followed both system and manually toggled themes. - fixed — Sonner transitions were limited to transform/opacity; no height or box-shadow transitions were computed. - fixed — Hover and active motion were modality-gated; keyboard transforms were none and touch reported hover:false/fine:false. - fixed — Tooltip aria-describedby was wired to the focusable child; the UI primitive test passed. - fixed — Dashboard and PlaceholderPage use the shared PageIntro primitive. - fixed — Inter and JetBrains Mono WOFF2 assets were bundled and requested; no system-font fallback was observed in the first-load network. - fixed — Dashboard status cards each have one status caption and no duplicate status caption. - fixed — Zero-count dashboard cards have no green StatusDot. - fixed — Header/sidebar chevron controls have accessible names. - fixed — Empty states contain no dash placeholder icon. - fixed — Repeated eyebrow labels were removed. - fixed — Marketing intro copy was removed from the operator dashboard. - fixed — Dead “Add host” primary actions were removed. fonts on first load: 88,660 bytes, `inter-latin-wght-normal.Dx4kXJAl.woff2` 48,256 bytes + `jetbrains-mono-latin-wght-normal.B9CIFXIH.woff2` 40,404 bytes. This is Latin-only normal-weight WOFF2, not the full character set. The installed Fontsource 5.3.0 normal-weight shard totals are Inter 218,512 + JetBrains Mono 86,244 = 304,756 bytes; Latin + Latin Extended would be Inter 133,324 + JetBrains Mono 55,600 = 188,924 bytes. The 302,728-byte fix estimate is not the first-load network figure and is approximately the all-normal-shard total with the 2,028-byte JetBrains Mono Cyrillic-ext shard omitted. metrics: initial route JS gzip 56,704 bytes (within the 120 KiB budget). artifacts: `/mnt/hdd/infraternal/artifacts/ui-verify/evidence.json` and the 20 `*.png` screenshots in that directory. blocks-merge: none later: none
Author
Owner

Verify job ui-verify (gpt-5.6-luna/max): merge. All 22 findings verified fixed; first-load fonts 88,660 B (Latin shards only). Merged to dev. Step 7 done.

Verify job `ui-verify` (gpt-5.6-luna/max): **merge**. All 22 findings verified fixed; first-load fonts 88,660 B (Latin shards only). Merged to dev. Step 7 done.
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/infraternal-v0#3
No description provided.