This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/ROADMAP-UI.md
Jeffrey Smith ff19a1b4d3
All checks were successful
CI/CD / detect-changes (push) Successful in 3s
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-sqlite (push) Successful in 2m49s
CI/CD / test-go-pg (push) Successful in 2m51s
CI/CD / build-and-deploy (push) Successful in 49s
Feat v0.6.16 usability survey gate (#51)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
2026-04-01 14:52:14 +00:00

10 KiB
Raw Blame History

Armature — v0.6.x UI Hardening Roadmap

Goal: Fix all viewport scaling, banner integration, and styling inconsistencies so Claude Code can run a meaningful automated usability survey against a stable, uniform UI.


Problem Inventory

P1 — Viewport & Scaling (blocks everything)

# Issue Where Impact
1 Dual layout systemsbase.html template has its own banner→surface→footer column; app-shell.js Preact shell has a separate sw-shellsw-shell__bodysw-shell__surface column. They never coordinate. server/pages/templates/base.htmlsrc/js/sw/shell/app-shell.js Every surface inherits an ambiguous viewport ancestor.
2 Transform-based scaling is brokentransform: scale() on #surfaceInner doesn't reflow layout. Breaks getBoundingClientRect (menu.js already carries a scale-correction hack at line 20), scroll containment, pointer events, and the inverse-width/height hack (100/s%) doesn't account for banners consuming viewport space. base.html:56-67, appearance.js:41-53, menu.js:20-33 Menus, tooltips, dropdowns all mis-positioned at any non-100% scale. Click targets wrong.
3 Banner height desyncbase.html hardcodes --banner-h: 28px and renders banners in-flow. app-shell.js ShellBanner measures offsetHeight into --banner-top-height / --banner-bottom-height and uses position: fixed + body padding. Two independent banner systems. base.html:31,72-75,103-107app-shell.js:25-42, sw-shell.css:22-37,63-69 With banners enabled, content overflows by the banner height or gets double-inset depending on which code path is active.
4 100vh on mobile.sw-shell, .chat-app, .chat-loading, .login-shell use 100vh which doesn't subtract mobile browser chrome (address bar, toolbar). sw-shell.css:9, chat/css/main.css:15,25, sw-login.css:7 Content overflows on iOS Safari, Android Chrome.
5 Chat uses 100vh not 100%.chat-app { height: 100vh } ignores parent container (which already excludes banners/footer). Notes correctly uses height: 100%. Every extension surface that copies chat's pattern will inherit the bug. packages/chat/css/main.css:15 Chat surface overflows behind banners.

P2 — CSS Architecture

# Issue Where Impact
6 Class name collisions.settings-section defined in both modals.css:41-43 and surfaces.css:75-83 with different padding, margin, and border-bottom rules. .sw-dropdown in primitives.css:443 (styled <select>) vs sw-primitives.css:262 (custom dropdown component). .sw-tabs in primitives.css:459 vs sw-primitives.css:234. Kernel CSS Styles randomly win depending on load order. Bug reports differ by surface.
7 Old/new primitive duplication — Two button systems (.btn-primary/.btn-small in primitives.css vs .sw-btn--primary/.sw-btn--sm in sw-primitives.css). Two toast systems (.toast vs .sw-toast). Two dropdown, two tabs implementations. primitives.csssw-primitives.css No single source of truth for any component. Extension authors can't know which to use.
8 Extension CSS bleeds globally — Extension main.css loaded via <link> at document level, no scoping. Any class name can override kernel or sibling extension styles. base.html:26-28, extension-surface.css Package CSS fights with kernel. Two packages with .sidebar both lose.
9 No intermediate breakpoint — Only 768px mobile breakpoint. No tablet (7681024px). Secondary workspace pane hardcoded 480px. Admin nav hardcoded 200px. layout.css:263, surfaces.css:305 Cramped layout on iPad/small laptops.

P3 — Visual Consistency

# Issue Where Impact
10 Mixed unit systemspx, rem, em used interchangeably with no rationale. Some font-sizes in px (primitives), others in rem (sw-primitives), others in em (user-picker). All CSS files Zoom/scale behaves differently per element.
11 Google Fonts CDN dependency@import url(...) in variables.css:5 blocks rendering if CDN is slow; breaks entirely on air-gapped deployments. variables.css:5 FOUT or blank page on slow networks. No offline support.
12 No spacing scale — Padding/margins are ad-hoc values (10px, 12px, 14px, 16px, 20px, 24px, 28px…). No design-token spacing scale. All CSS Inconsistent visual rhythm across surfaces.
13 Hardcoded fallback colors in component CSSsw-shell.css, sw-primitives.css have inline fallbacks like var(--accent, #b38a4e) — a gold color from a previous theme that doesn't match the current blue #6c9fff. sw-shell.css, sw-primitives.css Wrong colors flash briefly if variables load late.

Roadmap

v0.6.9 — Session Lifetime Config

Shipped. Admin-configurable TTLs, "keep me logged in" checkbox, idle timeout, config-driven generateTokens(), 7 new tests. See CHANGELOG.md for details.

v0.6.10 — Viewport Foundation

Shipped. Single layout model: body → shell → surface. CSS zoom replaces transform: scale(). 100dvh fallbacks everywhere. Extension surfaces use 100% instead of 100vh. Dead shell layout code deprecated. See CHANGELOG.md.

v0.6.11 — CSS Deduplication

Shipped. Old primitive system retired. One class per concept. See CHANGELOG.md.

Step Description
Audit collision inventory Script that finds all duplicate class selectors across kernel CSS files. Produce a machine-readable collision report (JSON).
Migrate .settings-section Remove modals.css:41-43 definition. The surfaces.css definition is authoritative. Modals that used the old styles get explicit overrides scoped to .modal .settings-section.
Retire primitives.css old components .btn-primary, .btn-small, .btn-danger, .btn-full → migrate all usages to .sw-btn--*. .toast-container / .toast → migrate to .sw-toast-container / .sw-toast. Old .popup-menu → migrate to .sw-menu. Old .sw-dropdown (styled select in primitives.css) → rename to .sw-native-select or delete if unused. Old .sw-tabs / .sw-tab-btn in primitives.css → delete (sw-primitives.css version is authoritative).
Mark deprecated classes Any remaining old classes get a /* DEPRECATED v0.6.11 — use .sw-btn--* */ comment and a 1-version grace period for package authors.
Package CSS audit Scan all packages/*/css/main.css for references to deprecated kernel classes. Fix in-tree packages.

v0.6.12 — Extension CSS Isolation

Shipped. Prefix enforcement via linter. All 12 in-tree packages migrated. See CHANGELOG.md.

Step Description
Scoping strategy Prefix enforcement (option B). @scope support still patchy; prefix works everywhere, trivially lintable.
Linter scripts/lint-package-css.sh — validates first class selector in every rule starts with .ext-{slug}. Exempts :root, @keyframes, @font-face, @media, .sw-* kernel classes, .cm-* CodeMirror classes.
Kernel CSS contract docs/EXTENSION-CSS.md — stable public classes (.sw-btn--*, .sw-input, .sw-field, .sw-dialog, .sw-toast, .sw-menu, .sw-tabs, etc.) and all CSS variables. Everything else internal.
Migrate in-tree packages data-ext="{{.Surface}}" on extension mount. All 12 packages prefixed to .ext-{slug}-*. CSS + JS updated in lockstep.

v0.6.13 — Responsive & Spacing

Shipped. Spacing token scale (--sp-1 through --sp-12, 4px grid) in variables.css. Tablet breakpoint (max-width: 1024px) in layout, surfaces, login. All kernel CSS and 12 in-tree packages migrated to spacing tokens. EXTENSION-CSS.md updated with spacing table and breakpoint guide. Font-size scale deferred to v0.6.14. See CHANGELOG.md.

v0.6.14 — Visual Polish

Shipped. Stale fallback colors purged (~65 instances), fonts self-hosted (DM Sans + JetBrains Mono woff2), border-radius standardized to three tokens (--radius-sm, --radius, --radius-lg). Also fixed v0.6.13 spacing regressions (half-step tokens), theme settings default, surface overflow, and user menu zoom drift. See CHANGELOG.md.

v0.6.15 — User Display Audit

Shipped. GET /api/v1/users/resolve?ids=... batch endpoint, sw.users SDK module with resolve(), resolveMany(), displayName() + 60s cache. Chat participants resolved from users table instead of snapshot. All admin surfaces show display_name || username || 'Unknown'. Chat-core snapshot column deprecated. 5 new handler tests. See CHANGELOG.md.

v0.6.16 — Usability Survey Gate

Shipped. Four audit scripts, structured survey prompt, contrast/touch-target fixes, Docker docs corrected. All 48 contrast pairings pass, all close buttons have 44px mobile targets, focus-visible on all key primitives. See CHANGELOG.md.


Sequencing Rationale

v0.6.9  Session Lifetime Config ✅ SHIPPED
  ↓
v0.6.10 Viewport Foundation     ✅ SHIPPED
  ↓
v0.6.11 CSS Deduplication       ✅ SHIPPED
  ↓
v0.6.12 Extension CSS Isolation ✅ SHIPPED
  ↓
v0.6.13 Responsive & Spacing    ✅ SHIPPED
  ↓
v0.6.14 Visual Polish           ✅ SHIPPED
  ↓
v0.6.15 User Display Audit     ✅ SHIPPED
  ↓
v0.6.16 Usability Survey Gate  ✅ SHIPPED

Each version is independently shippable and testable. No version depends on anything after it.


What "Usability Survey by Code" Means

The v0.6.16 deliverables give Claude Code (or any automated tool) three things:

  1. A structured inventory (ui-inventory.json) of every component, on every surface, with its CSS file and line number.

  2. Automated checks (contrast, touch targets, token usage) that produce machine-readable pass/fail reports.

  3. A survey prompt (USABILITY-SURVEY.md) with explicit criteria and file paths, so Claude Code can cat the relevant files, run the scripts, and produce a scored report without human guidance.

The survey is not a substitute for real user testing — it's a structural quality gate that catches the class of bugs (overflow, contrast, misalignment, inconsistent styling) that have historically slipped through.