hub-client: UI/UX modernization Phase 0 — design tokens and CSS lint - #605
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
08f6f1a to
ab325b3
Compare
|
I assume @vezwork has taken a look at the large-scale structure of these changes - we could benefit from someone's first-hand front-end expertise here. |
|
@vezwork and I discussed last week - not everything in here specifically but the direction - phases 0-4 are engineering and accessibility fixes. I do not plan to go beyond this for now (the later stages are there so we can pick up at a later date). |
Ok, great. By "this", do you mean all phases or just Phase 0? (Ie, do you intend to merge Phases 1.. as well as 0? I just want to keep track.) |
|
Ah sorry - I realise it didn't upload the full plan file. I'll do that separately - but basically I've sequenced it so we do the best practices stuff (phases 0-4 I mentioned) and then there's a gate before we make any opinionated visual changes. It'll all be part of one stack so hopefully easy to follow. |
26a1dff to
15e1f00
Compare
…routes, visual + axe baselines UI/UX modernization Phase 0 (bd-5nm6v8bl, epic bd-2q55e6rc), test specifications first per the plan: - scripts/lint-css.mjs (npm run lint:css): dependency-free CSS lint enforcing token-first rules — no hex/rgb() colors outside theme.css, no bare z-index integers, no outline:none without :focus-visible, no physical box properties where a logical equivalent exists. Grandfathered exceptions live in lint-css-exceptions.json (187 entries); stale exceptions fail, so the list is self-pruning as rules burn down per phase. - DevHarness grows baseline routes beyond the setup screens: projects-home, dialog-new-file, dialog-share, dialog-new-asset, sidebar (SidebarTabs + FileSidebar + OutlinePanel), header (MinimalHeader), notifications (Toast + UpdateAvailableToast + EphemeralSessionBanner) — all with canned data, no hub server. - e2e/baseline-screens.visual.spec.ts: Playwright pixel baselines of every route x light/dark, clock frozen at 2026-08-25 (ProjectsHome renders relative dates), transitions disabled before capture. - e2e/baseline-a11y.visual.spec.ts: @axe-core/playwright scans of the same routes x light/dark (approved devDependency). Characterization model: current serious/critical violations (all color-contrast) are recorded in helpers/axe-baseline.json; new or worsened violations fail, fixed ones force a baseline regeneration. - claude-notes plan pointer for the braid epic. Verified: full visual suite 38/38 green across repeated runs; vitest 1005/1005; typecheck + eslint clean.
…lines bd-5nm6v8bl. Additive only — no computed value changes (verified: the Phase 0 visual baselines diff clean against pre-token captures): - theme.css gains the scale layer: --space-1..8 (4px base), --radius-sm/md/lg, --shadow-1/2/3 (per-theme where the source value was per-theme), --z-base..--z-max layer scale, --text-xs..xl + --font-weight-* + --leading-* + --font-mono, --duration-fast/base + --ease-out/standard, --focus-ring. --modal-shadow now aliases --shadow-3 (identical values, both themes). - Fixed primitives for the coming migration: --alpha-black/white-*, --posit-teal/blue/green-alpha-*, the attribution palette (ReplayDrawer ring), the Catppuccin Macchiato debug-inspector palette, and the legacy ProjectSelector palette. - Header comment documents the token layering convention (primitive → scale → semantic → component). - DevHarness #/dev/tokens page renders every scale token (spacing swatches, radii, shadows, type specimens, focus ring); covered by new visual + axe baselines in both themes. - lint:css color rule refined: token *definitions* (custom-property declarations) may hold literals in any file — standalone dev pages (src/debug/) don't load theme.css and keep a local token block. Use sites still must reference var(--token). - Baseline determinism: bootHarness pins a fixed IndexedDB identity (the app's random anonymous avatar color was an intermittent 4th axe color-contrast node and sub-threshold screenshot noise), freezes the clock (relative dates), disables transitions (mid-transition contrast measurement drifted), and waits for fonts. Visual config gets retries: 1 for dev-server contention flakes (assertion failures remain deterministic and fail through). Verified: full visual suite 42/42 green across repeated runs.
bd-5nm6v8bl. Mechanical rename of all 130-ish ph- (projects-home) class tokens to the .qh-* (Quarto Hub) prefix — 611 replacements across 22 files (components, CSS, e2e selectors, unit tests), done early in the modernization before more CSS accrues. The ui.css header comment's 'rename pending' note is now resolved. Also drops 10 lint:css exceptions made stale by the token-definition relaxation (debug.css local token block) — the self-pruning exceptions list working as designed. Verified: typecheck clean, vitest 1005/1005, lint:css clean, visual suite 42/42 (pixel-identical against pre-rename baselines).
…shared utilities bd-5nm6v8bl. Every hardcoded color and bare z-index outside token definitions now flows through theme.css (or debug.css's local token block). lint:css exceptions: 187 → 85, with no-hardcoded-color and no-bare-z-index burned to EMPTY — the rules are now enforced repo-wide for all future changes. All migrations are value-preserving by construction; the Phase 0 visual baselines (16 screens x 2 themes) diff clean and the axe baselines hold. Two notes: - ProjectsHome menu z-index 70 → --z-dropdown (60): order-preserving renumber — no layer exists between 60 and 70, and the menu must only beat the sticky header (40). Pixel-invisible by construction. - Editor.css drops a dead var() fallback (rgba(0,0,0,0.1)) on --error-overlay-border — the token is always defined. Token mapping highlights: fixed alpha tints (--alpha-black/white-*, --posit-teal-alpha-*) for drop overlays/shadows/focus rings; --text-on-accent for text on colored fills; --backdrop-bg for dialog scrims; --selector-* legacy palette (classic selector, light-only); --debug-* Catppuccin Macchiato palette (permanently-dark dev panel); --attribution-* for the ReplayDrawer collaborator ring; --z-* layers everywhere (incl. --z-revealjs-menu for the preview iframe's own stacking context). Shared utilities extracted to ui.css and adopted at exact-match sites: .qh-truncate (5 sites across FileSidebar + MinimalHeader), .qh-row-hover and .qh-active-accent-row (FileSidebar rows; the active-accent utility uses the always-transparent-border pattern and logical border-inline-start, so two physical-properties exceptions burned down with it). .file-item's margin-offset variant of the active treatment is deliberately left for Phase 1 sidebar work — unifying it is an alignment change, not a value-preserving one. Verified: lint:css clean, typecheck clean, vitest 1005/1005, visual suite 42/42 pixel-clean.
…/UX modernization pointer bd-5nm6v8bl closed.
15e1f00 to
79f15ac
Compare
Phase 0 of the hub-client UI/UX modernization: token foundation and CSS hygiene. No visual changes. New baselines prove the UI is pixel-identical before and after.
What changes
theme.cssdefines the scale tokens: spacing, radii, shadows, z-index layers, type, motion, and a focus ring.theme.cssdocuments the token layers: primitive, scale, semantic, component..ph-*classes rename to.qh-*(611 mechanical replacements).ui.cssgains shared utilities:.qh-truncate,.qh-row-hover,.qh-active-accent-row.New test infrastructure
npm run lint:csschecks four CSS rules. An exceptions list covers old code and shrinks as later phases fix it. The color and z-index rules are already at zero exceptions.#/dev/tokens.Verification
npm run build:allandnpm run test:cipass (1005 + 112 + 133 tests).Notes
cargo xtask verifystops at a known failure that already exists on main: the preview-renderer Equation\tagtest (bd-s36g9dav, bd-kn7ln981). This PR does not cause it.Tracks bd-2q55e6rc (Phase 0: bd-5nm6v8bl, closed). Plan:
claude-notes/plans/2026-08-26-hub-client-uiux-modernization.md.