@selvajs/ui 6.6.0-beta.14 → 6.6.0-beta.16

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 (205) hide show
  1. package/README.md +0 -3
  2. package/dist/components/compute/AppLayout.svelte +10 -5
  3. package/dist/components/compute/CollapsedPanelStrip.svelte +1 -1
  4. package/dist/components/compute/ParameterPresetManager.svelte +1 -1
  5. package/dist/components/compute/SolveMessages.svelte +2 -2
  6. package/dist/components/layout/FooterItemRenderer.svelte +1 -1
  7. package/dist/components/layout/PageFooter.svelte +2 -2
  8. package/dist/components/layout/PageHeader.svelte +1 -1
  9. package/dist/components/layout/SideNav.svelte +3 -3
  10. package/dist/components/layout/SubNav.svelte +2 -2
  11. package/dist/components/preview/ChartOutput.svelte +3 -3
  12. package/dist/components/preview/Group.svelte +7 -7
  13. package/dist/components/preview/ImageOutput.svelte +6 -6
  14. package/dist/components/preview/InputControl.svelte +1 -0
  15. package/dist/components/preview/OutputDisplay.svelte +8 -6
  16. package/dist/components/preview/TabBar.svelte +6 -4
  17. package/dist/components/preview/TabBar.svelte.d.ts +2 -0
  18. package/dist/components/preview/TabContent.svelte +1 -1
  19. package/dist/components/preview/TabLayout.svelte +3 -4
  20. package/dist/components/preview/inputs/ChecklistInput.svelte +3 -3
  21. package/dist/components/preview/inputs/ColorInput.svelte +356 -14
  22. package/dist/components/preview/inputs/ColorInput.svelte.d.ts +1 -0
  23. package/dist/components/preview/inputs/FileInput.svelte +3 -3
  24. package/dist/components/preview/inputs/SegmentedInput.svelte +2 -1
  25. package/dist/components/preview/inputs/TileInput.svelte +3 -2
  26. package/dist/components/primitives/CalculateButton.svelte +2 -2
  27. package/dist/components/primitives/Callout.svelte +7 -5
  28. package/dist/components/primitives/Callout.svelte.d.ts +4 -4
  29. package/dist/components/primitives/DataTable.svelte +1 -1
  30. package/dist/components/primitives/ImageUploadField.svelte +1 -1
  31. package/dist/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  32. package/dist/components/primitives/badge/badge.svelte +2 -2
  33. package/dist/components/primitives/badge/badge.svelte.d.ts +6 -6
  34. package/dist/components/primitives/button/button.svelte +6 -7
  35. package/dist/components/primitives/button/button.svelte.d.ts +18 -18
  36. package/dist/components/primitives/card/card.svelte +1 -1
  37. package/dist/components/primitives/card/card.svelte.d.ts +1 -1
  38. package/dist/components/primitives/checkbox/checkbox.svelte +1 -1
  39. package/dist/components/primitives/command/command-input.svelte +1 -1
  40. package/dist/components/primitives/command/command-item.svelte +1 -1
  41. package/dist/components/primitives/command/command-link-item.svelte +1 -1
  42. package/dist/components/primitives/command/command.svelte +1 -1
  43. package/dist/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  44. package/dist/components/primitives/context-menu/context-menu-content.svelte +1 -1
  45. package/dist/components/primitives/context-menu/context-menu-item.svelte +1 -1
  46. package/dist/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  47. package/dist/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  48. package/dist/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  49. package/dist/components/primitives/dialog/dialog-content.svelte +2 -2
  50. package/dist/components/primitives/drawer/Drawer.svelte +1 -1
  51. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  52. package/dist/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +2 -0
  53. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  54. package/dist/components/primitives/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -0
  55. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  56. package/dist/components/primitives/dropdown-menu/dropdown-menu-item.svelte.d.ts +2 -1
  57. package/dist/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  58. package/dist/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  59. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  60. package/dist/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  61. package/dist/components/primitives/index.d.ts +1 -1
  62. package/dist/components/primitives/index.js +1 -1
  63. package/dist/components/primitives/input/input.svelte +2 -2
  64. package/dist/components/primitives/input-group/input-group.svelte +1 -1
  65. package/dist/components/primitives/popover/popover-content.svelte +1 -1
  66. package/dist/components/primitives/resizable/resizable-handle.svelte +2 -2
  67. package/dist/components/primitives/search/search.svelte +1 -1
  68. package/dist/components/primitives/select/select-content.svelte +1 -1
  69. package/dist/components/primitives/select/select-item.svelte +1 -1
  70. package/dist/components/primitives/select/select-trigger.svelte +1 -1
  71. package/dist/components/primitives/slider/slider.svelte +1 -1
  72. package/dist/components/primitives/switch/switch.svelte +1 -1
  73. package/dist/components/primitives/tabs/tabs-list.svelte +1 -1
  74. package/dist/components/primitives/tabs/tabs-list.svelte.d.ts +3 -3
  75. package/dist/components/primitives/tabs/tabs-trigger.svelte +1 -1
  76. package/dist/components/primitives/tabs/tabs-trigger.svelte.d.ts +3 -3
  77. package/dist/components/primitives/textarea/textarea.svelte +1 -1
  78. package/dist/components/primitives/toggle/toggle.svelte +8 -2
  79. package/dist/components/primitives/toggle/toggle.svelte.d.ts +10 -4
  80. package/dist/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  81. package/dist/components/primitives/toggle-group/toggle-group.svelte +1 -1
  82. package/dist/components/primitives/tooltip/index.d.ts +6 -0
  83. package/dist/components/primitives/tooltip/index.js +8 -0
  84. package/dist/components/primitives/tooltip/tooltip-content.svelte +34 -0
  85. package/dist/components/primitives/tooltip/tooltip-content.svelte.d.ts +10 -0
  86. package/dist/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  87. package/dist/components/primitives/tooltip/tooltip-portal.svelte.d.ts +4 -0
  88. package/dist/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  89. package/dist/components/primitives/tooltip/tooltip-provider.svelte.d.ts +4 -0
  90. package/dist/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  91. package/dist/components/primitives/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  92. package/dist/components/primitives/tooltip/tooltip.svelte +7 -0
  93. package/dist/components/primitives/tooltip/tooltip.svelte.d.ts +4 -0
  94. package/dist/components/viewer/MeshMetadataPanel.svelte +1 -1
  95. package/dist/components/viewer/SceneManager.svelte +19 -19
  96. package/dist/components/viewer/Viewer.svelte +90 -164
  97. package/dist/components/viewer/Viewer.svelte.d.ts +3 -1
  98. package/dist/components/viewer/ViewerDock.svelte +404 -0
  99. package/dist/components/viewer/ViewerDock.svelte.d.ts +42 -0
  100. package/dist/i18n/messages.d.ts +12 -0
  101. package/dist/i18n/messages.js +20 -0
  102. package/dist/styles/base.css +81 -80
  103. package/dist/utils/color-space.d.ts +21 -0
  104. package/dist/utils/color-space.js +90 -0
  105. package/package.json +12 -13
  106. package/src/lib/components/compute/AppLayout.svelte +10 -5
  107. package/src/lib/components/compute/CollapsedPanelStrip.svelte +1 -1
  108. package/src/lib/components/compute/ParameterPresetManager.svelte +1 -1
  109. package/src/lib/components/compute/SolveMessages.svelte +2 -2
  110. package/src/lib/components/layout/FooterItemRenderer.svelte +1 -1
  111. package/src/lib/components/layout/PageFooter.svelte +2 -2
  112. package/src/lib/components/layout/PageHeader.svelte +1 -1
  113. package/src/lib/components/layout/SideNav.svelte +3 -3
  114. package/src/lib/components/layout/SubNav.svelte +2 -2
  115. package/src/lib/components/preview/ChartOutput.svelte +3 -3
  116. package/src/lib/components/preview/Group.svelte +7 -7
  117. package/src/lib/components/preview/ImageOutput.svelte +6 -6
  118. package/src/lib/components/preview/InputControl.svelte +1 -0
  119. package/src/lib/components/preview/OutputDisplay.svelte +8 -6
  120. package/src/lib/components/preview/TabBar.svelte +6 -4
  121. package/src/lib/components/preview/TabContent.svelte +1 -1
  122. package/src/lib/components/preview/TabLayout.svelte +3 -4
  123. package/src/lib/components/preview/inputs/ChecklistInput.svelte +3 -3
  124. package/src/lib/components/preview/inputs/ColorInput.svelte +356 -14
  125. package/src/lib/components/preview/inputs/FileInput.svelte +3 -3
  126. package/src/lib/components/preview/inputs/SegmentedInput.svelte +2 -1
  127. package/src/lib/components/preview/inputs/TileInput.svelte +3 -2
  128. package/src/lib/components/primitives/CalculateButton.svelte +2 -2
  129. package/src/lib/components/primitives/Callout.svelte +7 -5
  130. package/src/lib/components/primitives/DataTable.svelte +1 -1
  131. package/src/lib/components/primitives/ImageUploadField.svelte +1 -1
  132. package/src/lib/components/primitives/alert-dialog/alert-dialog-content.svelte +1 -1
  133. package/src/lib/components/primitives/badge/badge.svelte +2 -2
  134. package/src/lib/components/primitives/button/button.svelte +6 -7
  135. package/src/lib/components/primitives/card/card.svelte +1 -1
  136. package/src/lib/components/primitives/checkbox/checkbox.svelte +1 -1
  137. package/src/lib/components/primitives/command/command-input.svelte +1 -1
  138. package/src/lib/components/primitives/command/command-item.svelte +1 -1
  139. package/src/lib/components/primitives/command/command-link-item.svelte +1 -1
  140. package/src/lib/components/primitives/command/command.svelte +1 -1
  141. package/src/lib/components/primitives/context-menu/context-menu-checkbox-item.svelte +1 -1
  142. package/src/lib/components/primitives/context-menu/context-menu-content.svelte +1 -1
  143. package/src/lib/components/primitives/context-menu/context-menu-item.svelte +1 -1
  144. package/src/lib/components/primitives/context-menu/context-menu-radio-item.svelte +1 -1
  145. package/src/lib/components/primitives/context-menu/context-menu-sub-content.svelte +1 -1
  146. package/src/lib/components/primitives/context-menu/context-menu-sub-trigger.svelte +1 -1
  147. package/src/lib/components/primitives/dialog/dialog-content.svelte +2 -2
  148. package/src/lib/components/primitives/drawer/Drawer.svelte +1 -1
  149. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-checkbox-item.svelte +31 -11
  150. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-content.svelte +5 -1
  151. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-item.svelte +4 -2
  152. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-radio-item.svelte +1 -1
  153. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-shortcut.svelte +1 -1
  154. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-content.svelte +1 -1
  155. package/src/lib/components/primitives/dropdown-menu/dropdown-menu-sub-trigger.svelte +1 -1
  156. package/src/lib/components/primitives/index.ts +1 -1
  157. package/src/lib/components/primitives/input/input.svelte +2 -2
  158. package/src/lib/components/primitives/input-group/input-group.svelte +1 -1
  159. package/src/lib/components/primitives/popover/popover-content.svelte +1 -1
  160. package/src/lib/components/primitives/resizable/resizable-handle.svelte +2 -2
  161. package/src/lib/components/primitives/search/search.svelte +1 -1
  162. package/src/lib/components/primitives/select/select-content.svelte +1 -1
  163. package/src/lib/components/primitives/select/select-item.svelte +1 -1
  164. package/src/lib/components/primitives/select/select-trigger.svelte +1 -1
  165. package/src/lib/components/primitives/slider/slider.svelte +1 -1
  166. package/src/lib/components/primitives/switch/switch.svelte +1 -1
  167. package/src/lib/components/primitives/tabs/tabs-list.svelte +1 -1
  168. package/src/lib/components/primitives/tabs/tabs-trigger.svelte +1 -1
  169. package/src/lib/components/primitives/textarea/textarea.svelte +1 -1
  170. package/src/lib/components/primitives/toggle/toggle.svelte +8 -2
  171. package/src/lib/components/primitives/toggle-group/toggle-group-item.svelte +1 -1
  172. package/src/lib/components/primitives/toggle-group/toggle-group.svelte +1 -1
  173. package/src/lib/components/primitives/tooltip/index.ts +19 -0
  174. package/src/lib/components/primitives/tooltip/tooltip-content.svelte +34 -0
  175. package/src/lib/components/primitives/tooltip/tooltip-portal.svelte +7 -0
  176. package/src/lib/components/primitives/tooltip/tooltip-provider.svelte +7 -0
  177. package/src/lib/components/primitives/tooltip/tooltip-trigger.svelte +7 -0
  178. package/src/lib/components/primitives/tooltip/tooltip.svelte +7 -0
  179. package/src/lib/components/viewer/MeshMetadataPanel.svelte +1 -1
  180. package/src/lib/components/viewer/SceneManager.svelte +19 -19
  181. package/src/lib/components/viewer/Viewer.svelte +90 -164
  182. package/src/lib/components/viewer/ViewerDock.svelte +404 -0
  183. package/src/lib/i18n/messages.ts +32 -0
  184. package/src/lib/styles/base.css +81 -80
  185. package/src/lib/utils/color-space.ts +107 -0
  186. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  187. package/dist/components/primitives/theme-switcher/ThemeSwitcher.svelte.d.ts +0 -3
  188. package/dist/components/primitives/theme-switcher/index.d.ts +0 -1
  189. package/dist/components/primitives/theme-switcher/index.js +0 -1
  190. package/dist/styles/themes/cyberpunk.css +0 -98
  191. package/dist/styles/themes/neutral.css +0 -72
  192. package/dist/styles/themes/ocean.css +0 -75
  193. package/dist/styles/themes/selva.css +0 -105
  194. package/dist/theme/themeStore.svelte.d.ts +0 -12
  195. package/dist/theme/themeStore.svelte.js +0 -40
  196. package/dist/theme/themes.d.ts +0 -5
  197. package/dist/theme/themes.js +0 -13
  198. package/src/lib/components/primitives/theme-switcher/ThemeSwitcher.svelte +0 -39
  199. package/src/lib/components/primitives/theme-switcher/index.ts +0 -1
  200. package/src/lib/styles/themes/cyberpunk.css +0 -98
  201. package/src/lib/styles/themes/neutral.css +0 -72
  202. package/src/lib/styles/themes/ocean.css +0 -75
  203. package/src/lib/styles/themes/selva.css +0 -105
  204. package/src/lib/theme/themeStore.svelte.ts +0 -50
  205. package/src/lib/theme/themes.ts +0 -18
