feat(ui): cohesive frontend polish — design system + per-screen refinement

Distill the UI into a single, recognizable voice: a precision
instrument for one operator on one machine. Bloomberg-coded chrome,
warm-paper detail surfaces, mono-heavy numerics, with one editorial
serif accent for moments of weight.

Design system
- Three-font stack: Geist Sans (UI), Geist Mono (data), Instrument
  Serif (editorial display). No Inter, no system fonts.
- Two surfaces: dark chrome (--background, --accent, --signal) and
  warm paper detail surfaces (--surface, --surface-ink*).
- Inbox has its own Ticker Tape terminal palette (--tt-*).
- Shared component classes: .eyebrow, .mono, .display, .surface,
  .surface-2, .row-hover, .nav-active, .kbd, .editorial, .hairline.
- --m-* token aliases for the legacy drawer components so test-
  asserted class strings keep resolving to the same hue family.

Drawers (Claim + Remit)
- Editorial display face for totals (paid/adjustment amounts).
- Color-coded money tiles: green-tinted paid card, amber-tinted
  adjustment card when non-zero, muted otherwise.
- Tabs get accent-blue underline + CSS-driven active state.
- Validation banners with proper background opacity + ring-around-
  dot success badge.
- StateHistoryTimeline: dashed border, ring around dots, ↳ prefix
  for remit ids.
- DiagnosesList, PartiesGrid, MatchedRemitCard, CasAdjustmentsPanel:
  refined typography, dashed dividers, italic descriptions, mono
  amounts, font-semibold totals, hover row tints.

Inbox Ticker Tape
- Custom RowCheckbox with sr-only input + amber accent.
- Alternating row striping, hover tints, accent rail with inset
  shadow on selection.
- Refined sparkline with glow at high values.
- BulkBar: bottom-floating bar with amber count chip, larger shadow.
- CandidateBreakdown: animated progress bars with amber gradient.
- InboxHeader: Instrument Serif headline, mono day/date stamp,
  pulsing amber status dot.

Dialogs & search
- NewClaimDialog: editorial title, mono NPI/CPT/amount fields.
- SearchBar: refined input row with mono, footer with pulsing
  loading indicator.
- KeyboardCheatsheet: monogram icon chip, hover row states, refined
  eyebrow header.

Primitives
- StatusBadge / ClaimStateBadge: per-state dot indicators.
- SelectItem: data-[highlighted]:outline tokens for keyboard a11y.
- Table primitives: refined header treatment, hover/focus states.

Tests + build
- 354/354 tests passing across 59 files.
- Vite build clean (53.84 kB CSS / 560.86 kB JS).
- Eyebrow assertions updated to match the consolidated .eyebrow
  class (intact visual contract, abstracted class string).
- Badge variant tokens updated to the polished bg-muted/80 /
  /0.14 opacity scale.
This commit is contained in:
Tyler
2026-06-20 22:27:01 -06:00
parent 02841d7e6e
commit fbe9940a3f
70 changed files with 2582 additions and 1663 deletions
+33 -22
View File
@@ -1,27 +1,29 @@
import { Outlet } from "react-router-dom";
import { useIsFetching } from "@tanstack/react-query";
import { cn } from "@/lib/utils";
import { Sidebar } from "./Sidebar";
import { SkipLink } from "@/components/ui/skip-link";
import { SearchBar } from "./SearchBar";
/**
* App shell. Three columns:
* - Sidebar (240px, fixed)
* - Top bar (sticky, lightweight utility row)
* - Outlet (page content, max-w-[1400px] centered)
*
* The hairline scan element at the very top of the viewport is a 1px
* line that slides an accent bar across the entire width whenever
* the React Query layer has an in-flight request. The intent is to
* surface "we're doing something" without a spinner — a moving line
* reads as a sensor sweep, not a loading state.
*/
export function Layout() {
// useIsFetching() returns the number of in-flight queries and is 0 on
// first load (queries that have not yet fired are not counted). We use it
// to drive a 1px hairline scan element at the very top of the layout.
const isFetching = useIsFetching();
const showScan = isFetching > 0;
return (
<div className="relative min-h-screen z-10">
{/* Skip link — first Tab stop, jumps past the sidebar.
Hidden until focused (see .skip-link in index.css). */}
<SkipLink />
{/*
Scan element — always in the DOM (no layout shift), 1px tall, full
width. pointer-events-none so it never blocks clicks. The inner
bar uses the `scan` keyframe from tailwind.config to slide a 1/3-
width electric-blue bar across the hairline.
*/}
<div
className="fixed top-0 left-0 right-0 z-50 h-px overflow-hidden pointer-events-none transition-opacity duration-200"
style={{ opacity: showScan ? 1 : 0 }}
@@ -38,19 +40,28 @@ export function Layout() {
tabIndex={-1}
className="md:pl-60 outline-none"
>
{/*
Top bar — sits inside <main> so it shares the sidebar's right
column. Sticky to the viewport top so the search chip stays
reachable while the user scrolls long claim lists. The
hairline + horizontal padding mirrors the main content
container below it for visual continuity. The Sidebar's
own header is taller and brand-marked; this is the
lightweight "always-on utility" row.
*/}
<div className="sticky top-0 z-20 mx-auto max-w-[1400px] px-8 h-12 flex items-center justify-end bg-background/70 backdrop-blur-md border-b border-border/40">
<div
className="sticky top-0 z-20 mx-auto max-w-[1400px] px-6 lg:px-8 h-12 flex items-center justify-end gap-3 bg-background/70 backdrop-blur-md border-b border-border/40"
data-print="hide"
>
{/* Tailing pill on the left edge of the top bar — a tiny
global "system is alive" indicator. It lights up whenever
any query is in flight, complementing the hairline scan. */}
<div className="mr-auto flex items-center gap-2 text-[10.5px] mono uppercase tracking-[0.14em] text-muted-foreground/60">
<span className="relative inline-flex h-1.5 w-1.5">
<span
className={cn(
"absolute inline-flex h-full w-full rounded-full bg-[hsl(var(--success))] opacity-60",
showScan && "animate-ping"
)}
/>
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-[hsl(var(--success))]" />
</span>
{showScan ? "Working" : "Idle"}
</div>
<SearchBar />
</div>
<div className="mx-auto max-w-[1400px] px-8 py-10">
<div className="mx-auto max-w-[1400px] px-6 lg:px-8 py-8 lg:py-10">
<Outlet />
</div>
</main>