@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
@@ -70,6 +70,8 @@ export function MultiViewportPreview({
70
70
  }: MultiViewportPreviewProps) {
71
71
  const [selectedMobile, setSelectedMobile] = useState<MobilePreset>(MOBILE_PRESETS[0]);
72
72
  const [showMobileDropdown, setShowMobileDropdown] = useState(false);
73
+ const [hoveredPreset, setHoveredPreset] = useState<string | null>(null);
74
+ const [mobileButtonHovered, setMobileButtonHovered] = useState(false);
73
75
 
74
76
  // Build viewports with selected mobile preset
75
77
  const viewports: ViewportConfig[] = [
@@ -79,28 +81,72 @@ export function MultiViewportPreview({
79
81
  ];
80
82
 
81
83
  return (
82
- <div className="h-full flex flex-col bg-gray-100 dark:bg-gray-900">
84
+ <div style={{
85
+ height: '100%',
86
+ display: 'flex',
87
+ flexDirection: 'column',
88
+ background: 'var(--bg-primary)',
89
+ }}>
83
90
  {/* Header */}
84
- <div className="flex-shrink-0 px-4 py-3 border-b border-[--border] bg-[--bg-secondary] flex items-center justify-center gap-8">
91
+ <div style={{
92
+ flexShrink: 0,
93
+ padding: '12px 16px',
94
+ borderBottom: '1px solid var(--border)',
95
+ background: 'var(--bg-secondary)',
96
+ display: 'flex',
97
+ alignItems: 'center',
98
+ justifyContent: 'center',
99
+ gap: 32,
100
+ }}>
85
101
  {/* Mobile with dropdown */}
86
- <div className="relative">
102
+ <div style={{ position: 'relative' }}>
87
103
  <button
88
104
  onClick={() => setShowMobileDropdown(!showMobileDropdown)}
89
- className="flex items-center gap-2 text-sm hover:bg-[--bg-hover] px-2 py-1 rounded transition-colors"
105
+ onMouseEnter={() => setMobileButtonHovered(true)}
106
+ onMouseLeave={() => setMobileButtonHovered(false)}
107
+ style={{
108
+ display: 'flex',
109
+ alignItems: 'center',
110
+ gap: 8,
111
+ fontSize: 14,
112
+ padding: '4px 8px',
113
+ borderRadius: 4,
114
+ transition: 'background-color 0.15s',
115
+ background: mobileButtonHovered ? 'var(--bg-hover)' : 'transparent',
116
+ border: 'none',
117
+ cursor: 'pointer',
118
+ color: 'inherit',
119
+ }}
90
120
  >
91
- <span className="text-lg">📱</span>
92
- <span className="font-medium text-secondary">Mobile</span>
93
- <span className="text-xs text-tertiary">({selectedMobile.width}px)</span>
94
- <ChevronDownIcon className="w-3 h-3 text-tertiary" />
121
+ <span style={{ fontSize: 18 }}>📱</span>
122
+ <span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Mobile</span>
123
+ <span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>({selectedMobile.width}px)</span>
124
+ <ChevronDownIcon style={{ width: 12, height: 12, color: 'var(--text-tertiary)' }} />
95
125
  </button>
96
126
 
97
127
  {showMobileDropdown && (
98
128
  <>
99
129
  <div
100
- className="fixed inset-0 z-10"
130
+ style={{
131
+ position: 'fixed',
132
+ inset: 0,
133
+ zIndex: 10,
134
+ }}
101
135
  onClick={() => setShowMobileDropdown(false)}
102
136
  />
103
- <div className="absolute top-full left-0 mt-1 z-20 bg-[--bg-elevated] border border-[--border] rounded-lg shadow-lg py-1 min-w-[180px]">
137
+ <div style={{
138
+ position: 'absolute',
139
+ top: '100%',
140
+ left: 0,
141
+ marginTop: 4,
142
+ zIndex: 20,
143
+ background: 'var(--bg-elevated)',
144
+ border: '1px solid var(--border)',
145
+ borderRadius: 8,
146
+ boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
147
+ padding: '4px 0',
148
+ minWidth: 180,
149
+ }}>
104
150
  {MOBILE_PRESETS.map((preset) => (
105
151
  <button
106
152
  key={preset.name}
@@ -108,12 +154,25 @@ export function MultiViewportPreview({
108
154
  setSelectedMobile(preset);
109
155
  setShowMobileDropdown(false);
110
156
  }}
111
- className={`w-full px-3 py-1.5 text-left text-xs hover:bg-[--bg-hover] transition-colors flex items-center justify-between ${
112
- selectedMobile.name === preset.name ? 'text-blue-500' : 'text-secondary'
113
- }`}
157
+ onMouseEnter={() => setHoveredPreset(preset.name)}
158
+ onMouseLeave={() => setHoveredPreset(null)}
159
+ style={{
160
+ width: '100%',
161
+ padding: '6px 12px',
162
+ textAlign: 'left',
163
+ fontSize: 12,
164
+ transition: 'background-color 0.15s',
165
+ display: 'flex',
166
+ alignItems: 'center',
167
+ justifyContent: 'space-between',
168
+ color: selectedMobile.name === preset.name ? '#3b82f6' : 'var(--text-secondary)',
169
+ background: hoveredPreset === preset.name ? 'var(--bg-hover)' : 'transparent',
170
+ border: 'none',
171
+ cursor: 'pointer',
172
+ }}
114
173
  >
115
174
  <span>{preset.name}</span>
116
- <span className="text-tertiary">{preset.width}×{preset.height}</span>
175
+ <span style={{ color: 'var(--text-tertiary)' }}>{preset.width}×{preset.height}</span>
117
176
  </button>
118
177
  ))}
119
178
  </div>
@@ -122,23 +181,23 @@ export function MultiViewportPreview({
122
181
  </div>
123
182
 
124
183
  {/* Tablet */}
125
- <div className="flex items-center gap-2 text-sm">
126
- <span className="text-lg">📱</span>
127
- <span className="font-medium text-secondary">Tablet</span>
128
- <span className="text-xs text-tertiary">(768px)</span>
184
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14 }}>
185
+ <span style={{ fontSize: 18 }}>📱</span>
186
+ <span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Tablet</span>
187
+ <span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>(768px)</span>
129
188
  </div>
130
189
 
131
190
  {/* Desktop */}
132
- <div className="flex items-center gap-2 text-sm">
133
- <span className="text-lg">🖥️</span>
134
- <span className="font-medium text-secondary">Desktop</span>
135
- <span className="text-xs text-tertiary">(1280px)</span>
191
+ <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 14 }}>
192
+ <span style={{ fontSize: 18 }}>🖥️</span>
193
+ <span style={{ fontWeight: 500, color: 'var(--text-secondary)' }}>Desktop</span>
194
+ <span style={{ fontSize: 12, color: 'var(--text-tertiary)' }}>(1280px)</span>
136
195
  </div>
137
196
  </div>
138
197
 
139
198
  {/* Viewport panels with horizontal scroll */}
140
- <div className="flex-1 overflow-x-auto overflow-y-auto">
141
- <div className="flex gap-8 p-8 min-w-max">
199
+ <div style={{ flex: 1, overflowX: 'auto', overflowY: 'auto' }}>
200
+ <div style={{ display: 'flex', gap: 32, padding: 32, minWidth: 'max-content' }}>
142
201
  {viewports.map((vp) => (
143
202
  <ViewportPanel
144
203
  key={`${vp.name}-${vp.width}`}
@@ -246,51 +305,124 @@ function DeviceMockup({
246
305
  const backgroundStyle = getBackgroundStyle(background);
247
306
 
248
307
  return (
249
- <div className="flex flex-col items-center">
308
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
250
309
  {/* Label */}
251
- <div className="mb-3 text-sm font-medium text-tertiary">
310
+ <div style={{
311
+ marginBottom: 12,
312
+ fontSize: 14,
313
+ fontWeight: 500,
314
+ color: 'var(--text-tertiary)',
315
+ }}>
252
316
  {label}
253
317
  </div>
254
318
 
255
319
  {/* Device frame */}
256
320
  <div
257
- className="relative flex-shrink-0"
258
- style={{ width: `${frameWidth}px` }}
321
+ style={{
322
+ position: 'relative',
323
+ flexShrink: 0,
324
+ width: `${frameWidth}px`,
325
+ }}
259
326
  >
260
327
  <div
261
- className="relative rounded-[40px] bg-[#1a1a1a] p-3 shadow-2xl"
262
328
  style={{
263
- boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)",
329
+ position: 'relative',
330
+ borderRadius: 40,
331
+ background: '#1a1a1a',
332
+ padding: 12,
333
+ boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)',
264
334
  }}
265
335
  >
266
336
  {/* Side buttons (mobile only) */}
267
337
  {isMobile && (
268
338
  <>
269
- <div className="absolute -left-[3px] top-24 w-[3px] h-8 bg-[#2a2a2a] rounded-l" />
270
- <div className="absolute -left-[3px] top-36 w-[3px] h-12 bg-[#2a2a2a] rounded-l" />
271
- <div className="absolute -left-[3px] top-52 w-[3px] h-12 bg-[#2a2a2a] rounded-l" />
272
- <div className="absolute -right-[3px] top-32 w-[3px] h-16 bg-[#2a2a2a] rounded-r" />
339
+ <div style={{
340
+ position: 'absolute',
341
+ left: -3,
342
+ top: 96,
343
+ width: 3,
344
+ height: 32,
345
+ background: '#2a2a2a',
346
+ borderRadius: '4px 0 0 4px',
347
+ }} />
348
+ <div style={{
349
+ position: 'absolute',
350
+ left: -3,
351
+ top: 144,
352
+ width: 3,
353
+ height: 48,
354
+ background: '#2a2a2a',
355
+ borderRadius: '4px 0 0 4px',
356
+ }} />
357
+ <div style={{
358
+ position: 'absolute',
359
+ left: -3,
360
+ top: 208,
361
+ width: 3,
362
+ height: 48,
363
+ background: '#2a2a2a',
364
+ borderRadius: '4px 0 0 4px',
365
+ }} />
366
+ <div style={{
367
+ position: 'absolute',
368
+ right: -3,
369
+ top: 128,
370
+ width: 3,
371
+ height: 64,
372
+ background: '#2a2a2a',
373
+ borderRadius: '0 4px 4px 0',
374
+ }} />
273
375
  </>
274
376
  )}
275
377
 
276
378
  {/* Screen container */}
277
379
  <div
278
- className="relative rounded-[32px] overflow-hidden bg-white"
279
- style={{ height: `${screenHeight}px`, width: `${width}px` }}
380
+ style={{
381
+ position: 'relative',
382
+ borderRadius: 32,
383
+ overflow: 'hidden',
384
+ background: '#ffffff',
385
+ height: `${screenHeight}px`,
386
+ width: `${width}px`,
387
+ }}
280
388
  >
281
389
  {/* Notch (mobile) or Camera (tablet) */}
282
390
  {isMobile ? (
283
- <div className="absolute top-0 left-1/2 -translate-x-1/2 w-[120px] h-[30px] bg-[#1a1a1a] rounded-b-2xl z-10 flex items-center justify-center gap-2">
284
- <div className="w-2 h-2 rounded-full bg-[#2a2a2a]" />
285
- <div className="w-12 h-1.5 rounded-full bg-[#2a2a2a]" />
391
+ <div style={{
392
+ position: 'absolute',
393
+ top: 0,
394
+ left: '50%',
395
+ transform: 'translateX(-50%)',
396
+ width: 120,
397
+ height: 30,
398
+ background: '#1a1a1a',
399
+ borderRadius: '0 0 16px 16px',
400
+ zIndex: 10,
401
+ display: 'flex',
402
+ alignItems: 'center',
403
+ justifyContent: 'center',
404
+ gap: 8,
405
+ }}>
406
+ <div style={{ width: 8, height: 8, borderRadius: '50%', background: '#2a2a2a' }} />
407
+ <div style={{ width: 48, height: 6, borderRadius: 9999, background: '#2a2a2a' }} />
286
408
  </div>
287
409
  ) : (
288
- <div className="absolute top-2 left-1/2 -translate-x-1/2 w-3 h-3 rounded-full bg-[#2a2a2a] z-10" />
410
+ <div style={{
411
+ position: 'absolute',
412
+ top: 8,
413
+ left: '50%',
414
+ transform: 'translateX(-50%)',
415
+ width: 12,
416
+ height: 12,
417
+ borderRadius: '50%',
418
+ background: '#2a2a2a',
419
+ zIndex: 10,
420
+ }} />
289
421
  )}
290
422
 
291
423
  {/* Screen content */}
292
424
  <div
293
- className="w-full h-full overflow-hidden"
425
+ style={{ width: '100%', height: '100%', overflow: 'hidden' }}
294
426
  data-theme={previewTheme}
295
427
  >
296
428
  {useIframeIsolation ? (
@@ -303,11 +435,16 @@ function DeviceMockup({
303
435
  minHeight={screenHeight}
304
436
  />
305
437
  ) : (
306
- <div className={isMobile ? "pt-10 px-4 pb-4" : "pt-6 px-4 pb-4"}>
438
+ <div style={{
439
+ paddingTop: isMobile ? 40 : 24,
440
+ paddingLeft: 16,
441
+ paddingRight: 16,
442
+ paddingBottom: 16,
443
+ }}>
307
444
  <ErrorBoundary
308
445
  componentName={componentName}
309
446
  fallback={
310
- <div className="text-xs text-red-500 p-2">
447
+ <div style={{ fontSize: 12, color: '#ef4444', padding: 8 }}>
311
448
  Error rendering at {width}px
312
449
  </div>
313
450
  }
@@ -319,7 +456,17 @@ function DeviceMockup({
319
456
  </div>
320
457
 
321
458
  {/* Home indicator */}
322
- <div className="absolute bottom-2 left-1/2 -translate-x-1/2 w-[100px] h-1 bg-black/20 rounded-full z-10" />
459
+ <div style={{
460
+ position: 'absolute',
461
+ bottom: 8,
462
+ left: '50%',
463
+ transform: 'translateX(-50%)',
464
+ width: 100,
465
+ height: 4,
466
+ background: 'rgba(0,0,0,0.2)',
467
+ borderRadius: 9999,
468
+ zIndex: 10,
469
+ }} />
323
470
  </div>
324
471
  </div>
325
472
  </div>
@@ -355,31 +502,60 @@ function DesktopMockup({
355
502
  const backgroundStyle = getBackgroundStyle(background);
356
503
 
357
504
  return (
358
- <div className="flex flex-col items-center">
505
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
359
506
  {/* Label */}
360
- <div className="mb-3 text-sm font-medium text-tertiary">
507
+ <div style={{
508
+ marginBottom: 12,
509
+ fontSize: 14,
510
+ fontWeight: 500,
511
+ color: 'var(--text-tertiary)',
512
+ }}>
361
513
  {label}
362
514
  </div>
363
515
 
364
516
  {/* Monitor frame */}
365
- <div className="flex flex-col items-center">
517
+ <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
366
518
  {/* Screen */}
367
519
  <div
368
- className="relative bg-[#1a1a1a] rounded-lg p-2 shadow-2xl"
369
520
  style={{
370
- boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)",
521
+ position: 'relative',
522
+ background: '#1a1a1a',
523
+ borderRadius: 8,
524
+ padding: 8,
525
+ boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.1)',
371
526
  }}
372
527
  >
373
528
  {/* Browser chrome */}
374
- <div className="flex items-center gap-2 px-3 py-2 bg-[#2a2a2a] rounded-t-md">
375
- <div className="flex items-center gap-1.5">
376
- <div className="w-3 h-3 rounded-full bg-[#ff5f57]" />
377
- <div className="w-3 h-3 rounded-full bg-[#ffbd2e]" />
378
- <div className="w-3 h-3 rounded-full bg-[#28ca41]" />
529
+ <div style={{
530
+ display: 'flex',
531
+ alignItems: 'center',
532
+ gap: 8,
533
+ padding: '8px 12px',
534
+ background: '#2a2a2a',
535
+ borderRadius: '6px 6px 0 0',
536
+ }}>
537
+ <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
538
+ <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ff5f57' }} />
539
+ <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#ffbd2e' }} />
540
+ <div style={{ width: 12, height: 12, borderRadius: '50%', background: '#28ca41' }} />
379
541
  </div>
380
- <div className="flex-1 mx-4">
381
- <div className="h-6 bg-[#3a3a3a] rounded-md flex items-center justify-center px-3">
382
- <span className="text-xs text-gray-400 truncate">
542
+ <div style={{ flex: 1, margin: '0 16px' }}>
543
+ <div style={{
544
+ height: 24,
545
+ background: '#3a3a3a',
546
+ borderRadius: 6,
547
+ display: 'flex',
548
+ alignItems: 'center',
549
+ justifyContent: 'center',
550
+ padding: '0 12px',
551
+ }}>
552
+ <span style={{
553
+ fontSize: 12,
554
+ color: '#9ca3af',
555
+ overflow: 'hidden',
556
+ textOverflow: 'ellipsis',
557
+ whiteSpace: 'nowrap',
558
+ }}>
383
559
  localhost:6006 — {width}px
384
560
  </span>
385
561
  </div>
@@ -388,8 +564,12 @@ function DesktopMockup({
388
564
 
389
565
  {/* Screen content */}
390
566
  <div
391
- className="overflow-hidden"
392
- style={{ width: `${width}px`, height: `${height}px`, ...backgroundStyle }}
567
+ style={{
568
+ overflow: 'hidden',
569
+ width: `${width}px`,
570
+ height: `${height}px`,
571
+ ...backgroundStyle,
572
+ }}
393
573
  data-theme={previewTheme}
394
574
  >
395
575
  {useIframeIsolation ? (
@@ -402,11 +582,11 @@ function DesktopMockup({
402
582
  minHeight={height}
403
583
  />
404
584
  ) : (
405
- <div className="p-6">
585
+ <div style={{ padding: 24 }}>
406
586
  <ErrorBoundary
407
587
  componentName={componentName}
408
588
  fallback={
409
- <div className="text-xs text-red-500 p-2">
589
+ <div style={{ fontSize: 12, color: '#ef4444', padding: 8 }}>
410
590
  Error rendering at {width}px
411
591
  </div>
412
592
  }
@@ -419,8 +599,19 @@ function DesktopMockup({
419
599
  </div>
420
600
 
421
601
  {/* Monitor stand */}
422
- <div className="w-20 h-4 bg-gradient-to-b from-[#2a2a2a] to-[#1a1a1a] rounded-b-sm" />
423
- <div className="w-32 h-2 bg-[#1a1a1a] rounded-full shadow-lg" />
602
+ <div style={{
603
+ width: 80,
604
+ height: 16,
605
+ background: 'linear-gradient(to bottom, #2a2a2a, #1a1a1a)',
606
+ borderRadius: '0 0 2px 2px',
607
+ }} />
608
+ <div style={{
609
+ width: 128,
610
+ height: 8,
611
+ background: '#1a1a1a',
612
+ borderRadius: 9999,
613
+ boxShadow: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)',
614
+ }} />
424
615
  </div>
425
616
  </div>
426
617
  );