package/README.md CHANGED
@@ -57,9 +57,6 @@ In your `app.css`:
57
57
  @import '@selvajs/ui/styles/base.css';
58
58
  ```
59
59
 
60
- Themes are available under `@selvajs/ui/styles/themes/*` — `selva`, `neutral`, `ocean`, and
61
- `cyberpunk`.
62
-
63
60
  ## Schema types
64
61
 
65
62
  Types generated from `packages/schemas/ui-schema.json` are published by `@selvajs/schemas`, not
@@ -284,7 +284,7 @@
284
284
  trailing={hasMenu ? actionsMenu : undefined}
285
285
  />
286
286
  {:else if hasMenu || solvingIndicatorPlacement === 'inline'}
287
- <div class="mt-3 pb-3 pt-2 px-2 gap-2 flex items-center border-t border-border/50">
287
+ <div class="mt-3 pb-3 pt-2 px-2 gap-2 flex items-center border-t border-border">
288
288
  {#if solvingIndicatorPlacement === 'inline'}
289
289
  <SolvingIndicator show={showSolvingChip} placement="inline" />
290
290
  {/if}
@@ -325,7 +325,7 @@
325
325
  data-layout-root
326
326
  class="min-h-0 flex flex-1 flex-col overflow-hidden {stacked
327
327
  ? ''
328
- : `sm:flex-row sm:py-(--page-py) ${leftCollapsed ? 'sm:pl-0' : 'sm:pl-(--page-px)'} ${rightCollapsed ? 'sm:pr-0' : 'sm:pr-(--page-px)'}`}"
328
+ : `sm:flex-row sm:py-2 ${leftCollapsed ? 'sm:pl-0' : 'sm:pl-2'} ${rightCollapsed ? 'sm:pr-0' : 'sm:pr-2'}`}"
329
329
  class:fullscreen-layout={isViewerFullscreen}
330
330
  class:relative={isMobile}
331
331
  class:mobile-root={stacked}
@@ -347,14 +347,15 @@
347
347
  {onViewerReady}
348
348
  viewerConfig={{
349
349
  ...viewerConfig,
350
- backgroundColor: schema?.viewerOptions?.backgroundColor,
350
+ backgroundColor: schema?.viewerOptions?.backgroundColor ?? viewerConfig.backgroundColor,
351
+ look: schema?.viewerOptions?.look ?? viewerConfig.look,
351
352
  showSceneManager: false
352
353
  }}
353
354
  />
354
355
  </div>
355
356
 
356
357
  <div
357
- class="drawer-container rounded-t-2xl z-40 border-t bg-background shadow-sheet drawer-{drawer}"
358
+ class="drawer-container z-40 rounded-t-xl border-t bg-background shadow-sheet drawer-{drawer}"
358
359
  >
359
360
  <!-- Named by its visible label; aria-expanded carries the open/closed state. -->
360
361
  <button
@@ -472,6 +473,7 @@
472
473
  <Resizable.Handle
473
474
  withHandle
474
475
  line={false}
476
+ class="translate-x-1.5 z-20"
475
477
  data-collapsed={leftCollapsed}
476
478
  onclick={() => {
477
479
  if (leftCollapsed) leftPaneRef?.expand();
@@ -490,7 +492,9 @@
490
492
  {onViewerReady}
491
493
  viewerConfig={{
492
494
  ...viewerConfig,
493
- backgroundColor: schema?.viewerOptions?.backgroundColor
495
+ backgroundColor:
496
+ schema?.viewerOptions?.backgroundColor ?? viewerConfig.backgroundColor,
497
+ look: schema?.viewerOptions?.look ?? viewerConfig.look
494
498
  }}
495
499
  />
496
500
  </Resizable.Pane>
@@ -501,6 +505,7 @@
501
505
  <Resizable.Handle
502
506
  withHandle
503
507
  line={false}
508
+ class="-translate-x-1.5 z-20"
504
509
  data-collapsed={rightCollapsed}
505
510
  onclick={() => {
506
511
  if (rightCollapsed) rightPaneRef?.expand();
@@ -27,7 +27,7 @@
27
27
  );
28
28
 
29
29
  const tabButtonClass =
30
- 'w-8 h-8 rounded-md cursor-pointer flex shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-accent hover:text-foreground';
30
+ 'w-8 h-8 rounded-md cursor-pointer flex shrink-0 items-center justify-center text-muted-foreground transition-colors hover:bg-hover hover:text-foreground';
31
31
  </script>
32
32
 
33
33
  <div
@@ -203,7 +203,7 @@
203
203
  <button
204
204
  type="button"
205
205
  onclick={() => selectListedState(preset)}
206
- class="p-3 w-full rounded-lg border text-left transition-colors hover:bg-muted"
206
+ class="p-3 w-full rounded-lg border text-left transition-colors hover:bg-hover"
207
207
  >
208
208
  <div class="text-sm font-medium">{preset.name}</div>
209
209
  {#if preset.description}
@@ -291,7 +291,7 @@
291
291
  framed box inside an edge-to-edge column reads as a dialog glued into the page. -->
292
292
  <div
293
293
  class={placement === 'inline'
294
- ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border/50'}`
294
+ ? `px-2 py-2 border-t ${view === 'blocked' ? 'border-destructive/40' : 'border-border'}`
295
295
  : `p-3 bottom-4 shadow-lg w-lg fixed left-1/2 z-50 max-w-screen-inset -translate-x-1/2 rounded-lg border bg-background ${view === 'blocked' ? 'border-destructive/50' : ''}`}
296
296
  role={view === 'review' || view === 'blocked' ? 'alert' : undefined}
297
297
  data-testid="solve-messages"
@@ -319,7 +319,7 @@
319
319
  title={t.solveMessagesEscHint}
320
320
  >
321
321
  {t.solveMessagesAbort}
322
- <kbd class="px-1 font-sans rounded border border-border/60 text-2xs opacity-70">
322
+ <kbd class="px-1 font-sans rounded-sm border border-border text-2xs opacity-70">
323
323
  Esc
324
324
  </kbd>
325
325
  </Button>
@@ -9,7 +9,7 @@
9
9
  {#if item.onClick}
10
10
  <button
11
11
  onclick={item.onClick}
12
- class="gap-1.5 px-2 py-0.5 rounded flex cursor-pointer items-center transition-colors hover:bg-muted"
12
+ class="gap-1.5 px-2 py-0.5 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover"
13
13
  >
14
14
  <item.component {...itemProps} />
15
15
  </button>
@@ -88,12 +88,12 @@
88
88
  <ComputeMessagesDialog {errors} {warnings} {diagnostics}>
89
89
  {#snippet trigger()}
90
90
  <div
91
- class="gap-1.5 px-2 py-1 rounded flex cursor-pointer items-center transition-colors hover:bg-muted {errorCount >
91
+ class="gap-1.5 px-2 py-1 flex cursor-pointer items-center rounded-sm transition-colors hover:bg-hover {errorCount >
92
92
  0
93
93
  ? 'text-destructive hover:bg-destructive/10'
94
94
  : warningCount > 0
95
95
  ? 'text-warning hover:bg-warning/10'
96
- : 'hover:bg-muted'}"
96
+ : 'hover:bg-hover'}"
97
97
  title={formatCount(totalCount, t.lastSolveMessagesOne, t.lastSolveMessagesOther)}
98
98
  >
99
99
  {#if errorCount > 0}
@@ -66,7 +66,7 @@
66
66
  </div>
67
67
 
68
68
  {#if subnav}
69
- <div class="h-10 flex items-center border-t border-border/60 px-(--page-px)">
69
+ <div class="h-10 flex items-center border-t border-border px-(--page-px)">
70
70
  {@render subnav()}
71
71
  </div>
72
72
  {/if}
@@ -119,8 +119,8 @@
119
119
  aria-current={active ? 'page' : undefined}
120
120
  class={`group gap-2 py-1.5 pr-2.5 relative flex w-full items-center text-left transition-colors ${
121
121
  active
122
- ? 'pl-4 rounded-r-md bg-accent text-accent-foreground'
123
- : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-muted/60 hover:text-foreground'
122
+ ? 'pl-4 rounded-r-md bg-selected text-foreground'
123
+ : 'mx-2 pl-2.5 rounded-md text-muted-foreground hover:bg-hover hover:text-foreground'
124
124
  }`}
125
125
  >
126
126
  {#if active}
@@ -138,7 +138,7 @@
138
138
  </nav>
139
139
 
140
140
  {#if footer}
141
- <div class="px-3 py-3 sm:block hidden border-t border-border/60">
141
+ <div class="px-3 py-3 sm:block hidden border-t border-border">
142
142
  {@render footer()}
143
143
  </div>
144
144
  {/if}
@@ -31,8 +31,8 @@
31
31
  class={[
32
32
  'h-7 px-3 gap-1.5 text-sm font-medium flex items-center rounded-md transition-colors',
33
33
  active
34
- ? 'bg-accent text-accent-foreground'
35
- : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground'
34
+ ? 'bg-selected text-foreground'
35
+ : 'text-muted-foreground hover:bg-hover hover:text-foreground'
36
36
  ].join(' ')}
37
37
  >
38
38
  {#if item.icon}
@@ -222,7 +222,7 @@
222
222
 
223
223
  <div
224
224
  bind:this={wrapperEl}
225
- class="group relative overflow-hidden rounded-lg border border-border {isFullscreen
225
+ class="group relative overflow-hidden rounded-lg border border-border-strong {isFullscreen
226
226
  ? 'bg-background'
227
227
  : ''}"
228
228
  >
@@ -241,7 +241,7 @@
241
241
  >
242
242
  {#if loading}
243
243
  <div
244
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-muted-foreground"
244
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-muted-foreground"
245
245
  >
246
246
  <Loader size={14} class="animate-spin" />
247
247
  </div>
@@ -253,7 +253,7 @@
253
253
  disabled={loading}
254
254
  title={isFullscreen ? t.exitFullscreen : t.fullscreen}
255
255
  aria-label={isFullscreen ? t.exitFullscreen : t.fullscreen}
256
- class="rounded p-1.5 backdrop-blur-sm flex items-center border border-border bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
256
+ class="p-1.5 backdrop-blur-sm flex items-center rounded-sm border border-border-strong bg-background/80 text-foreground transition-colors hover:bg-background disabled:cursor-not-allowed disabled:opacity-50"
257
257
  >
258
258
  {#if isFullscreen}
259
259
  <Minimize size={14} />
@@ -69,7 +69,7 @@
69
69
  </div>
70
70
  {/snippet}
71
71
 
72
- <section class="shadow-xs rounded-xl border bg-card">
72
+ <section class="rounded-xl border bg-card shadow-raised">
73
73
  {#if flat}
74
74
  <div class="p-4">
75
75
  {@render grid()}
@@ -80,18 +80,18 @@
80
80
  <h3>
81
81
  <button
82
82
  type="button"
83
- class="gap-3 px-4 pt-3.5 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
83
+ class="gap-3 px-4 pt-4 flex w-full items-start text-left outline-none select-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset {description
84
84
  ? 'pb-0'
85
- : 'pb-3.5'}"
85
+ : 'pb-3'}"
86
86
  aria-expanded={!collapsed}
87
87
  aria-describedby={description ? descriptionId : undefined}
88
88
  onclick={onToggle}
89
89
  >
90
- <span class="min-w-0 text-base font-semibold leading-snug flex-1 text-foreground"
90
+ <span class="min-w-0 text-sm font-semibold leading-snug flex-1 text-foreground"
91
91
  >{label}</span
92
92
  >
93
93
  <ChevronDown
94
- class="mt-1 h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200 {collapsed
94
+ class="mt-0.5 h-4 w-4 shrink-0 text-faint-foreground transition-transform duration-200 {collapsed
95
95
  ? '-rotate-90'
96
96
  : ''}"
97
97
  />
@@ -100,14 +100,14 @@
100
100
  {#if description}
101
101
  <p
102
102
  id={descriptionId}
103
- class="pl-4 pr-11 pt-0.5 pb-3.5 text-xs leading-snug text-muted-foreground"
103
+ class="pl-4 pr-11 pt-0.5 pb-3 text-xs leading-snug text-muted-foreground"
104
104
  >
105
105
  {description}
106
106
  </p>
107
107
  {/if}
108
108
  <div class="content-wrapper" class:collapsed inert={collapsed}>
109
109
  <div class="content-inner">
110
- <div class="px-4 pt-1 pb-5">
110
+ <div class="px-4 pt-1 pb-4">
111
111
  {@render grid()}
112
112
  </div>
113
113
  </div>
@@ -297,14 +297,14 @@
297
297
  }
298
298
 
299
299
  const toolButton =
300
- 'flex h-7 min-w-7 items-center justify-center rounded px-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground disabled:pointer-events-none disabled:opacity-40';
300
+ 'flex h-7 min-w-7 items-center justify-center rounded-sm px-1.5 text-muted-foreground transition-colors hover:bg-hover hover:text-foreground disabled:pointer-events-none disabled:opacity-40';
301
301
  </script>
302
302
 
303
303
  <!-- The layout hides this output until a solve returns a file, so there is no empty state here. -->
304
304
  {#if error || unsupported || current}
305
305
  <div
306
306
  bind:this={wrapperEl}
307
- class="flex flex-col overflow-hidden rounded-lg border border-border bg-background {isFullscreen
307
+ class="flex flex-col overflow-hidden rounded-lg border border-border-strong bg-background {isFullscreen
308
308
  ? 'h-dvh'
309
309
  : ''}"
310
310
  >
@@ -375,7 +375,7 @@
375
375
  onclick={() => step(-1)}
376
376
  title="{t.previousImage} (←)"
377
377
  aria-label={t.previousImage}
378
- class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
378
+ class="left-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
379
379
  >
380
380
  <ChevronLeft size={16} />
381
381
  </button>
@@ -383,14 +383,14 @@
383
383
  onclick={() => step(1)}
384
384
  title="{t.nextImage} (→)"
385
385
  aria-label={t.nextImage}
386
- class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border bg-background/80 text-foreground hover:bg-background"
386
+ class="right-2 p-1.5 backdrop-blur-sm absolute top-1/2 -translate-y-1/2 rounded-full border border-border-strong bg-background/80 text-foreground hover:bg-background"
387
387
  >
388
388
  <ChevronRight size={16} />
389
389
  </button>
390
390
  {/if}
391
391
 
392
392
  <div
393
- class="px-2.5 py-1 text-xs bottom-2 rounded pointer-events-none absolute left-1/2 -translate-x-1/2 bg-foreground/80 text-background transition-opacity {showWheelHint
393
+ class="px-2.5 py-1 text-xs bottom-2 pointer-events-none absolute left-1/2 -translate-x-1/2 rounded-sm bg-foreground text-background transition-opacity {showWheelHint
394
394
  ? 'opacity-100'
395
395
  : 'opacity-0'}"
396
396
  >
@@ -404,7 +404,7 @@
404
404
  <button
405
405
  onclick={() => select(i)}
406
406
  title="{image.fileName}{image.fileType}"
407
- class="h-12 w-16 rounded shrink-0 overflow-hidden border-2 bg-muted transition-colors {i ===
407
+ class="h-12 w-16 shrink-0 overflow-hidden rounded-sm border-2 bg-muted transition-colors {i ===
408
408
  currentIndex
409
409
  ? 'border-primary'
410
410
  : 'border-transparent opacity-70 hover:opacity-100'}"
@@ -378,6 +378,7 @@
378
378
  {inputId}
379
379
  value={typeof value === 'string' ? value : '#000000'}
380
380
  onChange={(newValue) => commit(newValue)}
381
+ {disabled}
381
382
  />
382
383
  {/if}
383
384
  </div>
@@ -38,7 +38,7 @@
38
38
  );
39
39
  const hasValue = $derived(value != null);
40
40
 
41
- const boxClass = 'min-h-12.5 rounded-md px-3 py-3 text-sm border border-border/60';
41
+ const boxClass = 'min-h-12.5 rounded-md px-3 py-3 text-sm border border-border-strong';
42
42
 
43
43
  async function copyToClipboard() {
44
44
  try {
@@ -194,7 +194,7 @@
194
194
  <span class="font-medium">{node.name}</span>
195
195
  </button>
196
196
  {#if isOpen}
197
- <div class="ml-4 pl-2 border-l border-border/50">
197
+ <div class="ml-4 pl-2 border-l border-border-strong">
198
198
  {@render treeNodes(node.children, folderPath)}
199
199
  </div>
200
200
  {/if}
@@ -217,12 +217,14 @@
217
217
 
218
218
  {#snippet fileDisplay()}
219
219
  {#if fileCount === 0}
220
- <div class="px-3 py-3 text-sm rounded-md border border-border bg-muted text-muted-foreground">
220
+ <div
221
+ class="px-3 py-3 text-sm rounded-md border border-border-strong bg-muted text-muted-foreground"
222
+ >
221
223
  {t.waitingForFiles}
222
224
  </div>
223
225
  {:else}
224
226
  <div class="gap-2 flex flex-col">
225
- <div class="px-3 py-2 rounded-md border border-border bg-muted">
227
+ <div class="px-3 py-2 rounded-md border border-border-strong bg-muted">
226
228
  <div class="gap-2 flex items-center justify-between">
227
229
  <span class="min-w-0 text-sm font-medium truncate text-foreground">
228
230
  {fileCount === 1
@@ -313,10 +315,10 @@
313
315
  <div class="group relative">
314
316
  {#if isObjectValue}
315
317
  <pre
316
- class="{boxClass} max-h-96 font-mono overflow-auto bg-muted/10 wrap-anywhere text-foreground">{formattedValue}</pre>
318
+ class="{boxClass} max-h-96 font-mono overflow-auto bg-muted wrap-anywhere text-foreground">{formattedValue}</pre>
317
319
  {:else}
318
320
  <div
319
- class="{boxClass} bg-muted/10 wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
321
+ class="{boxClass} bg-muted wrap-anywhere wrap-break-word whitespace-pre-wrap text-foreground"
320
322
  >
321
323
  {#if hasValue}{value}{:else}{@render placeholder()}{/if}
322
324
  </div>
@@ -12,9 +12,11 @@
12
12
  tabs: TabConfig[];
13
13
  activeTabId: string;
14
14
  onTabChange: (tabId: string) => void;
15
+ /** Matches TabContent's tighter gutter in the stacked phone layout. */
16
+ bare?: boolean;
15
17
  }
