@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
@@ -1,7 +1,6 @@
1
1
  import { useState, useCallback } from "react";
2
2
  import { useForm, useFieldArray, Controller } from "react-hook-form";
3
3
  import type { Fragment, FragmentUsage, FragmentMeta } from "../../core/index.js";
4
- import clsx from "clsx";
5
4
  import { ChevronDownIcon } from "./Icons.js";
6
5
 
7
6
  interface FragmentEditorProps {
@@ -39,6 +38,44 @@ interface FormData {
39
38
  };
40
39
  }
41
40
 
41
+ const inputStyle: React.CSSProperties = {
42
+ width: '100%',
43
+ padding: '6px 12px',
44
+ fontSize: '14px',
45
+ background: 'var(--bg-elevated)',
46
+ border: '1px solid var(--border)',
47
+ borderRadius: '8px',
48
+ outline: 'none',
49
+ color: 'var(--text-primary)',
50
+ boxSizing: 'border-box',
51
+ };
52
+
53
+ const labelStyle: React.CSSProperties = {
54
+ display: 'block',
55
+ fontSize: '12px',
56
+ fontWeight: 500,
57
+ color: 'var(--text-secondary)',
58
+ marginBottom: '6px',
59
+ };
60
+
61
+ const removeButtonStyle: React.CSSProperties = {
62
+ padding: '0 8px',
63
+ color: 'var(--text-secondary)',
64
+ background: 'none',
65
+ border: 'none',
66
+ cursor: 'pointer',
67
+ fontSize: '16px',
68
+ };
69
+
70
+ const addButtonStyle: React.CSSProperties = {
71
+ fontSize: '12px',
72
+ color: 'var(--color-accent)',
73
+ background: 'none',
74
+ border: 'none',
75
+ cursor: 'pointer',
76
+ padding: 0,
77
+ };
78
+
42
79
  export function FragmentEditor({
43
80
  componentName,
44
81
  fragment,
@@ -156,27 +193,30 @@ export function FragmentEditor({
156
193
  return (
157
194
  <form
158
195
  onSubmit={handleSubmit(onSubmit)}
159
- className="h-full flex flex-col bg-[--bg-primary]"
196
+ style={{ height: '100%', display: 'flex', flexDirection: 'column', background: 'var(--bg-primary)' }}
160
197
  >
161
198
  {/* Header */}
162
- <div className="px-4 py-3 border-b border-[--border] bg-[--bg-secondary]">
163
- <h3 className="text-sm font-semibold text-primary">Fragment Editor</h3>
164
- <p className="text-xs text-secondary mt-0.5">
199
+ <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--border)', background: 'var(--bg-secondary)' }}>
200
+ <h3 style={{ fontSize: '14px', fontWeight: 600, color: 'var(--text-primary)', margin: 0 }}>Fragment Editor</h3>
201
+ <p style={{ fontSize: '12px', color: 'var(--text-secondary)', marginTop: '2px', marginBottom: 0 }}>
165
202
  Enrich {componentName} with metadata
166
203
  </p>
167
204
  </div>
168
205
 
169
206
  {/* Scrollable content */}
170
- <div className="flex-1 overflow-y-auto">
207
+ <div style={{ flex: 1, overflowY: 'auto' }}>
171
208
  {/* Basic Info */}
172
- <div className="p-4 border-b border-[--border]">
173
- <label className="block text-xs font-medium text-secondary mb-1.5">
209
+ <div style={{ padding: '16px', borderBottom: '1px solid var(--border)' }}>
210
+ <label style={labelStyle}>
174
211
  Description
175
212
  </label>
176
213
  <textarea
177
214
  {...register("description")}
178
215
  rows={3}
179
- className="w-full px-3 py-2 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
216
+ style={{
217
+ ...inputStyle,
218
+ resize: 'none',
219
+ }}
180
220
  placeholder="Brief description of the component's purpose..."
181
221
  />
182
222
  </div>
@@ -188,22 +228,22 @@ export function FragmentEditor({
188
228
  onToggle={() => toggleSection("usage")}
189
229
  >
190
230
  {/* When to Use */}
191
- <div className="mb-4">
192
- <label className="block text-xs font-medium text-secondary mb-2">
231
+ <div style={{ marginBottom: '16px' }}>
232
+ <label style={{ ...labelStyle, marginBottom: '8px' }}>
193
233
  When to Use
194
234
  </label>
195
- <div className="space-y-2">
235
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
196
236
  {whenFields.map((field, index) => (
197
- <div key={field.id} className="flex gap-2">
237
+ <div key={field.id} style={{ display: 'flex', gap: '8px' }}>
198
238
  <input
199
239
  {...register(`usage.when.${index}` as const)}
200
- className="flex-1 px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
240
+ style={{ ...inputStyle, flex: 1 }}
201
241
  placeholder="Scenario..."
202
242
  />
203
243
  <button
204
244
  type="button"
205
245
  onClick={() => removeWhen(index)}
206
- className="px-2 text-secondary hover:text-error"
246
+ style={removeButtonStyle}
207
247
  >
208
248
  &times;
209
249
  </button>
@@ -212,7 +252,7 @@ export function FragmentEditor({
212
252
  <button
213
253
  type="button"
214
254
  onClick={() => appendWhen("")}
215
- className="text-xs text-[--color-accent] hover:underline"
255
+ style={addButtonStyle}
216
256
  >
217
257
  + Add scenario
218
258
  </button>
@@ -221,26 +261,26 @@ export function FragmentEditor({
221
261
 
222
262
  {/* Do Not */}
223
263
  <div>
224
- <label className="block text-xs font-medium text-secondary mb-2">
264
+ <label style={{ ...labelStyle, marginBottom: '8px' }}>
225
265
  Do Not
226
266
  </label>
227
- <div className="space-y-2">
267
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
228
268
  {doNotFields.map((field, index) => (
229
- <div key={field.id} className="flex gap-2">
269
+ <div key={field.id} style={{ display: 'flex', gap: '8px' }}>
230
270
  <input
231
271
  {...register(`usage.doNot.${index}.text` as const)}
232
- className="flex-1 px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
272
+ style={{ ...inputStyle, flex: 1 }}
233
273
  placeholder="What not to do..."
234
274
  />
235
275
  <input
236
276
  {...register(`usage.doNot.${index}.instead` as const)}
237
- className="w-32 px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
277
+ style={{ ...inputStyle, width: '128px' }}
238
278
  placeholder="Instead..."
239
279
  />
240
280
  <button
241
281
  type="button"
242
282
  onClick={() => removeDoNot(index)}
243
- className="px-2 text-secondary hover:text-error"
283
+ style={removeButtonStyle}
244
284
  >
245
285
  &times;
246
286
  </button>
@@ -249,7 +289,7 @@ export function FragmentEditor({
249
289
  <button
250
290
  type="button"
251
291
  onClick={() => appendDoNot({ text: "", instead: "" })}
252
- className="text-xs text-[--color-accent] hover:underline"
292
+ style={addButtonStyle}
253
293
  >
254
294
  + Add anti-pattern
255
295
  </button>
@@ -263,35 +303,35 @@ export function FragmentEditor({
263
303
  expanded={expandedSections.has("accessibility")}
264
304
  onToggle={() => toggleSection("accessibility")}
265
305
  >
266
- <div className="mb-4">
267
- <label className="block text-xs font-medium text-secondary mb-1.5">
306
+ <div style={{ marginBottom: '16px' }}>
307
+ <label style={labelStyle}>
268
308
  ARIA Role
269
309
  </label>
270
310
  <input
271
311
  {...register("accessibility.role")}
272
- className="w-full px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
312
+ style={inputStyle}
273
313
  placeholder="button, dialog, etc."
274
314
  />
275
315
  </div>
276
316
 
277
317
  <div>
278
- <label className="block text-xs font-medium text-secondary mb-2">
318
+ <label style={{ ...labelStyle, marginBottom: '8px' }}>
279
319
  Requirements
280
320
  </label>
281
- <div className="space-y-2">
321
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
282
322
  {requirementsFields.map((field, index) => (
283
- <div key={field.id} className="flex gap-2">
323
+ <div key={field.id} style={{ display: 'flex', gap: '8px' }}>
284
324
  <input
285
325
  {...register(
286
326
  `accessibility.requirements.${index}` as const
287
327
  )}
288
- className="flex-1 px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
328
+ style={{ ...inputStyle, flex: 1 }}
289
329
  placeholder="Requirement..."
290
330
  />
291
331
  <button
292
332
  type="button"
293
333
  onClick={() => removeRequirement(index)}
294
- className="px-2 text-secondary hover:text-error"
334
+ style={removeButtonStyle}
295
335
  >
296
336
  &times;
297
337
  </button>
@@ -300,7 +340,7 @@ export function FragmentEditor({
300
340
  <button
301
341
  type="button"
302
342
  onClick={() => appendRequirement("")}
303
- className="text-xs text-[--color-accent] hover:underline"
343
+ style={addButtonStyle}
304
344
  >
305
345
  + Add requirement
306
346
  </button>
@@ -343,14 +383,14 @@ export function FragmentEditor({
343
383
  expanded={expandedSections.has("meta")}
344
384
  onToggle={() => toggleSection("meta")}
345
385
  >
346
- <div className="grid grid-cols-2 gap-4 mb-4">
386
+ <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '16px' }}>
347
387
  <div>
348
- <label className="block text-xs font-medium text-secondary mb-1.5">
388
+ <label style={labelStyle}>
349
389
  Status
350
390
  </label>
351
391
  <select
352
392
  {...register("meta.status")}
353
- className="w-full px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
393
+ style={inputStyle}
354
394
  >
355
395
  <option value="draft">Draft</option>
356
396
  <option value="experimental">Experimental</option>
@@ -360,23 +400,23 @@ export function FragmentEditor({
360
400
  </select>
361
401
  </div>
362
402
  <div>
363
- <label className="block text-xs font-medium text-secondary mb-1.5">
403
+ <label style={labelStyle}>
364
404
  Since Version
365
405
  </label>
366
406
  <input
367
407
  {...register("meta.since")}
368
- className="w-full px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
408
+ style={inputStyle}
369
409
  placeholder="1.0.0"
370
410
  />
371
411
  </div>
372
412
  </div>
373
- <div className="mb-4">
374
- <label className="block text-xs font-medium text-secondary mb-1.5">
413
+ <div style={{ marginBottom: '16px' }}>
414
+ <label style={labelStyle}>
375
415
  Owner
376
416
  </label>
377
417
  <input
378
418
  {...register("meta.owner")}
379
- className="w-full px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
419
+ style={inputStyle}
380
420
  placeholder="@team-name or email"
381
421
  />
382
422
  </div>
@@ -384,16 +424,22 @@ export function FragmentEditor({
384
424
  </div>
385
425
 
386
426
  {/* Footer with save button */}
387
- <div className="px-4 py-3 border-t border-[--border] bg-[--bg-secondary]">
427
+ <div style={{ padding: '12px 16px', borderTop: '1px solid var(--border)', background: 'var(--bg-secondary)' }}>
388
428
  <button
389
429
  type="submit"
390
430
  disabled={!isDirty || saving}
391
- className={clsx(
392
- "w-full py-2 px-4 text-sm font-medium rounded-lg transition-colors",
393
- isDirty && !saving
394
- ? "bg-[--color-accent] text-white hover:bg-[--color-accent-hover]"
395
- : "bg-[--bg-disabled] text-tertiary cursor-not-allowed"
396
- )}
431
+ style={{
432
+ width: '100%',
433
+ padding: '8px 16px',
434
+ fontSize: '14px',
435
+ fontWeight: 500,
436
+ borderRadius: '8px',
437
+ transition: 'background-color 150ms',
438
+ border: 'none',
439
+ cursor: isDirty && !saving ? 'pointer' : 'not-allowed',
440
+ background: isDirty && !saving ? 'var(--color-accent)' : 'var(--bg-secondary)',
441
+ color: isDirty && !saving ? 'white' : 'var(--text-tertiary)',
442
+ }}
397
443
  >
398
444
  {saving ? "Saving..." : "Save Fragment"}
399
445
  </button>
@@ -410,24 +456,41 @@ interface SectionProps {
410
456
  }
411
457
 
412
458
  function Section({ title, expanded, onToggle, children }: SectionProps) {
459
+ const [hovered, setHovered] = useState(false);
460
+
413
461
  return (
414
- <div className="border-b border-[--border]">
462
+ <div style={{ borderBottom: '1px solid var(--border)' }}>
415
463
  <button
416
464
  type="button"
417
465
  onClick={onToggle}
418
- className="w-full px-4 py-3 flex items-center justify-between bg-[--bg-secondary] hover:bg-[--bg-hover] transition-colors"
466
+ onMouseEnter={() => setHovered(true)}
467
+ onMouseLeave={() => setHovered(false)}
468
+ style={{
469
+ width: '100%',
470
+ padding: '12px 16px',
471
+ display: 'flex',
472
+ alignItems: 'center',
473
+ justifyContent: 'space-between',
474
+ background: hovered ? 'var(--bg-hover)' : 'var(--bg-secondary)',
475
+ transition: 'background-color 150ms',
476
+ border: 'none',
477
+ cursor: 'pointer',
478
+ }}
419
479
  >
420
- <span className="text-xs font-semibold text-primary uppercase tracking-wide">
480
+ <span style={{ fontSize: '12px', fontWeight: 600, color: 'var(--text-primary)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
421
481
  {title}
422
482
  </span>
423
483
  <ChevronDownIcon
424
- className={clsx(
425
- "w-4 h-4 text-tertiary transition-transform",
426
- !expanded && "-rotate-90"
427
- )}
484
+ style={{
485
+ width: '16px',
486
+ height: '16px',
487
+ color: 'var(--text-tertiary)',
488
+ transition: 'transform 150ms',
489
+ transform: expanded ? 'rotate(0deg)' : 'rotate(-90deg)',
490
+ }}
428
491
  />
429
492
  </button>
430
- {expanded && <div className="p-4">{children}</div>}
493
+ {expanded && <div style={{ padding: '16px' }}>{children}</div>}
431
494
  </div>
432
495
  );
433
496
  }
@@ -450,23 +513,23 @@ function RelatedField({
450
513
  const { fields, append, remove } = useFieldArray({ control, name });
451
514
 
452
515
  return (
453
- <div className="mb-4 last:mb-0">
454
- <label className="block text-xs font-medium text-secondary mb-0.5">
516
+ <div style={{ marginBottom: '16px' }}>
517
+ <label style={{ display: 'block', fontSize: '12px', fontWeight: 500, color: 'var(--text-secondary)', marginBottom: '2px' }}>
455
518
  {label}
456
519
  </label>
457
- <p className="text-[10px] text-tertiary mb-2">{description}</p>
458
- <div className="space-y-2">
520
+ <p style={{ fontSize: '10px', color: 'var(--text-tertiary)', marginBottom: '8px', marginTop: 0 }}>{description}</p>
521
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
459
522
  {fields.map((field, index) => (
460
- <div key={field.id} className="flex gap-2">
523
+ <div key={field.id} style={{ display: 'flex', gap: '8px' }}>
461
524
  <input
462
525
  {...register(`${name}.${index}` as const)}
463
- className="flex-1 px-3 py-1.5 text-sm bg-[--bg-elevated] border border-[--border] rounded-lg focus:outline-none focus:ring-2 focus:ring-[--color-accent] text-primary"
526
+ style={{ ...inputStyle, flex: 1 }}
464
527
  placeholder="ComponentName"
465
528
  />
466
529
  <button
467
530
  type="button"
468
531
  onClick={() => remove(index)}
469
- className="px-2 text-secondary hover:text-error"
532
+ style={removeButtonStyle}
470
533
  >
471
534
  &times;
472
535
  </button>
@@ -475,7 +538,7 @@ function RelatedField({
475
538
  <button
476
539
  type="button"
477
540
  onClick={() => append("")}
478
- className="text-xs text-[--color-accent] hover:underline"
541
+ style={addButtonStyle}
479
542
  >
480
543
  + Add component
481
544
  </button>