6.6 KiB
SDD Proposal: Web UI Spacing, Typography & Visual Rhythm Rework
Status
Phase: proposal
Date: 2026-06-16
Owner: el Gentleman
Based on: Scout audit ui-audit-spacing-typography.md
User Story
As a Headquarter user, I want the web UI to feel consistent, readable, and polished across desktop and mobile, so that I can navigate and manage workspaces, projects, and sessions without fighting cramped layouts, broken mobile views, or inconsistent spacing.
Problem Statement
A comprehensive audit of apps/web/src found systemic spacing, typography, margin, and visual-hierarchy issues:
- Missing primitive styles: dozens of widely-used class names (
.btn,.form-error,.alert,.badge,.mobile-detail-*, etc.) are referenced in TSX but have no CSS rules, causing broken or unstyled UI on multiple pages. - Completely unstyled mobile detail view:
mobile-detail-view.tsxships layout classes that do not exist in any stylesheet. - Mobile layout collisions: the bottom nav, start-tool FAB, and mobile edit sheets can overlap and do not account for safe-area insets.
- Inconsistent design tokens: the token scale lacks border-radius, line-height, shadow, touch-target, and nav-height primitives. Mixed
px/rem/emvalues and inlinestyle={{...}}blocks bypass the token system. - Duplicated systems: two modal/dialog implementations, duplicated
.form-field/.form-grouppatterns, duplicated status-badge/chip styles, and overlapping breakpoints (767px,768px,860px). - Heavy inline-style usage: editors and sidebars embed layout CSS directly in JSX, making responsive overrides and theming impossible.
This is not a single bug; it is a design-system hygiene issue that affects nearly every page.
Goals
- Establish a complete, single-source-of-truth token scale for spacing, typography, radius, shadow, line-height, touch targets, and layout heights.
- Add every missing primitive component style so that referenced classes actually render correctly.
- Fix mobile layout collisions by deriving FAB/bottom-sheet offsets from a shared nav-height token.
- Replace ad-hoc
px/remvalues and inline styles with token-based utility classes where feasible. - Consolidate duplicated patterns: one modal/dialog system, one form-field pattern, one status-badge family, one card family.
- Standardize breakpoints to the existing token scale (
--bp-sm,--bp-md,--bp-lg,--bp-xl). - Leave the UI visually improved without changing behavior or user-facing features.
Non-Goals
- No new user-facing features or workflows.
- No changes to backend APIs, database schema, or authentication.
- No redesign of the information architecture or navigation structure.
- No replacement of Tailwind or CSS-modules; we stay in the existing global-CSS architecture.
- No runtime theme-engine rewrite; light/dark tokens remain as-is.
High-Level Approach
Split the work into three reviewable passes to stay under the 400-line review budget:
Pass 1: Foundations (P0)
- Expand
tokens.csswith missing primitives. - Add missing primitive classes to
global.css/utilities.css(buttons, alerts, errors, badges, form inputs, loading states, checkbox labels, hints, mobile detail view, etc.). - Introduce
--mobile-nav-heightand fix FAB/bottom-sheet/shell-content collisions. - Fix the most critical inline font-size violations (
0.7rem→ tokens). - Add focused
:focusvisibility to interactive controls.
Pass 2: Component Cleanup (P1)
- Refactor the highest-volume inline-style offenders into utility classes:
manifest-editor.tsxConfigProfileEditorPanel.tsxToolTypeEditorPanel.tsxToolTypeListSidebar.tsxConfigProfileListSidebar.tsxgit-mount-editor.tsx
- Replace hardcoded
280pxsidebars with--sidebar-widthtoken. - Unify
.form-field/.form-groupand migrate callers. - Consolidate status badges/chips into a single
.status-badgefamily.
Pass 3: Consolidation & Polish (P2)
- Deprecate
.modal-*in favor of.dialog-*and migrate callers. - Consolidate card patterns across page CSS files into
global.cssmodifiers. - Standardize breakpoints to
--bp-*tokens and remove the860pxone-off. - Add token documentation and a lightweight review checklist.
Open Questions
- Which pass should include the mobile detail view styles?
- Recommendation: Pass 1, because it is currently broken.
- Should we keep the existing
.utilities.cssnaming convention or introduce BEM-style modifiers (.card--elevated,.status-badge--error)?- Recommendation: introduce BEM-style modifiers only for the new consolidated families; keep existing utilities untouched to minimize churn.
- Is the terminal page's hardcoded dark palette acceptable long-term, or should it become theme-aware?
- Recommendation: keep terminal colors hardcoded for now; only convert spacing to tokens.
- Should we add a lint rule to block new inline
style={{...}}layout declarations?- Recommendation: add a code-review checklist in Pass 3, not a blocking lint rule, to avoid false positives.
Risks
| Risk | Severity | Mitigation |
|---|---|---|
| Large diff touching many files | High | Split into three chained PRs; each under 400 changed lines. |
| Visual regressions on pages not manually tested | Medium | Rely on typecheck/lint for TSX; do visual spot-checks on representative pages. |
| Inline-style refactor breaks dynamic values | Medium | Only refactor static layout styles; keep dynamic values (computed positions) in JS. |
| Token changes affect existing components unexpectedly | Medium | Add new tokens only; do not rename existing tokens without a compat layer. |
| Mobile safe-area behavior varies across devices | Medium | Use env(safe-area-inset-bottom, 0px) with a sensible fallback. |
Effort Estimate
| Pass | Focus | Est. Files | Est. Lines | Complexity |
|---|---|---|---|---|
| Pass 1: Foundations | tokens, missing primitives, mobile nav/FAB | 4–6 | ~400 | Medium |
| Pass 2: Component Cleanup | inline styles, sidebars, forms, badges | 10–14 | ~600 | High |
| Pass 3: Consolidation | modals, cards, breakpoints, docs | 8–12 | ~400 | Medium |
| Total | 22–32 | ~1400 | High |
Review workload forecast: Each pass should stay near or below the 400-line review budget. Pass 2 may need to be split further if it grows.
Next Recommended Phase
Spec — detail the exact token additions, primitive class API, mobile-nav height calculation, and the migration path for inline styles.
Should I proceed to spec?