16
18
 
17
- let { tabs, activeTabId, onTabChange }: Props = $props();
19
+ let { tabs, activeTabId, onTabChange, bare = false }: Props = $props();
18
20
 
19
21
  const SCROLL_BUTTON_WIDTH = 32;
20
22
 
@@ -64,7 +66,7 @@
64
66
  }
65
67
  </script>
66
68
 
67
- <div class="tab-bar relative shrink-0 border-b border-border">
69
+ <div class="tab-bar relative shrink-0 border-b border-border {bare ? 'mx-1' : 'mx-3'}">
68
70
  <Tabs.List bind:ref={listRef} variant="line" onscroll={updateOverflow} onwheel={handleWheel}>
69
71
  {#each tabs as tab (tab.id)}
70
72
  <Tabs.Trigger value={tab.id} onclick={() => onTabChange(tab.id)} variant="line">
@@ -127,11 +129,11 @@
127
129
  .scroll-button.back {
128
130
  left: 0;
129
131
  padding: 0 1.25rem 0 0.375rem;
130
- background: linear-gradient(to right, var(--card) 55%, transparent);
132
+ background: linear-gradient(to right, var(--tab-bar-bg, var(--background)) 55%, transparent);
131
133
  }
132
134
  .scroll-button.forward {
133
135
  right: 0;
134
136
  padding: 0 0.375rem 0 1.25rem;
135
- background: linear-gradient(to left, var(--card) 55%, transparent);
137
+ background: linear-gradient(to left, var(--tab-bar-bg, var(--background)) 55%, transparent);
136
138
  }
137
139
  </style>
@@ -3,6 +3,8 @@ interface Props {
3
3
  tabs: TabConfig[];
4
4
  activeTabId: string;
5
5
  onTabChange: (tabId: string) => void;
6
+ /** Matches TabContent's tighter gutter in the stacked phone layout. */
7
+ bare?: boolean;
6
8
  }
7
9
  declare const TabBar: import("svelte").Component<Props, {}, "">;
8
10
  type TabBar = ReturnType<typeof TabBar>;
@@ -137,7 +137,7 @@
137
137
  {#if bare}
138
138
  {@render body()}
139
139
  {:else}
140
- <div class="h-full bg-muted dark:bg-background">
140
+ <div class="h-full">
141
141
  <!-- `auto`, not the default `hover`: a hover-only bar comes and goes with the pointer,
142
142
  and a host that freezes mid-solve drops the pointer state with it. -->
143
143
  <ScrollArea class="h-full" orientation="vertical" type="auto">
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
2
  import type { UISchema, SupportedTypes } from '@selvajs/schemas';
3
- import * as Card from '../primitives/card';
4
3
  import * as Tabs from '../primitives/tabs';
5
4
  import TabBar from './TabBar.svelte';
6
5
  import TabContent from './TabContent.svelte';
@@ -81,7 +80,7 @@
81
80
  {#snippet tabs()}
82
81
  <Tabs.Root value={activeTabId} variant="line" class="min-h-0 flex-1">
83
82
  {#if showTabBar}
84
- <TabBar tabs={visibleTabs} {activeTabId} onTabChange={handleTabChange} />
83
+ <TabBar tabs={visibleTabs} {activeTabId} onTabChange={handleTabChange} {bare} />
85
84
  {/if}
86
85
 
87
86
  {#each visibleTabs as tab (tab.id)}
@@ -104,7 +103,7 @@
104
103
  {#if bare}
105
104
  {@render tabs()}
106
105
  {:else}
107
- <Card.Root variant="flush" class="min-h-0 flex-1">
106
+ <div class="min-h-0 flex flex-1 flex-col">
108
107
  {@render tabs()}
109
- </Card.Root>
108
+ </div>
110
109
  {/if}
@@ -30,7 +30,7 @@
30
30
  }
31
31
  </script>
32
32
 
33
- <div class="divide-y divide-border/60 overflow-hidden rounded-md border border-input">
33
+ <div class="divide-y divide-border overflow-hidden rounded-md border border-input">
34
34
  {#each Object.entries(options) as [name, expr] (name)}
35
35
  {@const optionValue = expr ?? name}
36
36
  {@const optionId = `${inputId}-${optionValue}`}
@@ -38,8 +38,8 @@
38
38
  {@const glyph = optionGlyph(config?.optionMedia?.[name], assets)}
39
39
  <label
40
40
  for={optionId}
41
- class="gap-3 px-3 py-2 text-sm flex items-center transition-colors select-none hover:bg-accent/50 {isSelected
42
- ? 'bg-accent/30'
41
+ class="gap-3 px-3 py-2 text-sm flex items-center transition-colors select-none hover:bg-hover {isSelected
42
+ ? 'bg-selected'
43
43
  : ''} {disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}"
44
44
  >
45
45
  <Checkbox