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 221ae94f4f
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-go-pg (push) Successful in 2m44s
CI/CD / test-sqlite (push) Successful in 2m47s
CI/CD / build-and-deploy (push) Successful in 1m46s
Feat v0.6.12 css isolation (#47)
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
2026-04-01 11:58:39 +00:00

12 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

Fill the gaps between mobile and desktop.

Step Description
Tablet breakpoint Add @media (min-width: 769px) and (max-width: 1024px) rules. Secondary workspace pane: 360px (from 480px). Admin nav collapses to icon-only at this breakpoint. Settings nav: 180px.
Spacing scale Define spacing tokens in variables.css: --space-1: 4px through --space-8: 64px (4px base, doubling). Migrate hardcoded padding/margin values to tokens. Priority: surfaces that users see on every session (sidebar, topbar, admin content areas).
Font-size scale Define --text-xs: 0.75rem through --text-xl: 1.25rem (5 stops). Migrate all font-size declarations. Remove em-based sizes (user-picker) and bare px sizes.
Secondary pane responsive workspace-secondary.open width uses clamp(320px, 35vw, 560px) instead of fixed 480px.

v0.6.14 — Visual Polish

Systematic cleanup of stale values and rendering artifacts.

Step Description
Purge stale fallback colors Remove all var(--foo, #hexvalue) fallbacks that reference old gold theme colors (#b38a4e and variants). If a CSS variable is undefined at this point, that's a bug — don't mask it with a wrong fallback.
Self-host fonts Bundle DM Sans and JetBrains Mono woff2 files in src/fonts/. Replace Google Fonts @import with local @font-face declarations. Zero external font dependencies.
Light theme audit Walk every surface in light mode. Fix any remaining hardcoded dark-mode colors, contrast issues, or invisible borders. Document any surface-specific light-mode overrides.
Consistent border-radius Surfaces currently mix 6px, 8px, 10px, var(--radius), var(--radius-lg). Audit and reduce to 3 values: --radius-sm: 4px, --radius: 8px, --radius-lg: 12px.

v0.6.15 — Usability Survey Gate

Make the UI machine-auditable so Claude Code can run an automated survey.

Step Description
UI inventory manifest scripts/generate-ui-inventory.sh — walks kernel CSS + package CSS, extracts every rendered class, groups by surface, outputs ui-inventory.json. Fields: {surface, component, classes, file, line, responsive_breakpoints, spacing_tokens_used, font_size_tokens_used}.
Contrast checker Script that parses variables.css light/dark token pairs and checks WCAG AA contrast ratios for all text-* on bg-* combinations. Outputs pass/fail report.
Component coverage matrix Markdown table: each kernel primitive (button, input, dropdown, dialog, toast, menu, tabs, avatar, spinner, tooltip, drawer, banner) × each surface that uses it. Identifies surfaces still using deprecated old-style components.
Touch target audit Script that finds all <button>, [role=button], clickable elements across templates and JS, checks for min-width/min-height ≥ 44px on mobile breakpoint.
Claude Code survey prompt docs/USABILITY-SURVEY.md — structured prompt template that Claude Code can execute against the codebase. Sections: viewport correctness, banner integration, responsive behavior, styling consistency, accessibility basics (contrast, touch targets, focus indicators), component uniformity. Each section has pass/fail criteria and file paths to inspect.
Survey dry-run Run the survey. Fix anything it catches. Tag v0.6.15 only after clean survey.

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    ← Spacing tokens need stable class names to attach to
  ↓
v0.6.14 Visual Polish           ← Final visual pass after structure is locked
  ↓
v0.6.15 Usability Survey Gate   ← Machine-audit the finished product

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


What "Usability Survey by Code" Means

The v0.6.15 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.