Skip to content

Full UI/UX polish: design tokens, responsive drawer, offline hardening, shortcuts, a11y#4

Merged
Neverdecel merged 1 commit into
mainfrom
claude/ui-ux-polish
Jul 10, 2026
Merged

Full UI/UX polish: design tokens, responsive drawer, offline hardening, shortcuts, a11y#4
Neverdecel merged 1 commit into
mainfrom
claude/ui-ux-polish

Conversation

@Neverdecel

Copy link
Copy Markdown
Owner

Summary

Complete UI/UX pass over the web frontend, guided by Nielsen's 10 usability heuristics and Shneiderman's Eight Golden Rules. Dark-only, zero new runtime dependencies. One commit, 26 files, +2,288 / -481.

Design system

  • app.css restructured into semantic tokens (--surface-*, --status-*, spacing/type/radius/motion scales, focus rings, z-layers); a future light theme is a single [data-theme] override block
  • Global :focus-visible rings, prefers-reduced-motion support, .sr-only utility
  • New web/src/components/ui/ primitives: Icon (inline-SVG set, replaces all emoji glyphs), Toasts (stacking, severities, sticky errors, undo actions - removes showToast prop-drilling), ConfirmDialog (native <dialog>, promise API, danger mode focuses Cancel), ShortcutsHelp, DiffBlock

Responsive shell

  • Sidebar collapses to an overlay drawer at <= 900px: scrim, inert main, focus management, approval-count badge on the hamburger
  • Reconnect banner with a working "Retry now"

Per-surface polish

  • Sidebar: valid button semantics (fixes nested-interactive rows), per-row busy spinners, delete via styled confirm, archive with Undo toast, chips for engine state / BYPASS / worktree / cross-session "needs approval", live-ticking timestamps
  • StatusBar: worktree chip, visible starting status, bypassPermissions now requires confirmation
  • ChatView: empty-state hint, amber "Stop turn" (red reserved for destructive), jump-to-latest pill
  • ApprovalCard: Edit/Write render as diffs, Bash as its command, raw JSON collapsed behind a disclosure
  • Launcher: closable dir browser (Close + Escape), surfaced validation errors; LoginGate: explains why you were signed out

Offline / error hardening

  • ws.ts send() returns success; drafts are never cleared on failed sends; Send disabled while offline; approvals cannot be bricked by a dropped socket; guarded JSON parsing
  • Optimistic user bubbles (pendingSends, kept outside the event log so replay dedupe is untouched) with "sending…"/"queued" captions; interrupt-dropped queue offers "Restore to composer"

Keyboard + a11y

  • Global shortcuts: n, /, i, x, Ctrl+B, Alt+↑/↓, ? help dialog, contextual Escape
  • aria-label on every icon-only button, live regions for connection/status changes, 28px touch targets on coarse pointers

Test plan

  • All CI gates green locally: format:check, lint, typecheck, build, server tests (25 passed)
  • Verified end-to-end with a local headless Chromium against an isolated echo-engine stack: login (incl. rejected token), launch with dir browser + worktree, send / queue / interrupt / restore, approval allow/deny, rename / fork / archive-undo / delete-confirm, bypass-mode confirm, server-kill offline drill (banner, disabled send, preserved draft, reconnect + replay), all shortcuts, and 1280 / 768 / 375px viewports

Design system (dependency-free):
- Restructure app.css into semantic tokens (--surface-*, --status-*,
  spacing/type/radius/motion scales, focus-ring vars, z-layers); a light
  theme is now a [data-theme] override block away
- Global :focus-visible rings, prefers-reduced-motion support, .sr-only
- New ui/ primitives: Icon (inline-SVG set, replaces emoji), Toasts
  (stacking, severities, sticky errors, undo actions), ConfirmDialog
  (native <dialog>, promise API, danger mode focuses Cancel),
  ShortcutsHelp; friendlyWsError() maps protocol codes to sentences

Responsive shell:
- Sidebar collapses to an overlay drawer at <= 900px (scrim, inert main,
  focus management, approval-count badge on the hamburger)
- Reconnect banner with Retry (reconnectNow with retry-timer tracking)

Per-surface polish:
- Sidebar: valid button semantics (no nested interactives), per-row busy
  spinners, delete via confirm dialog, archive with Undo toast, engine/
  BYPASS/worktree/needs-approval chips, live-ticking relative time
- StatusBar: worktree chip, visible 'starting' status, bypassPermissions
  now requires confirmation
- ChatView: empty-state hint, amber "Stop turn" (red reserved for
  destructive), jump-to-latest pill
- ApprovalCard: Edit/Write render as diffs, Bash as its command, raw
  JSON collapsed behind a disclosure; Launcher: closable dir browser,
  surfaced validation errors; LoginGate: explains why you were signed out

Offline/error hardening:
- ws send() returns success; drafts never cleared on failed sends; Send
  disabled while offline; approvals cannot be bricked by a dropped socket
- Optimistic user bubbles (pendingSends, outside the event log so replay
  dedupe is untouched) with sending/queued captions; interrupt-dropped
  queue offers "Restore to composer"; guarded ws JSON parsing

Keyboard + a11y:
- Global shortcuts (n, /, i, x, Ctrl+B, Alt+arrows, ? help, Esc chain)
- aria-labels on all icon-only buttons, live regions for status changes,
  28px touch targets on coarse pointers
@Neverdecel Neverdecel merged commit 8d5156f into main Jul 10, 2026
1 check 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.

1 participant