@fragments-sdk/cli 0.5.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dist/bin.js +996 -79
  2. package/dist/bin.js.map +1 -1
  3. package/dist/{chunk-ICAIQ57V.js → chunk-6JBGU74P.js} +5 -3
  4. package/dist/chunk-6JBGU74P.js.map +1 -0
  5. package/dist/chunk-7OPWMLOE.js +1625 -0
  6. package/dist/chunk-7OPWMLOE.js.map +1 -0
  7. package/dist/{chunk-2H2JAA3U.js → chunk-CVXKXVOY.js} +3 -3
  8. package/dist/{chunk-2H2JAA3U.js.map → chunk-CVXKXVOY.js.map} +1 -1
  9. package/dist/{chunk-IOJE35DZ.js → chunk-NWQ4CJOQ.js} +3 -3
  10. package/dist/{chunk-2DJH4F4P.js → chunk-RVRTRESS.js} +3 -3
  11. package/dist/{chunk-V7YLRR4C.js → chunk-TJ34N7C7.js} +41 -4
  12. package/dist/{chunk-V7YLRR4C.js.map → chunk-TJ34N7C7.js.map} +1 -1
  13. package/dist/{chunk-XNWDI6UT.js → chunk-XHUDJNN3.js} +5 -5
  14. package/dist/{core-DKHB7FYV.js → core-W2HYIQW6.js} +4 -4
  15. package/dist/{generate-KL24VZVD.js → generate-LMTISDIJ.js} +5 -5
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.js +15 -7
  18. package/dist/index.js.map +1 -1
  19. package/dist/{init-NION5S3M.js → init-7CHRKQ7P.js} +5 -5
  20. package/dist/mcp-bin.js +8 -220
  21. package/dist/mcp-bin.js.map +1 -1
  22. package/dist/scan-WY23TJCP.js +12 -0
  23. package/dist/{service-RWUMZ3EW.js → service-T2L7VLTE.js} +5 -5
  24. package/dist/static-viewer-GBR7YNF3.js +12 -0
  25. package/dist/{test-ECPEXFDN.js → test-OJRXNDO2.js} +4 -4
  26. package/dist/{tokens-ITADYVPF.js → tokens-3BWDESVM.js} +6 -6
  27. package/dist/viewer-SUFOISZM.js +1822 -0
  28. package/dist/viewer-SUFOISZM.js.map +1 -0
  29. package/package.json +6 -5
  30. package/src/bin.ts +31 -0
  31. package/src/build.ts +147 -13
  32. package/src/cli-commands.ts +18 -0
  33. package/src/commands/__tests__/a11y-scoring.test.ts +278 -0
  34. package/src/commands/a11y-report.ts +625 -0
  35. package/src/commands/a11y.ts +168 -14
  36. package/src/commands/build.ts +16 -0
  37. package/src/commands/graph.ts +274 -0
  38. package/src/core/auto-props.ts +464 -0
  39. package/src/core/composition.ts +64 -1
  40. package/src/core/graph-extractor.test.ts +542 -0
  41. package/src/core/graph-extractor.ts +601 -0
  42. package/src/core/importAnalyzer.ts +5 -0
  43. package/src/core/schema.ts +2 -0
  44. package/src/core/types.ts +3 -1
  45. package/src/index.ts +4 -0
  46. package/src/mcp/server.ts +13 -220
  47. package/src/theme/__tests__/component-contrast.test.ts +338 -0
  48. package/src/theme/__tests__/contrast-validation.test.ts +326 -0
  49. package/src/theme/contrast.test.ts +331 -0
  50. package/src/theme/contrast.ts +246 -0
  51. package/src/theme/generator.ts +213 -1
  52. package/src/theme/index.ts +16 -0
  53. package/src/theme/types.ts +51 -0
  54. package/src/viewer/__tests__/a11y-fixes.test.ts +358 -0
  55. package/src/viewer/__tests__/viewer-integration.test.ts +2 -7
  56. package/src/viewer/components/AccessibilityPanel.tsx +493 -433
  57. package/src/viewer/components/ActionCapture.tsx +1 -1
  58. package/src/viewer/components/ActionsPanel.tsx +142 -183
  59. package/src/viewer/components/App.tsx +276 -183
  60. package/src/viewer/components/BottomPanel.tsx +40 -80
  61. package/src/viewer/components/CodePanel.tsx +9 -87
  62. package/src/viewer/components/CommandPalette.tsx +117 -74
  63. package/src/viewer/components/ComponentGraph.tsx +143 -126
  64. package/src/viewer/components/ComponentHeader.tsx +46 -43
  65. package/src/viewer/components/ContractPanel.tsx +124 -117
  66. package/src/viewer/components/ErrorBoundary.tsx +47 -35
  67. package/src/viewer/components/FigmaEmbed.tsx +18 -13
  68. package/src/viewer/components/FragmentEditor.tsx +126 -63
  69. package/src/viewer/components/HealthDashboard.tsx +146 -171
  70. package/src/viewer/components/HmrStatusIndicator.tsx +31 -41
  71. package/src/viewer/components/Icons.tsx +151 -98
  72. package/src/viewer/components/InteractionsPanel.tsx +317 -264
  73. package/src/viewer/components/IsolatedPreviewFrame.tsx +52 -27
  74. package/src/viewer/components/IsolatedRender.tsx +12 -6
  75. package/src/viewer/components/KeyboardShortcutsHelp.tsx +34 -70
  76. package/src/viewer/components/LandingPage.tsx +285 -305
  77. package/src/viewer/components/Layout.tsx +12 -10
  78. package/src/viewer/components/LeftSidebar.tsx +103 -155
  79. package/src/viewer/components/MultiViewportPreview.tsx +254 -63
  80. package/src/viewer/components/PreviewArea.tsx +113 -44
  81. package/src/viewer/components/PreviewFrameHost.tsx +36 -6
  82. package/src/viewer/components/PreviewPane.tsx +2 -3
  83. package/src/viewer/components/PreviewToolbar.tsx +109 -105
  84. package/src/viewer/components/PropsEditor.tsx +154 -74
  85. package/src/viewer/components/PropsTable.tsx +95 -82
  86. package/src/viewer/components/RelationsSection.tsx +71 -40
  87. package/src/viewer/components/ResizablePanel.tsx +158 -55
  88. package/src/viewer/components/RightSidebar.tsx +46 -56
  89. package/src/viewer/components/ScreenshotButton.tsx +12 -12
  90. package/src/viewer/components/SkeletonLoader.tsx +99 -83
  91. package/src/viewer/components/StoryRenderer.tsx +4 -11
  92. package/src/viewer/components/Toast.tsx +3 -67
  93. package/src/viewer/components/TokenStylePanel.tsx +136 -118
  94. package/src/viewer/components/UsageSection.tsx +26 -26
  95. package/src/viewer/components/VariantMatrix.tsx +140 -47
  96. package/src/viewer/components/VariantTabs.tsx +24 -68
  97. package/src/viewer/components/ViewportSelector.tsx +121 -114
  98. package/src/viewer/constants/ui.ts +23 -22
  99. package/src/viewer/entry.tsx +8 -3
  100. package/src/viewer/index.ts +3 -6
  101. package/src/viewer/preview-frame.html +43 -18
  102. package/src/viewer/server.ts +7 -16
  103. package/src/viewer/styles/globals.css +46 -85
  104. package/src/viewer/utils/a11y-fixes.ts +53 -30
  105. package/dist/chunk-ICAIQ57V.js.map +0 -1
  106. package/dist/chunk-U4GQ2JTD.js +0 -832
  107. package/dist/chunk-U4GQ2JTD.js.map +0 -1
  108. package/dist/scan-ESEXV7LF.js +0 -12
  109. package/dist/static-viewer-O37MJ5B6.js +0 -12
  110. package/dist/viewer-YDGFDTK5.js +0 -11104
  111. package/dist/viewer-YDGFDTK5.js.map +0 -1
  112. package/src/viewer/postcss.config.js +0 -6
  113. package/src/viewer/tailwind.config.js +0 -37
  114. /package/dist/{chunk-IOJE35DZ.js.map → chunk-NWQ4CJOQ.js.map} +0 -0
  115. /package/dist/{chunk-2DJH4F4P.js.map → chunk-RVRTRESS.js.map} +0 -0
  116. /package/dist/{chunk-XNWDI6UT.js.map → chunk-XHUDJNN3.js.map} +0 -0
  117. /package/dist/{core-DKHB7FYV.js.map → core-W2HYIQW6.js.map} +0 -0
  118. /package/dist/{generate-KL24VZVD.js.map → generate-LMTISDIJ.js.map} +0 -0
  119. /package/dist/{init-NION5S3M.js.map → init-7CHRKQ7P.js.map} +0 -0
  120. /package/dist/{scan-ESEXV7LF.js.map → scan-WY23TJCP.js.map} +0 -0
  121. /package/dist/{service-RWUMZ3EW.js.map → service-T2L7VLTE.js.map} +0 -0
  122. /package/dist/{static-viewer-O37MJ5B6.js.map → static-viewer-GBR7YNF3.js.map} +0 -0
  123. /package/dist/{test-ECPEXFDN.js.map → test-OJRXNDO2.js.map} +0 -0
  124. /package/dist/{tokens-ITADYVPF.js.map → tokens-3BWDESVM.js.map} +0 -0
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { useState, useEffect, useCallback } from "react";
12
- import clsx from "clsx";
12
+ import { Badge } from "@fragments/ui";
13
13
  import type { DesignToken, EnhancedStyleDiffItem, TokenUsageSummary } from "../../core/index.js";
