Skip to content

Console UI audit: accessibility, guidelines, copy and load performance - #50

Merged
ysinghc merged 3 commits into
mainfrom
claude/production-frontend-dashboards-aedb5f
Nov 9, 2026
Merged

ysinghc merged 3 commits into
mainfrom
claude/production-frontend-dashboards-aedb5f

Conversation

@ysinghc

@ysinghc ysinghc commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Audits every page of both consoles (self-hosted gateway and Meridian Cloud) against WCAG 2.2 AA (axe-core), the Vercel Web Interface Guidelines, Anthropic's frontend-design / accessibility-review / design-critique guidance and Cloudflare's web-perf checklist, and fixes what they found.

What changed

Broken / failing

  • Phones: the node-detail tab bar and the routing isolation table made the whole page scroll sideways (WCAG 1.4.10). Tab lists now scroll on their own; grid panels get min-w-0.
  • Connect-gateway dialog went blank while closing (content was unmounted before the exit animation).
  • Contrast below 4.5:1: toast descriptions (2.15:1), critical status text, inactive tabs, sidebar captions, destructive buttons.
  • 18 filter selects had no accessible name; empty table headers; two nested main landmarks on every page; 404 page had no h1; scrollable code blocks and wide tables weren't keyboard-reachable.

Load performance

  • Builds now write Brotli and gzip copies of JS/CSS/SVG; the gateway and control plane serve them with Content-Encoding + Vary: Accept-Encoding (meridian/api/static_files.py). Main bundle 1.58 MB → 420 KB over the wire.
  • The control plane embeds cloud boot info in the page (<script type="application/json">, CSP-safe and </script>-escaped), so neither console waits on /api/cloud/info before first render.
  • Throttled phone profile: gateway sign-in FCP 7.6 s → 2.4 s, LCP 8.0 s → 2.7 s; CLS ≤ 0.07.

Guidelines

  • Filters and tabs are kept in the URL (useUrlState), so reloads and shared links keep them.
  • Inputs: name, autoComplete, inputMode, spellCheck, one-time-code; autofocus only on pointer-fine devices.
  • Numbers and dates use the viewer's locale; theme-color follows the theme; reduced motion honoured; no transition: all; overscroll containment in dialogs and menus.
  • Copy: sentence case instead of all-caps labels, links that say where they go (no trailing arrows), specific placeholders.

Tooling

  • npm run audit:ui -- --mode gateway|cloud: axe, 390 px reflow, console errors and visible-focus checks on every route in light, dark and mobile; exits 1 on any problem. Documented under "UI quality bar" in docs/CONSOLE.md.

Checklist

  • Tests: pytest -q 671 passed (new tests/test_static_files.py, boot-info escaping test); vitest 45 passed (readBootInfo)
  • ruff check ., mypy meridian, mypy meridian_control, tsc, oxlint, npm run build clean
  • Docs: docs/CONSOLE.md, CHANGELOG.md

Validation

  • npm run audit:ui: gateway 60 page views, cloud 46 page views, 0 axe violations, no horizontal overflow, no console errors, no focus stop without an indicator.
  • Gateway end-to-end script 22/22 and cloud end-to-end flow (email-code sign-in, workspace, connect gateway, sign-out) pass against scripts/console_demo.py [--cloud].

Generated by Claude Code

- npm run build writes .br/.gz next to every text asset (Node zlib, no
  new dependency); the gateway and meridian-control serve the variant the
  browser accepts with Content-Encoding and Vary. Console JS goes from
  1.58 MB to 420 KB on the wire without compressing API or SSE responses.
- meridian-control embeds the console's boot info in the page as a JSON
  data block (CSP-safe, '<' escaped), so the console renders without a
  /api/cloud/info round trip; self-hosted gateways no longer get a 404
  probe on every load (dev server still probes).
- Throttled mobile profile (4x CPU, 150 ms RTT, 1.6 Mbps): first paint
  7.6 s -> 2.4 s, LCP 8.0 s -> 2.7 s, CLS unchanged (<= 0.07).
- Tests: encoding negotiation (br > gzip > identity, q=0), boot block
  parsing, and that a hostile config value cannot break out of the block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177yERMgobFkKXuZUcZmpwZ
Audited every page of the gateway and Cloud consoles in light, dark and
mobile views against WCAG 2.2 AA (axe-core), the Vercel Web Interface
Guidelines and Anthropic's frontend-design guidance. Both consoles now
report zero violations (60 + 46 page views), no horizontal scroll at
390 px, no console errors and a visible focus ring on every Tab stop.

Accessibility
- One main landmark per page (SidebarInset is a div); sidebar is an
  aside with a named nav; sign-in, onboarding, boot and error screens
  have main; 404 has an h1; the sign-in tagline is no longer a stray h2
- Accessible names for 18 filter selects, empty Actions headers and the
  per-member role select; Playground snippet tabs wired to panels;
  command palette title moved inside its dialog
- Contrast >= 4.5:1: inactive tabs, sidebar captions, destructive text,
  toast descriptions, dark-mode critical text (--status-critical-ink)
- Focus rings on tab panels, charts and clickable rows; scrolling tables
  and code blocks become keyboard-focusable

Layout, forms, behaviour
- Tab bars scroll instead of widening the page; panels and grid items
  shrink (min-w-0): node detail and routing no longer overflow on phones
- Inputs: name, autocomplete (email, organization, one-time-code, off),
  inputmode, spellCheck off for identifiers; autoFocus desktop-only
- Filters and tabs in the URL (useUrlState): keys, nodes, fleet audit,
  policies, metrics, node detail
- Viewer's locale for numbers and dates; theme-color follows the theme;
  global prefers-reduced-motion; no transition: all; touch-action and
  overscroll-behavior; connect-gateway dialog no longer empties while
  closing

Copy (frontend-design)
- Specific link labels (Routing details, All nodes, All errors) without
  appended arrows; sentence-case eyebrows and scope labels instead of
  all caps; plain titles instead of dot-joined ones; decorative dots
  removed from the sign-in panel

Repeatable audit
- npm run audit:ui (axe-core + reflow + console + focus checks against
  the demo stack); docs/CONSOLE.md 'UI quality bar'; CHANGELOG

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177yERMgobFkKXuZUcZmpwZ
Copilot AI balanced review requested due to automatic review settings November 9, 2026 12:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

The meridian-control image is published only for tagged releases, so
`docker compose pull` never picked up new code on a main checkout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177yERMgobFkKXuZUcZmpwZ
@ysinghc
ysinghc merged commit 1bc1a21 into main Nov 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants