- Phase 0
[Opus]— Token layer: CSS vars, Tailwind config, Inter/JetBrains Mono, theme reducer,statusColors.js - Phase 1a
[Sonnet]— Shell: SkipLink, HashDisplay, Navigation, Footer, App/AppContent wiring - Phase 1b
[Opus]— Auth surfaces: WalletConnect, UserRegistration, RoleSelector
API spec was designed by Opus (see previous session). Sonnet implements in this order:
client/src/components/ui/LoadingSpinner.js— add token color names (accent,success,current,on-accent,muted); legacy names (blue,green,purple,gray,white) become aliases so existing callers don't break. Defaultcolor="accent". UpdatefullScreenbackdrop + label colors.client/src/components/StyledComponents.js— deleteGlassContainerandConnectButtonentirely. RewriteButtonto use token variants,focus-visible:rings,disabled:opacity-60, andLoadingSpinnerinstead of the inline spinner. RewriteCardwith token surface + optional elevation/padding props. RewriteFormInput/FormSelectwith token-driven input styles.client/src/components/ui/index.js— removeGlassContainerandConnectButtonfrom re-exports.client/src/components/ui/FormField.js— class-only swap:text-gray-700→text-fg,text-red-500/600→text-danger,text-gray-500→text-fg-muted,border-red-300→border-danger. A11y wiring untouched.client/src/components/ui/Modal.js— backdropbg-black/50→bg-fg/50 backdrop-blur-sm; panelbg-white rounded-xl shadow-xl→bg-surface-raised border border-line rounded-token-lg shadow-soft-lg. FocusTrap and scroll-lock unchanged.client/src/components/ui/TabNavigation.js— active:border-blue-500 text-blue-600→border-accent text-accent; inactive:text-gray-500 hover:text-gray-700 hover:border-gray-300→text-fg-muted hover:text-fg hover:border-line-strong. Addfocus-visible:rings.client/src/components/ui/ErrorDisplay.js—bg-red-50 border-red-200 text-red-700→bg-danger-soft border-danger/30 text-danger. Button rings →focus-visible:ring-focus-ring.client/src/components/ui/NotificationsContainer.js— switch from solid-color panels to soft-tinted per type (bg-success-soft,bg-danger-soft,bg-warning-soft,bg-info-soft). Text inherits from parent (droptext-white).
Verify after all 8 files:
cd client && NODE_ENV=development npx react-scripts build 2>&1 | grep -iE "warning|error"
# Expect: empty
grep -rnE 'bg-(blue|red|green|yellow|purple|gray)-[0-9]|text-(blue|red|green|yellow|purple|gray)-[0-9]' \
src/components/ui src/components/StyledComponents.js
# Expect: emptyclient/src/components/dashboard/Dashboard.js (~1628 LOC). Apply token swaps throughout:
- Status colors →
statusColors.jshelpers (statusBadgeClass,statusTextClass,statusBgClass) - Hard-coded grays →
text-fg-muted,text-fg-subtle - Blues →
text-accent,bg-accent,bg-accent/10 - Card surfaces →
bg-surface border border-line LoadingSpinner color="green"→color="success"
In priority order (one PR-sized unit each):
client/src/pages/DataMarketplace.js(~1018 LOC)client/src/pages/AccessHistoryPage.js(~833 LOC) — useHashDisplayfor IDsclient/src/pages/DataContributionPortal.js(~787 LOC)client/src/pages/TransactionPage.js(~516 LOC) — heavyHashDisplayadoption for tx hashesclient/src/components/DataBrowserView.js/DataBrowser.jsclient/src/components/analytics/— DataVisualization, StatisticalAnalysis, PopulationStudiesclient/src/pages/StoragePage.js
client/src/components/ProfileManager.js— visual-only swap (logic was refactored in a prior task)client/src/pages/resources/— 6 pages, mostly typography work (static content)
- Audit all pages for
text-gray-500survivors → remap totext-fg-muted/text-fg-subtle✅ - Add
aria-liveregions on data filters and pagination ✅ - Add
<caption>or heading-above-table on all data tables ✅ - Add
eslint-plugin-jsx-a11yas dev dep; run and fix violations ✅ (0 violations) - Optional:
@axe-core/reactin dev mode only
| Concept | Class |
|---|---|
| Page background | bg-page |
| Card/container | bg-surface border border-line |
| Elevated (nav/modal) | bg-surface-raised |
| Body text | text-fg |
| Secondary text | text-fg-muted |
| Tertiary/placeholder | text-fg-subtle |
| Primary action | bg-accent hover:bg-accent-hover text-accent-fg |
| Focus ring | focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring |
| Success | bg-success-soft text-success |
| Warning | bg-warning-soft text-warning |
| Danger | bg-danger-soft text-danger |
| Info | bg-info-soft text-info |
| Monospace (addresses/hashes) | font-mono via HashDisplay component |
| Shadows | shadow-soft-sm, shadow-soft-md, shadow-soft-lg |
| Radii | rounded-token, rounded-token-sm, rounded-token-lg |