14
14
  import { CheckIcon, XIcon, LoadingIcon, FigmaIcon, WandIcon } from "./Icons.js";
15
15
 
@@ -244,9 +244,9 @@ export function TokenStylePanel({
244
244
  // Show loading state
245
245
  if (figmaLoading) {
246
246
  return (
247
- <div className="flex items-center gap-2 text-tertiary p-4">
248
- <SyncingIcon className="w-4 h-4 animate-spin" />
249
- <span className="text-xs">Loading Figma styles...</span>
247
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-tertiary)', padding: '16px' }}>
248
+ <SyncingIcon style={{ width: 16, height: 16, animation: 'spin 1s linear infinite' }} />
249
+ <span style={{ fontSize: '12px' }}>Loading Figma styles...</span>
250
250
  </div>
251
251
  );
252
252
  }
@@ -254,12 +254,12 @@ export function TokenStylePanel({
254
254
  // Show error state
255
255
  if (figmaError) {
256
256
  return (
257
- <div className="flex items-center gap-2 text-tertiary p-4">
258
- <XIcon className="w-4 h-4 text-red-500" />
259
- <span className="text-xs">{figmaError}</span>
257
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-tertiary)', padding: '16px' }}>
258
+ <XIcon style={{ width: 16, height: 16, color: '#ef4444' }} />
259
+ <span style={{ fontSize: '12px' }}>{figmaError}</span>
260
260
  <button
261
261
  onClick={onFetchFigma}
262
- className="text-xs text-[--color-accent] hover:underline ml-2"
262
+ style={{ fontSize: '12px', color: 'var(--color-accent)', background: 'none', border: 'none', cursor: 'pointer', marginLeft: '8px', textDecoration: 'underline' }}
263
263
  >
264
264
  Retry
265
265
  </button>
@@ -270,12 +270,12 @@ export function TokenStylePanel({
270
270
  // Show idle state
271
271
  if (!figmaStyles) {
272
272
  return (
273
- <div className="flex items-center gap-2 text-tertiary p-4">
274
- <FigmaIcon className="w-4 h-4" />
275
- <span className="text-xs">Click to load style comparison</span>
273
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px', color: 'var(--text-tertiary)', padding: '16px' }}>
274
+ <FigmaIcon style={{ width: 16, height: 16 }} />
275
+ <span style={{ fontSize: '12px' }}>Click to load style comparison</span>
276
276
  <button
277
277
  onClick={onFetchFigma}
278
- className="text-xs text-[--color-accent] hover:underline ml-2"
278
+ style={{ fontSize: '12px', color: 'var(--color-accent)', background: 'none', border: 'none', cursor: 'pointer', marginLeft: '8px', textDecoration: 'underline' }}
279
279
  >
280
280
  Load
281
281
  </button>
@@ -330,157 +330,149 @@ export function TokenStylePanel({
330
330
  : 100;
331
331
 
332
332
  return (
333
- <div className="overflow-x-auto p-4">
333
+ <div style={{ overflowX: 'auto', padding: '16px' }}>
334
334
  {/* Summary Header */}
335
- <div className="flex items-center justify-between mb-3">
336
- <div className="flex items-center gap-4">
337
- <span className="text-xs font-medium text-primary">Style Comparison</span>
335
+ <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px' }}>
336
+ <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
337
+ <span style={{ fontSize: '12px', fontWeight: 500, color: 'var(--text-primary)' }}>Style Comparison</span>
338
338
 
339
339
  {/* Token info badge */}
340
340
  {tokenData && (
341
- <span className="text-xs text-tertiary">
341
+ <span style={{ fontSize: '12px', color: 'var(--text-tertiary)' }}>
342
342
  {tokenData.meta?.totalTokens || tokenData.tokens.length} tokens loaded
343
343
  </span>
344
344
  )}
345
345
  {tokenLoading && (
346
- <span className="text-xs text-tertiary flex items-center gap-1">
347
- <SyncingIcon className="w-3 h-3 animate-spin" />
346
+ <span style={{ fontSize: '12px', color: 'var(--text-tertiary)', display: 'flex', alignItems: 'center', gap: '4px' }}>
347
+ <SyncingIcon style={{ width: 12, height: 12, animation: 'spin 1s linear infinite' }} />
348
348
  Loading tokens...
349
349
  </span>
350
350
  )}
351
351
  {tokenError && !tokenLoading && (
352
- <span className="text-xs text-amber-600" title={tokenError}>
352
+ <span style={{ fontSize: '12px', color: '#d97706' }} title={tokenError}>
353
353
  Tokens not configured
354
354
  </span>
355
355
  )}
356
356
  </div>
357
357
 
358
- <div className="flex items-center gap-3">
358
+ <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
359
359
  {/* Compliance badge */}
360
360
  {tokenData && (
361
- <span
362
- className={clsx(
363
- "text-xs font-medium px-2 py-0.5 rounded",
364
- compliancePercent >= 80
365
- ? "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"
366
- : compliancePercent >= 50
367
- ? "bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300"
368
- : "bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300"
369
- )}
361
+ <Badge
362
+ variant={compliancePercent >= 80 ? 'success' : compliancePercent >= 50 ? 'warning' : 'danger'}
370
363
  >
371
364
  {compliancePercent}% token compliance
372
- </span>
365
+ </Badge>
373
366
  )}
374
367
 
375
368
  {/* Match summary */}
376
- <span
377
- className={clsx(
378
- "text-xs font-medium",
379
- differences === 0 ? "text-green-600" : "text-amber-600"
380
- )}
381
- >
369
+ <Badge variant={differences === 0 ? 'success' : 'warning'}>
382
370
  {differences === 0 ? "All styles match" : `${differences} difference${differences !== 1 ? "s" : ""}`}
383
- </span>
371
+ </Badge>
384
372
 
385
373
  {/* Hardcoded warning */}
386
374
  {hardcodedCount > 0 && (
387
- <span className="text-xs font-medium text-red-600">
375
+ <Badge variant="danger">
388
376
  {hardcodedCount} hardcoded
389
- </span>
377
+ </Badge>
390
378
  )}
391
379
  </div>
392
380
  </div>
393
381
 
394
382
  {/* Comparison Table */}
395
- <table className="w-full text-xs">
383
+ <table style={{ width: '100%', fontSize: '12px' }}>
396
384
  <thead>
397
- <tr className="border-b border-[--border-subtle]">
398
- <th className="px-3 py-2 text-left text-tertiary font-medium">Property</th>
399
- <th className="px-3 py-2 text-left text-tertiary font-medium">Figma</th>
385
+ <tr style={{ borderBottom: '1px solid var(--border)' }}>
386
+ <th style={{ padding: '8px 12px', textAlign: 'left', color: 'var(--text-tertiary)', fontWeight: 500 }}>Property</th>
387
+ <th style={{ padding: '8px 12px', textAlign: 'left', color: 'var(--text-tertiary)', fontWeight: 500 }}>Figma</th>
400
388
  {tokenData && (
401
- <th className="px-3 py-2 text-left text-tertiary font-medium">Token</th>
389
+ <th style={{ padding: '8px 12px', textAlign: 'left', color: 'var(--text-tertiary)', fontWeight: 500 }}>Token</th>
402
390
  )}
403
- <th className="px-3 py-2 text-left text-tertiary font-medium">Rendered</th>
404
- <th className="px-3 py-2 text-center text-tertiary font-medium w-12">Match</th>
391
+ <th style={{ padding: '8px 12px', textAlign: 'left', color: 'var(--text-tertiary)', fontWeight: 500 }}>Rendered</th>
392
+ <th style={{ padding: '8px 12px', textAlign: 'center', color: 'var(--text-tertiary)', fontWeight: 500, width: '48px' }}>Match</th>
405
393
  {tokenData && fixableCount > 0 && (
406
- <th className="px-3 py-2 text-center text-tertiary font-medium w-16">Fix</th>
394
+ <th style={{ padding: '8px 12px', textAlign: 'center', color: 'var(--text-tertiary)', fontWeight: 500, width: '64px' }}>Fix</th>
407
395
  )}
408
396
  </tr>
409
397
  </thead>
410
398
  <tbody>
411
- {properties.map((prop) => (
399
+ {properties.map((prop, index) => (
412
400
  <tr
413
401
  key={prop.property}
414
- className={clsx(
415
- "border-b border-[--border-subtle] last:border-b-0",
416
- !prop.match && "bg-amber-50 dark:bg-amber-950/20",
417
- prop.isHardcoded && "bg-red-50 dark:bg-red-950/20"
418
- )}
402
+ style={{
403
+ borderBottom: index < properties.length - 1 ? '1px solid var(--border)' : undefined,
404
+ background: prop.isHardcoded
405
+ ? 'color-mix(in srgb, #ef4444 5%, transparent)'
406
+ : !prop.match
407
+ ? 'color-mix(in srgb, #f59e0b 5%, transparent)'
408
+ : undefined,
409
+ }}
419
410
  >
420
- <td className="px-3 py-2 font-mono text-primary">{prop.property}</td>
421
- <td className="px-3 py-2">
422
- <div className="flex items-center gap-2">
411
+ <td style={{ padding: '8px 12px', fontFamily: 'monospace', color: 'var(--text-primary)' }}>{prop.property}</td>
412
+ <td style={{ padding: '8px 12px' }}>
413
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
423
414
  {/* Color swatch */}
424
415
  {isColorProperty(prop.property) && prop.figma !== "(not set)" && (
425
416
  <ColorSwatch color={prop.figma} />
426
417
  )}
427
- <span className="font-mono text-secondary truncate max-w-[120px]" title={prop.figma}>
418
+ <span style={{ fontFamily: 'monospace', color: 'var(--text-secondary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '120px' }} title={prop.figma}>
428
419
  {prop.figma}
429
420
  </span>
430
421
  </div>
431
422
  </td>
432
423
  {tokenData && (
433
- <td className="px-3 py-2">
424
+ <td style={{ padding: '8px 12px' }}>
434
425
  {prop.figmaToken ? (
435
426
  <TokenBadge token={prop.figmaToken} confidence={prop.figmaConfidence} />
436
427
  ) : prop.renderedToken ? (
437
428
  <TokenBadge token={prop.renderedToken} confidence={prop.renderedConfidence} />
438
429
  ) : (
439
- <span className="text-tertiary">-</span>
430
+ <span style={{ color: 'var(--text-tertiary)' }}>-</span>
440
431
  )}
441
432
  </td>
442
433
  )}
443
- <td className="px-3 py-2">
444
- <div className="flex items-center gap-2">
434
+ <td style={{ padding: '8px 12px' }}>
435
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
445
436
  {/* Color swatch */}
446
437
  {isColorProperty(prop.property) && prop.rendered !== "(not set)" && (
447
438
  <ColorSwatch color={prop.rendered} />
448
439
  )}
449
- <span className="font-mono text-secondary truncate max-w-[120px]" title={prop.rendered}>
440
+ <span style={{ fontFamily: 'monospace', color: 'var(--text-secondary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '120px' }} title={prop.rendered}>
450
441
  {prop.rendered}
451
442
  </span>
452
443
  {/* Hardcoded badge */}
453
444
  {prop.isHardcoded && (
454
- <span className="text-[10px] px-1 py-0.5 bg-red-100 text-red-600 dark:bg-red-900 dark:text-red-300 rounded">
455
- HC
456
- </span>
445
+ <Badge variant="danger">HC</Badge>
457
446
  )}
458
447
  </div>
459
448
  </td>
460
- <td className="px-3 py-2 text-center">
449
+ <td style={{ padding: '8px 12px', textAlign: 'center' }}>
461
450
  {prop.match ? (
462
- <CheckIcon className="w-4 h-4 text-green-600 mx-auto" />
451
+ <CheckIcon style={{ width: 16, height: 16, color: '#16a34a', margin: '0 auto' }} />
463
452
  ) : (
464
- <XIcon className="w-4 h-4 text-amber-600 mx-auto" />
453
+ <XIcon style={{ width: 16, height: 16, color: '#d97706', margin: '0 auto' }} />
465
454
  )}
466
455
  </td>
467
456
  {tokenData && fixableCount > 0 && (
468
- <td className="px-3 py-2 text-center">
457
+ <td style={{ padding: '8px 12px', textAlign: 'center' }}>
469
458
  {prop.isHardcoded && prop.figmaToken && (
470
459
  <button
471
460
  onClick={() => copyFix(prop.property, prop.figmaToken!.name)}
472
- className={clsx(
473
- "p-1 rounded transition-colors",
474
- copiedFix === prop.property
475
- ? "bg-green-100 text-green-600"
476
- : "hover:bg-[--bg-hover] text-tertiary hover:text-primary"
477
- )}
461
+ style={{
462
+ padding: '4px',
463
+ borderRadius: '4px',
464
+ transition: 'color 0.15s, background 0.15s',
465
+ background: copiedFix === prop.property ? 'color-mix(in srgb, #22c55e 15%, transparent)' : 'transparent',
466
+ color: copiedFix === prop.property ? '#16a34a' : 'var(--text-tertiary)',
467
+ border: 'none',
468
+ cursor: 'pointer',
469
+ }}
478
470
  title={`Copy: ${prop.property.replace(/([A-Z])/g, "-$1").toLowerCase()}: var(${prop.figmaToken.name});`}
479
471
  >
480
472
  {copiedFix === prop.property ? (
481
- <CheckIcon className="w-3 h-3" />
473
+ <CheckIcon style={{ width: 12, height: 12 }} />
482
474
  ) : (
483
- <WandIcon className="w-3 h-3" />
475
+ <WandIcon style={{ width: 12, height: 12 }} />
484
476
  )}
485
477
  </button>
486
478
  )}
@@ -493,14 +485,14 @@ export function TokenStylePanel({
493
485
 
494
486
  {/* Hardcoded fixes summary */}
495
487
  {hardcodedCount > 0 && tokenData && (
496
- <div className="mt-4 p-3 bg-amber-50 dark:bg-amber-950/30 rounded-lg border border-amber-200 dark:border-amber-800">
497
- <div className="flex items-start gap-2">
498
- <WandIcon className="w-4 h-4 text-amber-600 mt-0.5" />
488
+ <div style={{ marginTop: '16px', padding: '12px', background: 'color-mix(in srgb, #f59e0b 8%, transparent)', borderRadius: '8px', border: '1px solid color-mix(in srgb, #f59e0b 20%, transparent)' }}>
489
+ <div style={{ display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
490
+ <WandIcon style={{ width: 16, height: 16, color: '#d97706', marginTop: '2px' }} />
499
491
  <div>
500
- <p className="text-xs font-medium text-amber-800 dark:text-amber-200">
492
+ <p style={{ fontSize: '12px', fontWeight: 500, color: '#92400e' }}>
501
493
  {hardcodedCount} hardcoded value{hardcodedCount !== 1 ? "s" : ""} detected
502
494
  </p>
503
- <p className="text-xs text-amber-700 dark:text-amber-300 mt-1">
495
+ <p style={{ fontSize: '12px', color: '#a16207', marginTop: '4px' }}>
504
496
  These values should use design tokens for consistency and theming support.
505
497
  Click the fix button to copy the token-based CSS.
506
498
  </p>
@@ -526,15 +518,22 @@ function TokenBadge({
526
518
  }) {
527
519
  const [showTooltip, setShowTooltip] = useState(false);
528
520
 
521
+ const isValueOnly = confidence === "value-only";
522
+
529
523
  return (
530
- <div className="relative inline-block">
524
+ <div style={{ position: 'relative', display: 'inline-block' }}>
531
525
  <span
532
- className={clsx(
533
- "font-mono text-xs cursor-help px-1.5 py-0.5 rounded",
534
- confidence === "value-only"
535
- ? "text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-950/30"
536
- : "text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-950/30"
537
- )}
526
+ style={{
527
+ fontFamily: 'monospace',
528
+ fontSize: '12px',
529
+ cursor: 'help',
530
+ padding: '2px 6px',
531
+ borderRadius: '4px',
532
+ color: isValueOnly ? '#d97706' : 'var(--color-accent)',
533
+ background: isValueOnly
534
+ ? 'color-mix(in srgb, #f59e0b 8%, transparent)'
535
+ : 'color-mix(in srgb, var(--color-accent) 8%, transparent)',
536
+ }}
538
537
  onMouseEnter={() => setShowTooltip(true)}
539
538
  onMouseLeave={() => setShowTooltip(false)}
540
539
  >
@@ -544,20 +543,32 @@ function TokenBadge({
544
543
  {/* Enhanced tooltip */}
545
544
  {showTooltip && (
546
545
  <div
547
- className="absolute z-50 left-0 top-full mt-1 p-3 bg-[--bg-primary] border border-[--border] rounded-lg shadow-lg min-w-[280px]"
548
- style={{ maxWidth: "320px" }}
546
+ style={{
547
+ position: 'absolute',
548
+ zIndex: 50,
549
+ left: 0,
550
+ top: '100%',
551
+ marginTop: '4px',
552
+ padding: '12px',
553
+ background: 'var(--bg-primary)',
554
+ border: '1px solid var(--border)',
555
+ borderRadius: '8px',
556
+ boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
557
+ minWidth: '280px',
558
+ maxWidth: '320px',
559
+ }}
549
560
  >
550
- <div className="space-y-2 text-xs">
561
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', fontSize: '12px' }}>
551
562
  {/* Token name */}
552
563
  <div>
553
- <span className="text-tertiary">Token:</span>
554
- <span className="ml-2 font-mono text-primary font-medium">{token.name}</span>
564
+ <span style={{ color: 'var(--text-tertiary)' }}>Token:</span>
565
+ <span style={{ marginLeft: '8px', fontFamily: 'monospace', color: 'var(--text-primary)', fontWeight: 500 }}>{token.name}</span>
555
566
  </div>
556
567
 
557
568
  {/* Resolved value */}
558
- <div className="flex items-center">
559
- <span className="text-tertiary">Value:</span>
560
- <span className="ml-2 font-mono text-secondary">{token.resolvedValue}</span>
569
+ <div style={{ display: 'flex', alignItems: 'center' }}>
570
+ <span style={{ color: 'var(--text-tertiary)' }}>Value:</span>
571
+ <span style={{ marginLeft: '8px', fontFamily: 'monospace', color: 'var(--text-secondary)' }}>{token.resolvedValue}</span>
561
572
  {token.category === "color" && (
562
573
  <ColorSwatch color={token.resolvedValue} />
563
574
  )}
@@ -566,20 +577,20 @@ function TokenBadge({
566
577
  {/* Raw value (if different from resolved) */}
567
578
  {token.rawValue !== token.resolvedValue && (
568
579
  <div>
569
- <span className="text-tertiary">Raw:</span>
570
- <span className="ml-2 font-mono text-secondary">{token.rawValue}</span>
580
+ <span style={{ color: 'var(--text-tertiary)' }}>Raw:</span>
581
+ <span style={{ marginLeft: '8px', fontFamily: 'monospace', color: 'var(--text-secondary)' }}>{token.rawValue}</span>
571
582
  </div>
572
583
  )}
573
584
 
574
585
  {/* Category & Level */}
575
- <div className="flex gap-4">
586
+ <div style={{ display: 'flex', gap: '16px' }}>
576
587
  <div>
577
- <span className="text-tertiary">Category:</span>
578
- <span className="ml-2 text-secondary capitalize">{token.category}</span>
588
+ <span style={{ color: 'var(--text-tertiary)' }}>Category:</span>
589
+ <span style={{ marginLeft: '8px', color: 'var(--text-secondary)', textTransform: 'capitalize' }}>{token.category}</span>
579
590
  </div>
580
591
  <div>
581
- <span className="text-tertiary">Level:</span>
582
- <span className="ml-2 text-secondary">
592
+ <span style={{ color: 'var(--text-tertiary)' }}>Level:</span>
593
+ <span style={{ marginLeft: '8px', color: 'var(--text-secondary)' }}>
583
594
  {token.level === 1 ? "Base" : token.level === 2 ? "Semantic" : "Component"}
584
595
  </span>
585
596
  </div>
@@ -587,18 +598,18 @@ function TokenBadge({
587
598
 
588
599
  {/* Theme */}
589
600
  <div>
590
- <span className="text-tertiary">Theme:</span>
591
- <span className="ml-2 text-secondary">{token.theme}</span>
601
+ <span style={{ color: 'var(--text-tertiary)' }}>Theme:</span>
602
+ <span style={{ marginLeft: '8px', color: 'var(--text-secondary)' }}>{token.theme}</span>
592
603
  </div>
593
604
 
594
605
  {/* Reference chain (if has references) */}
595
606
  {token.referenceChain.length > 1 && (
596
607
  <div>
597
- <span className="text-tertiary">References:</span>
598
- <div className="mt-1 font-mono text-secondary text-[10px] space-y-0.5">
608
+ <span style={{ color: 'var(--text-tertiary)' }}>References:</span>
609
+ <div style={{ marginTop: '4px', fontFamily: 'monospace', color: 'var(--text-secondary)', fontSize: '10px', display: 'flex', flexDirection: 'column', gap: '2px' }}>
599
610
  {token.referenceChain.map((ref, i) => (
600
- <div key={ref} className="flex items-center">
601
- {i > 0 && <span className="mr-1 text-tertiary">→</span>}
611
+ <div key={ref} style={{ display: 'flex', alignItems: 'center' }}>
612
+ {i > 0 && <span style={{ marginRight: '4px', color: 'var(--text-tertiary)' }}>&rarr;</span>}
602
613
  <span>{ref}</span>
603
614
  </div>
604
615
  ))}
@@ -607,9 +618,9 @@ function TokenBadge({
607
618
  )}
608
619
 
609
620
  {/* Source file */}
610
- <div className="pt-1 border-t border-[--border-subtle]">
611
- <span className="text-tertiary">Source:</span>
612
- <span className="ml-2 font-mono text-[10px] text-tertiary truncate">
621
+ <div style={{ paddingTop: '4px', borderTop: '1px solid var(--border)' }}>
622
+ <span style={{ color: 'var(--text-tertiary)' }}>Source:</span>
623
+ <span style={{ marginLeft: '8px', fontFamily: 'monospace', fontSize: '10px', color: 'var(--text-tertiary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
613
624
  {token.sourceFile.split("/").slice(-2).join("/")}
614
625
  {token.lineNumber && `:${token.lineNumber}`}
615
626
  </span>
@@ -617,8 +628,8 @@ function TokenBadge({
617
628
 
618
629
  {/* Confidence indicator */}
619
630
  {confidence === "value-only" && (
620
- <div className="pt-1 text-amber-600 dark:text-amber-400">
621
- ⚠️ Value match only - verify this is the correct token
631
+ <div style={{ paddingTop: '4px', color: '#d97706' }}>
632
+ Warning: Value match only - verify this is the correct token
622
633
  </div>
623
634
  )}
624
635
  </div>
@@ -631,8 +642,15 @@ function TokenBadge({
631
642
  function ColorSwatch({ color }: { color: string }) {
632
643
  return (
633
644
  <div
634
- className="w-4 h-4 rounded border border-[--border] flex-shrink-0 ml-1"
635
- style={{ backgroundColor: color }}
645
+ style={{
646
+ width: '16px',
647
+ height: '16px',
648
+ borderRadius: '4px',
649
+ border: '1px solid var(--border)',
650
+ flexShrink: 0,
651
+ marginLeft: '4px',
652
+ backgroundColor: color,
653
+ }}
636
654
  title={color}
637
655
  />
638
656
  );
@@ -16,22 +16,22 @@ export function UsageSection({ usage }: UsageSectionProps) {
16
16
  }
17
17
 
18
18
  return (
19
- <section id="usage" className="scroll-mt-24">
20
- <h2 className="text-base font-semibold text-primary mb-5">Usage</h2>
19
+ <section id="usage" style={{ scrollMarginTop: '96px' }}>
20
+ <h2 style={{ fontSize: '16px', fontWeight: 600, color: 'var(--text-primary)', marginBottom: '20px' }}>Usage</h2>
21
21
 
22
22
  {/* When to use / When not to use */}
23
23
  {(hasWhen || hasWhenNot) && (
24
- <div className="grid md:grid-cols-2 gap-8 mb-8">
24
+ <div style={{ display: 'grid', gridTemplateColumns: hasWhen && hasWhenNot ? '1fr 1fr' : '1fr', gap: '32px', marginBottom: '32px' }}>
25
25
  {hasWhen && (
26
- <div className="p-4 rounded-xl bg-[--color-success-bg] border border-[--color-success]/20">
27
- <h3 className="text-[13px] font-medium text-[--color-success] mb-3 flex items-center gap-2">
28
- <CheckIcon className="w-4 h-4" />
26
+ <div style={{ padding: '16px', borderRadius: '12px', background: 'var(--color-success-bg)', border: '1px solid rgba(16, 163, 127, 0.2)' }}>
27
+ <h3 style={{ fontSize: '13px', fontWeight: 500, color: 'var(--color-success)', marginBottom: '12px', display: 'flex', alignItems: 'center', gap: '8px' }}>
28
+ <CheckIcon style={{ width: '16px', height: '16px' }} />
29
29
  When to use
30
30
  </h3>
31
- <ul className="space-y-2">
31
+ <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '8px' }}>
32
32
  {usage.when!.map((item, index) => (
33
- <li key={index} className="text-[13px] text-primary leading-relaxed flex items-start gap-2">
34
- <span className="text-[--color-success] mt-1.5 text-xs">•</span>
33
+ <li key={index} style={{ fontSize: '13px', color: 'var(--text-primary)', lineHeight: 1.6, display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
34
+ <span style={{ color: 'var(--color-success)', marginTop: '6px', fontSize: '12px' }}>&#8226;</span>
35
35
  <span>{item}</span>
36
36
  </li>
37
37
  ))}
@@ -40,15 +40,15 @@ export function UsageSection({ usage }: UsageSectionProps) {
40
40
  )}
41
41
 
42
42
  {hasWhenNot && (
43
- <div className="p-4 rounded-xl bg-[--color-danger-bg] border border-[--color-danger]/20">
44
- <h3 className="text-[13px] font-medium text-[--color-danger] mb-3 flex items-center gap-2">
45
- <XIcon className="w-4 h-4" />
43
+ <div style={{ padding: '16px', borderRadius: '12px', background: 'var(--color-danger-bg)', border: '1px solid rgba(239, 68, 68, 0.2)' }}>
44
+ <h3 style={{ fontSize: '13px', fontWeight: 500, color: 'var(--color-danger)', marginBottom: '12px', display: 'flex', alignItems: 'center', gap: '8px' }}>
45
+ <XIcon style={{ width: '16px', height: '16px' }} />
46
46
  When not to use
47
47
  </h3>
48
- <ul className="space-y-2">
48
+ <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '8px' }}>
49
49
  {usage.whenNot!.map((item, index) => (
50
- <li key={index} className="text-[13px] text-primary leading-relaxed flex items-start gap-2">
51
- <span className="text-[--color-danger] mt-1.5 text-xs">•</span>
50
+ <li key={index} style={{ fontSize: '13px', color: 'var(--text-primary)', lineHeight: 1.6, display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
51
+ <span style={{ color: 'var(--color-danger)', marginTop: '6px', fontSize: '12px' }}>&#8226;</span>
52
52
  <span>{item}</span>
53
53
  </li>
54
54
  ))}
@@ -60,12 +60,12 @@ export function UsageSection({ usage }: UsageSectionProps) {
60
60
 
61
61
  {/* Guidelines */}
62
62
  {hasGuidelines && (
63
- <div className="mb-6">
64
- <h3 className="text-[13px] font-medium text-primary mb-3">Guidelines</h3>
65
- <ul className="space-y-2">
63
+ <div style={{ marginBottom: '24px' }}>
64
+ <h3 style={{ fontSize: '13px', fontWeight: 500, color: 'var(--text-primary)', marginBottom: '12px' }}>Guidelines</h3>
65
+ <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '8px' }}>
66
66
  {usage.guidelines!.map((item, index) => (
67
- <li key={index} className="text-[13px] text-secondary leading-relaxed flex items-start gap-2">
68
- <span className="text-[--color-accent] mt-1.5 text-xs">•</span>
67
+ <li key={index} style={{ fontSize: '13px', color: 'var(--text-secondary)', lineHeight: 1.6, display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
68
+ <span style={{ color: 'var(--color-accent)', marginTop: '6px', fontSize: '12px' }}>&#8226;</span>
69
69
  <span>{item}</span>
70
70
  </li>
71
71
  ))}
@@ -75,15 +75,15 @@ export function UsageSection({ usage }: UsageSectionProps) {
75
75
 
76
76
  {/* Accessibility */}
77
77
  {hasAccessibility && (
78
- <div className="p-4 rounded-xl border border-[--border] bg-[--bg-secondary]">
79
- <h3 className="text-[13px] font-medium text-primary mb-3 flex items-center gap-2">
80
- <AccessibilityIcon className="w-4 h-4 text-secondary" />
78
+ <div style={{ padding: '16px', borderRadius: '12px', border: '1px solid var(--border)', background: 'var(--bg-secondary)' }}>
79
+ <h3 style={{ fontSize: '13px', fontWeight: 500, color: 'var(--text-primary)', marginBottom: '12px', display: 'flex', alignItems: 'center', gap: '8px' }}>
80
+ <AccessibilityIcon style={{ width: '16px', height: '16px', color: 'var(--text-secondary)' }} />
81
81
  Accessibility
82
82
  </h3>
83
- <ul className="space-y-2">
83
+ <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: '8px' }}>
84
84
  {usage.accessibility!.map((item, index) => (
85
- <li key={index} className="text-[13px] text-secondary leading-relaxed flex items-start gap-2">
86
- <span className="text-tertiary mt-1.5 text-xs">•</span>
85
+ <li key={index} style={{ fontSize: '13px', color: 'var(--text-secondary)', lineHeight: 1.6, display: 'flex', alignItems: 'flex-start', gap: '8px' }}>
86
+ <span style={{ color: 'var(--text-tertiary)', marginTop: '6px', fontSize: '12px' }}>&#8226;</span>
87
87
  <span>{item}</span>
88
88
  </li>
89
89
  ))}