feat(ui): D.6a wrap MeasurementDashboard in DeviceRack + migrate cards - #76
Conversation
PR 10 (sub-step a) of 16 in the UI consistency overhaul. First of three small PRs against MeasurementDashboard.tsx (2814 LOC) — split per plan §E.3 to keep each diff eyeball-reviewable. This step: - Wrap the dashboard outer <div data-testid="measurement-dashboard"> in <DeviceRack name="Measurements" density="dense" status="success">. The dashboard now lives inside the Live 12 device chrome (title strip + LED + dense body padding) consistent with every other results section. - Migrate every AccentMetricCard (5 instances at :1325, :1365, :1384, :1662, :1866) to <MetricTile size="xl">. The xl size renders the numeric value at text-3xl (1.875rem) — exact visual match for the old AccentMetricCard which manually appended text-3xl to its value span. accent="warning" call at :1866 maps cleanly to MetricTile's accent prop (both share warning/success/error/accent/neutral tones). Drop the AccentMetricCard import in favor of DeviceRack + MetricTile from ./ui. Other MeasurementPrimitives exports (DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, StatusBadge, StyledDataTable, TokenBadgeList) stay imported — those are migrated in D.6b/c. Preserved verbatim: - data-testid="measurement-dashboard" hook (locked by smoke tests). - All MetricTile props (label/value/unit/headerRight/footer) match AccentMetricCard's API 1:1. - All inner data-text-role attributes and visible text. Verified: lint clean, 628/628 unit tests passing, build clean (AnalysisResults chunk stable at 254 KB / 63 KB gz). Next: D.6b — UnavailableMeasurementCard → EmptyState + drift fix at :438 (bg-blue-500 → bg-accent). D.6c — local SectionHeader (:288-303) → primitive. https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
slittycode
left a comment
There was a problem hiding this comment.
Verdict: COMMENT
Summary
Pure UI restyle — wraps MeasurementDashboard in DeviceRack chrome and migrates 5 AccentMetricCard instances to MetricTile size="xl". No Phase 1/2/3 logic touched, no measurement schema changes, no phase boundary violations. One real finding: the PR description's "exact visual match" claim is false in two ways.
Findings
Should fix (post-merge)
AccentMetricCard defaults accent to 'accent', which renders border-l-2 border-accent on every instance unless overridden. MetricTile defaults accent to 'none' — no left border. The 4 tiles that don't pass an explicit accent prop (Tempo :1325, Key Signature :1365, Duration :1384, the loudness .map() block :1662) have silently dropped their left accent border. Only the Dynamics & Texture fallback :1866 correctly carries accent="warning".
If the intent is to keep the accent border on core metric tiles — and it was the default in the old component — each of those 4 call sites needs accent="accent". If the intent is to strip it (they're now inside a rack frame), the PR description should not claim "exact visual match."
Second minor mismatch: AccentMetricCard uses p-4, MetricTile uses p-3 (tileVariants base classes). The tiles are slightly tighter now. Probably fine given the rack adds its own body padding, but not "exact."
Worth considering
data-testid="measurement-dashboard" moved one DOM level deeper (now a child of DeviceRack's body div instead of the root render node). Playwright locators that use page.locator('[data-testid="measurement-dashboard"]') will still resolve, but any test that also checks evaluate(el => el.parentElement.tagName) or similar structural assertions will fail. The smoke tests couldn't run in this environment to verify — flag if D.6b/c smokes start failing on dashboard fixture lookups.
Test results
Unit tests: not runnable in this environment (node_modules absent). PR reports 628/628 passing — no reason to doubt it, this change doesn't touch any service layer. Smoke tests: sandbox-blocked as noted in the PR.
Phase boundary check
Clean. No Phase 1 output consumed differently, no Phase 2/3 code touched, no measurement values re-derived.
Generated by Claude Code
PR 14 of 16 in the UI consistency overhaul. Final cleanup pass. Removes three CSS utility classes from index.css: - .ableton-panel - .ableton-device - .ableton-header All three were retired by D.* migrations — every former consumer now uses the canonical primitives from components/ui/ (Panel, DeviceRack, SectionHeader). `grep -rn` against apps/ui/src/ confirms zero remaining usages. .ableton-shell and .ableton-toolbar STAY because App.tsx:952,956 still consumes them for the outer app chrome (the load-bearing section-grid shell). A focused follow-up could migrate those two to DeviceRack / a future AppShell primitive; out of scope here. Deferred (preserved as-is): - components/MeasurementPrimitives.tsx cannot be fully deleted yet — 5 consumers still depend on timeline/lane primitives (LaneContainer, LaneRow, StatsBar, TimeRuler) that the plan explicitly preserved. The shipped primitives (StatusBadge, DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, TokenBadgeList, StyledDataTable, AccentMetricCard) also still have consumers in MeasurementDashboard and AnalysisResults sections that weren't migrated (StructureLanes, HarmonyLanes, AnalysisResults remaining sections). Keep the file intact. - components/Tooltip.tsx stays as a re-export shim; the file isn't causing any drift and external imports may still target it. Verified: lint clean, 628/628 unit tests passing, build clean. D.* migrations summary (all merged or open at time of this PR): - D.0 Foundation (#64) ✓ - D.1 Primitives complete (#65) ✓ - D.2 SamplePlayback (#66) ✓ - D.3 SignalChain marquee (#67) ✓ - D.4 FileUpload + Input Source (#69) ✓ - D.5a Results header + metric strip (#71) ✓ - D.5b Mix Chain (#73) ✓ - D.5c Patches (#74) ✓ - D.5d Section headers (#75) ✓ - D.6a Dashboard structure (#76) ✓ - D.6b Dashboard sections (#77) ✓ - D.6c Dashboard headers (#78) ✓ - D.7 SessionMusicianPanel + MixDoctorPanel (#79) — open - D.8 Signal Monitor + SpectrogramViewer drift (#80) — open - D.9 DenseDawConcept drift (#81) — open - D.10 Cleanup (this PR) ✓ https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
…82) PR 14 of 16 in the UI consistency overhaul. Final cleanup pass. Removes three CSS utility classes from index.css: - .ableton-panel - .ableton-device - .ableton-header All three were retired by D.* migrations — every former consumer now uses the canonical primitives from components/ui/ (Panel, DeviceRack, SectionHeader). `grep -rn` against apps/ui/src/ confirms zero remaining usages. .ableton-shell and .ableton-toolbar STAY because App.tsx:952,956 still consumes them for the outer app chrome (the load-bearing section-grid shell). A focused follow-up could migrate those two to DeviceRack / a future AppShell primitive; out of scope here. Deferred (preserved as-is): - components/MeasurementPrimitives.tsx cannot be fully deleted yet — 5 consumers still depend on timeline/lane primitives (LaneContainer, LaneRow, StatsBar, TimeRuler) that the plan explicitly preserved. The shipped primitives (StatusBadge, DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, TokenBadgeList, StyledDataTable, AccentMetricCard) also still have consumers in MeasurementDashboard and AnalysisResults sections that weren't migrated (StructureLanes, HarmonyLanes, AnalysisResults remaining sections). Keep the file intact. - components/Tooltip.tsx stays as a re-export shim; the file isn't causing any drift and external imports may still target it. Verified: lint clean, 628/628 unit tests passing, build clean. D.* migrations summary (all merged or open at time of this PR): - D.0 Foundation (#64) ✓ - D.1 Primitives complete (#65) ✓ - D.2 SamplePlayback (#66) ✓ - D.3 SignalChain marquee (#67) ✓ - D.4 FileUpload + Input Source (#69) ✓ - D.5a Results header + metric strip (#71) ✓ - D.5b Mix Chain (#73) ✓ - D.5c Patches (#74) ✓ - D.5d Section headers (#75) ✓ - D.6a Dashboard structure (#76) ✓ - D.6b Dashboard sections (#77) ✓ - D.6c Dashboard headers (#78) ✓ - D.7 SessionMusicianPanel + MixDoctorPanel (#79) — open - D.8 Signal Monitor + SpectrogramViewer drift (#80) — open - D.9 DenseDawConcept drift (#81) — open - D.10 Cleanup (this PR) ✓ https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe Co-authored-by: Claude <noreply@anthropic.com>
Summary
PR 10 (sub-step a) of 16 in the UI consistency overhaul / Live 12 restyle stack. First of three small PRs against
MeasurementDashboard.tsx(2814 LOC) — split per plan §E.3 to keep each diff eyeball-reviewable.This step
<div data-testid="measurement-dashboard">in<DeviceRack name="Measurements" density="dense" status="success">. The dashboard now lives inside the Live 12 device chrome (title strip + LED + dense body padding) consistent with every other results section.AccentMetricCard(5 instances at:1325,:1365,:1384,:1662,:1866) →<MetricTile size="xl">. Thexlsize renders the numeric value attext-3xl(1.875rem) — exact visual match for the old AccentMetricCard which manually appendedtext-3xlto its value span. Theaccent="warning"call at:1866maps cleanly (both share warning/success/error/accent/neutral tones).Drop the
AccentMetricCardimport in favor ofDeviceRack+MetricTilefrom./ui. OtherMeasurementPrimitivesexports (DeltaBadge, MetricBar, MetricBarRow, OutlinePillButton, StatusBadge, StyledDataTable, TokenBadgeList) stay imported — those migrate in D.6b/c if at all.Preserved verbatim
data-testid="measurement-dashboard"hook (locked by smoke tests).MetricTileprops (label/value/unit/headerRight/footer) matchAccentMetricCard's API 1:1.data-text-roleattributes and visible text.Test plan
npm run lint— cleannpm run test:unit— 628/628 passingnpm run build— clean (AnalysisResults chunk stable at 254 KB / 63 KB gz)npm run test:smoke— sandbox blocks Playwright browser;data-testid+ text content preservedUp next
UnavailableMeasurementCard→<EmptyState>; drift fix at:438(bg-blue-500→bg-accent).:288-303) → primitive.https://claude.ai/code/session_01WNtYcWXwn4mVnnjxqT7uAe
Generated by Claude Code