feat: design token system — DS_TEXT/DS_SURFACE/DS_BORDER + 237 hex migrations

Token infrastructure (src/lib/ds.ts):
- DS_TEXT: 16 semantic text color tokens (primary/secondary/muted/success/
  warning/error/info/brand/signal + dark variants successDark/warningDark/
  signalDark/infoDark for text on tinted surfaces)
- DS_BG: page/surface/subtle/muted background tokens
- DS_BORDER: default/muted/strong border tokens
- DS_SURFACE: 10 bg+border surface pairs (success/warning/error/info/indigo/
  purple/orange/blue/neutral/slate)
- DS_MATCH_TIER: score-tier surface aliases keyed by strong/moderate/weak
- DS_PRE_MARKET / DS_MARKET_SIGNAL: named aliases for futureCard tokens
- DS_SHADOW: card/panel/dialog elevation tokens
- BADGE_COLORS: 14 semantic presets for GenericBadge (confidenceHigh,
  riskMedium, preMarket, marketSignal, verified, gold, silver, bronze…)

GenericBadge (src/components/shared/GenericBadge.tsx):
- New semanticVariant prop (keyof BADGE_COLORS) — preferred over raw hex
- color prop becomes optional (fallback), type-documented as escape hatch

Priority file migrations — 237 hex literals replaced across 10 files:
  ScoreBreakdownPanel.tsx    −22  PipelineDetailPanel.tsx    −22
  FutureAvailabilityCard.tsx −26  AICompareSummary.tsx       −27
  LocationIntelligencePanel  −39  AssistantPromptSuggestions −18
  UnitStructurePanel.tsx     −25  BerichtDialog.tsx          −24
  PreMarketPanel.tsx         −24  PropertyActivityLogPanel   −10

ESLint (eslint.config.js):
- Updated rule message to reference new tokens (DS_TEXT, DS_SURFACE, etc.)
- Added 'stroke' to monitored property names
- Remains 'warn' for gradual migration; use check:tokens for CI gate

CI script (scripts/check-tokens.js + npm run check:tokens):
- Counts hex patterns in components/ + pages/
- Fails if count > THRESHOLD (ratchet: 1958 baseline, lower per sprint)
- Reports top 15 offenders for prioritizing next migration batch

Results: ESLint targeted sx-prop violations: 1752 → 1030 (−41%)
0 TypeScript errors, 154 tests green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Sutter
2026-05-24 14:05:52 +02:00
parent e62391af66
commit 7934da7669
16 changed files with 445 additions and 243 deletions
+17 -2
View File
@@ -1,9 +1,21 @@
import { Chip, Tooltip } from '@mui/material'
import type { ReactElement } from 'react'
import { BADGE_COLORS } from '../../lib/ds'
export type BadgeSemanticVariant = keyof typeof BADGE_COLORS
export interface GenericBadgeProps {
label: string
color: string
/**
* Semantic variant key from BADGE_COLORS (preferred).
* Example: semanticVariant="confidenceHigh" instead of color="#1a7a4a"
*/
semanticVariant?: BadgeSemanticVariant
/**
* Raw hex color — use only when no semantic variant fits.
* Prefer semanticVariant to avoid hardcoded colors.
*/
color?: string
/** transparent: semi-opaque bg (color + 18% opacity) | solid: filled bg, white text */
variant?: 'transparent' | 'solid'
/** Adds a 1px border at color 25% opacity (transparent variant only) */
@@ -20,7 +32,8 @@ export interface GenericBadgeProps {
export function GenericBadge({
label,
color,
semanticVariant,
color: colorProp,
variant = 'transparent',
showBorder = false,
bold = false,
@@ -29,6 +42,8 @@ export function GenericBadge({
tooltip,
ariaLabel,
}: GenericBadgeProps) {
const color = semanticVariant ? BADGE_COLORS[semanticVariant] : (colorProp ?? '#64748b')
const chip = (
<Chip
size={size}