Skip to content

ux: extract the three surfaces every screen was rewriting - #387

Open
huyplb wants to merge 2 commits into
mainfrom
ux/professional-polish
Open

ux: extract the three surfaces every screen was rewriting#387
huyplb wants to merge 2 commits into
mainfrom
ux/professional-polish

Conversation

@huyplb

@huyplb huyplb commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

First of three slices toward the mockups. Retargeted at main, since #385 landed there and its branch is gone.

What the mockups actually needed

Most of the mockup functionality already exists — #385 shipped it. What did not exist was a consistent surface to render it on. Counted, not judged by eye:

  • 85 distinct card/panel class strings across the frontend
  • the uppercase label above a group in eight spellings across ~70 uses — text-[10px] vs text-[11px], tracking-wide vs tracking-wider, text-slate-400 vs text-slate-500

None of that variation carried meaning. It is what screens look like when each is written alone, and it is the main reason the UI reads as less finished than the mockups do.

The change

shared/components/surfaces.tsxSectionLabel, Panel, StatCard. Lowercase filename per CONVENTIONS: a components file is PascalCase only when it exports a single component.

The access feature already said this once with labelCls, but a feature cannot lend a primitive to another feature — architecture.test.ts forbids reaching into features/*/lib, correctly. It now defers to the shared string, so there is one definition instead of a matching pair free to drift.

Migrated the two places that had each grown their own stat card:

  • Peek Insight — Rows / Null-heavy / High distinct
  • Snapshot briefing — was a run of coloured numbers, +3 ~2 −0, which asks the reader to supply the nouns. It names them now, as the mockup shows.

StatCard keeps the hint optional deliberately. A row count estimated from a catalog and one arrived at by counting are different claims; that line is where the difference gets said, and rendering it empty would read as a value that failed to load.

Verification

Eight tests, A/B'd against three deliberate breaks — tone moved from value to label, hint rendered unconditionally, a falsy value blanked to an em dash. Each break fails the test written for it, so none are vacuous.

Suite: 3627 passed, 0 failed. Typecheck clean.

The next two slices, and what they cost

  • Peek Insight → Size + Orphan FKs. Bigger than it looks. sizeBytes needs a different catalog expression in each of the 14 dialect probes, each worth verifying against a live engine. And the orphan figures in the mockup ("14 orphans · 99.99% matched") need a real WHERE NOT EXISTS scan, which contradicts the contract table-insight.service.ts states in its own header — "Catalog-only … Never COUNT(DISTINCT)". I plan to make orphans an explicit opt-in probe so the default load stays cheap and the two claims stay separable.
  • Account stage → inline alterations, replacing today's link out to User Management.

🤖 Generated with Claude Code


Note

Low Risk
Presentation-layer refactor with preserved test IDs and unit tests; no API, auth, or data-path changes.

Overview
Introduces shared/components/surfaces (SectionLabel, Panel, StatCard, plus sectionLabelCls / panelCls) so card layout and micro-labels stop diverging across features. Access labelCls now re-exports sectionLabelCls instead of a duplicate Tailwind string.

Data Peek Insight and Lokee version briefing drop hand-rolled stat boxes in favor of StatCard (named labels, optional hints, tone on the value). The briefing moves from a single row of + / ~ / − numbers to a three-column card grid.

Adds surfaces.test.tsx (label consistency, tone/hint/zero-value behavior, optional panel padding). The diff also adds planning docs excel-and-sheets-import.md and restructure.md with no runtime changes.

Reviewed by Cursor Bugbot for commit b9a6708. Bugbot is set up for automated code reviews on this repo. Configure here.

huyplb and others added 2 commits September 7, 2026 23:26
Counted, not judged by eye: the frontend held 85 distinct card/panel class
strings, and the small uppercase label above a group came in eight spellings
across some seventy uses — text-[10px] and text-[11px], tracking-wide and
tracking-wider, text-slate-400 and text-slate-500. None of that variation
carried meaning. It is what screens look like when each is written alone.

shared/components/surfaces.tsx now holds SectionLabel, Panel and StatCard.
Named for the set and lowercase, per CONVENTIONS: a components file is
PascalCase only when it exports one component.

The access feature already had `labelCls` saying this once, but a feature
cannot lend a primitive to another feature — architecture.test.ts forbids
reaching into `features/*/lib`, and rightly. It now defers to the shared
string so there is a single definition rather than a matching pair.

Migrated the two places that had each grown their own stat card: Peek Insight
(Rows / Null-heavy / High distinct) and the snapshot briefing. The briefing was
a run of coloured numbers — "+3 ~2 −0" — which asks the reader to supply the
nouns; it now names them, which is what the mockup shows.

StatCard keeps the hint line optional on purpose. A row count estimated from a
catalog and one arrived at by counting are different claims, and that line is
where the difference gets said; rendering it empty would read as a value that
failed to load.

Eight tests, A/B'd against three deliberate breaks — tone moved to the label,
hint rendered unconditionally, a falsy value blanked to an em dash. Each break
fails the test written for it.

Suite: 3625 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_eb93ab0c-fb99-4e6b-8d14-4627e89091f7)

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