@devalok/shilp-sutra 0.56.0 → 0.59.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 (374) hide show
  1. package/MIGRATION.md +198 -0
  2. package/dist/_chunks/badge-group.js +75 -174
  3. package/dist/_chunks/badge-group.js.map +1 -1
  4. package/dist/_chunks/chat.js +270 -253
  5. package/dist/_chunks/chat.js.map +1 -1
  6. package/dist/_chunks/document-preview.js +1 -1
  7. package/dist/_chunks/document-preview.js.map +1 -1
  8. package/dist/_chunks/emoji-suggestion.js +1 -1
  9. package/dist/_chunks/emoji-suggestion.js.map +1 -1
  10. package/dist/_chunks/image-preview.js +71 -70
  11. package/dist/_chunks/image-preview.js.map +1 -1
  12. package/dist/_chunks/mention-suggestion.js +2 -2
  13. package/dist/_chunks/mention-suggestion.js.map +1 -1
  14. package/dist/_chunks/motion-preference.js +15 -0
  15. package/dist/_chunks/motion-preference.js.map +1 -0
  16. package/dist/_chunks/motion-provider.js +1 -1
  17. package/dist/_chunks/motion-provider.js.map +1 -1
  18. package/dist/_chunks/oauth-button.js +1 -1
  19. package/dist/_chunks/oauth-button.js.map +1 -1
  20. package/dist/_chunks/popover.js +50 -49
  21. package/dist/_chunks/popover.js.map +1 -1
  22. package/dist/_chunks/primitives-internal.js +29 -29
  23. package/dist/_chunks/primitives-internal.js.map +1 -1
  24. package/dist/_chunks/shared.js +48 -47
  25. package/dist/_chunks/shared.js.map +1 -1
  26. package/dist/_chunks/success.js +36 -36
  27. package/dist/_chunks/success.js.map +1 -1
  28. package/dist/_chunks/tree-view.js +1 -1
  29. package/dist/_chunks/tree-view.js.map +1 -1
  30. package/dist/_chunks/use-calendar.js +4 -4
  31. package/dist/_chunks/use-calendar.js.map +1 -1
  32. package/dist/ai/block-renderer.js +8 -8
  33. package/dist/ai/blocks/text.js +1 -1
  34. package/dist/ai/blocks/text.js.map +1 -1
  35. package/dist/ai/command-bar.js +67 -67
  36. package/dist/ai/command-bar.js.map +1 -1
  37. package/dist/ai/conversation.js +35 -35
  38. package/dist/ai/conversation.js.map +1 -1
  39. package/dist/ai/index.js +4 -4
  40. package/dist/composed/activity-feed.d.ts.map +1 -1
  41. package/dist/composed/activity-feed.js +109 -108
  42. package/dist/composed/activity-feed.js.map +1 -1
  43. package/dist/composed/avatar-group.d.ts +7 -2
  44. package/dist/composed/avatar-group.d.ts.map +1 -1
  45. package/dist/composed/avatar-group.js +3 -3
  46. package/dist/composed/avatar-group.js.map +1 -1
  47. package/dist/composed/command-palette.js +137 -137
  48. package/dist/composed/command-palette.js.map +1 -1
  49. package/dist/composed/content-card.js +2 -2
  50. package/dist/composed/content-card.js.map +1 -1
  51. package/dist/composed/date-picker/index.js +9 -9
  52. package/dist/composed/date-picker/index.js.map +1 -1
  53. package/dist/composed/diff.d.ts +23 -2
  54. package/dist/composed/diff.d.ts.map +1 -1
  55. package/dist/composed/diff.js +341 -260
  56. package/dist/composed/diff.js.map +1 -1
  57. package/dist/composed/emoji-picker.js +3 -3
  58. package/dist/composed/emoji-picker.js.map +1 -1
  59. package/dist/composed/empty-state.js +4 -4
  60. package/dist/composed/error-boundary.js +2 -2
  61. package/dist/composed/error-boundary.js.map +1 -1
  62. package/dist/composed/file-preview/image-preview.d.ts.map +1 -1
  63. package/dist/composed/file-preview/shared.d.ts.map +1 -1
  64. package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
  65. package/dist/composed/file-preview.js +152 -151
  66. package/dist/composed/file-preview.js.map +1 -1
  67. package/dist/composed/filter-bar.d.ts.map +1 -1
  68. package/dist/composed/filter-bar.js +53 -52
  69. package/dist/composed/filter-bar.js.map +1 -1
  70. package/dist/composed/form-section.d.ts.map +1 -1
  71. package/dist/composed/form-section.js +38 -37
  72. package/dist/composed/form-section.js.map +1 -1
  73. package/dist/composed/inline-edit.js +1 -1
  74. package/dist/composed/inline-edit.js.map +1 -1
  75. package/dist/composed/loading-skeleton.js +3 -3
  76. package/dist/composed/loading-skeleton.js.map +1 -1
  77. package/dist/composed/master-detail.d.ts.map +1 -1
  78. package/dist/composed/master-detail.js +1 -1
  79. package/dist/composed/master-detail.js.map +1 -1
  80. package/dist/composed/member-picker.js +1 -1
  81. package/dist/composed/member-picker.js.map +1 -1
  82. package/dist/composed/multi-select-popover.d.ts.map +1 -1
  83. package/dist/composed/multi-select-popover.js +109 -108
  84. package/dist/composed/multi-select-popover.js.map +1 -1
  85. package/dist/composed/page-skeletons.js +4 -4
  86. package/dist/composed/page-skeletons.js.map +1 -1
  87. package/dist/composed/responsive-modal.js +1 -1
  88. package/dist/composed/responsive-modal.js.map +1 -1
  89. package/dist/composed/rich-chat-input/attachment-strip.d.ts.map +1 -1
  90. package/dist/composed/rich-chat-input/reply-banner.d.ts.map +1 -1
  91. package/dist/composed/rich-chat-input/schedule-send.d.ts.map +1 -1
  92. package/dist/composed/rich-chat-input.d.ts.map +1 -1
  93. package/dist/composed/rich-chat-input.js +473 -472
  94. package/dist/composed/rich-chat-input.js.map +1 -1
  95. package/dist/composed/rich-text-editor.js +6 -6
  96. package/dist/composed/rich-text-editor.js.map +1 -1
  97. package/dist/composed/schedule-view.js +5 -5
  98. package/dist/composed/schedule-view.js.map +1 -1
  99. package/dist/composed/status-badge.d.ts.map +1 -1
  100. package/dist/composed/status-badge.js +29 -28
  101. package/dist/composed/status-badge.js.map +1 -1
  102. package/dist/hooks/index.d.ts +1 -0
  103. package/dist/hooks/index.d.ts.map +1 -1
  104. package/dist/hooks/index.js +4 -3
  105. package/dist/hooks/use-container-size.d.ts +18 -0
  106. package/dist/hooks/use-container-size.d.ts.map +1 -0
  107. package/dist/hooks/use-container-size.js +28 -0
  108. package/dist/hooks/use-container-size.js.map +1 -0
  109. package/dist/motion/index.d.ts +1 -0
  110. package/dist/motion/index.d.ts.map +1 -1
  111. package/dist/motion/index.js +2 -15
  112. package/dist/motion/motion-preference.d.ts +36 -0
  113. package/dist/motion/motion-preference.d.ts.map +1 -0
  114. package/dist/motion/motion-provider.d.ts +2 -1
  115. package/dist/motion/motion-provider.d.ts.map +1 -1
  116. package/dist/motion/primitives-index.js +103 -102
  117. package/dist/motion/primitives-index.js.map +1 -1
  118. package/dist/motion/primitives.d.ts.map +1 -1
  119. package/dist/shell/app-shell.d.ts +101 -0
  120. package/dist/shell/app-shell.d.ts.map +1 -0
  121. package/dist/shell/app-shell.js +76 -0
  122. package/dist/shell/app-shell.js.map +1 -0
  123. package/dist/shell/bottom-navbar.js +21 -21
  124. package/dist/shell/bottom-navbar.js.map +1 -1
  125. package/dist/shell/index.d.ts +2 -1
  126. package/dist/shell/index.d.ts.map +1 -1
  127. package/dist/shell/index.js +6 -5
  128. package/dist/shell/notification-center.d.ts +17 -0
  129. package/dist/shell/notification-center.d.ts.map +1 -1
  130. package/dist/shell/notification-center.js +110 -105
  131. package/dist/shell/notification-center.js.map +1 -1
  132. package/dist/shell/notification-preferences.js +1 -1
  133. package/dist/shell/notification-preferences.js.map +1 -1
  134. package/dist/shell/top-bar.js +7 -7
  135. package/dist/shell/top-bar.js.map +1 -1
  136. package/dist/tokens/generate-scale.d.ts +49 -0
  137. package/dist/tokens/generate-scale.d.ts.map +1 -1
  138. package/dist/tokens/index.css +1 -0
  139. package/dist/tokens/palettes.css +292 -0
  140. package/dist/tokens/primitives.css +29 -26
  141. package/dist/tokens/semantic.css +170 -47
  142. package/dist/tokens/shilp-sutra.css +1 -0
  143. package/dist/tokens/utilities.css +10 -7
  144. package/dist/tokens/variants.css +1 -1
  145. package/dist/ui/accordion.d.ts.map +1 -1
  146. package/dist/ui/accordion.js +27 -26
  147. package/dist/ui/accordion.js.map +1 -1
  148. package/dist/ui/alert-dialog.d.ts.map +1 -1
  149. package/dist/ui/alert-dialog.js +60 -59
  150. package/dist/ui/alert-dialog.js.map +1 -1
  151. package/dist/ui/alert.d.ts.map +1 -1
  152. package/dist/ui/alert.js +55 -113
  153. package/dist/ui/alert.js.map +1 -1
  154. package/dist/ui/autocomplete.js +80 -80
  155. package/dist/ui/autocomplete.js.map +1 -1
  156. package/dist/ui/avatar.d.ts.map +1 -1
  157. package/dist/ui/avatar.js +71 -70
  158. package/dist/ui/avatar.js.map +1 -1
  159. package/dist/ui/badge-indicator.d.ts +4 -8
  160. package/dist/ui/badge-indicator.d.ts.map +1 -1
  161. package/dist/ui/badge-indicator.js +3 -8
  162. package/dist/ui/badge-indicator.js.map +1 -1
  163. package/dist/ui/badge.d.ts +55 -34
  164. package/dist/ui/badge.d.ts.map +1 -1
  165. package/dist/ui/banner.d.ts.map +1 -1
  166. package/dist/ui/banner.js +43 -41
  167. package/dist/ui/banner.js.map +1 -1
  168. package/dist/ui/button-group.d.ts.map +1 -1
  169. package/dist/ui/button-group.js +3 -23
  170. package/dist/ui/button-group.js.map +1 -1
  171. package/dist/ui/button.d.ts +10 -1
  172. package/dist/ui/button.d.ts.map +1 -1
  173. package/dist/ui/button.js +79 -212
  174. package/dist/ui/button.js.map +1 -1
  175. package/dist/ui/card.d.ts.map +1 -1
  176. package/dist/ui/card.js +78 -75
  177. package/dist/ui/card.js.map +1 -1
  178. package/dist/ui/charts/radar-chart.d.ts.map +1 -1
  179. package/dist/ui/charts/radar-chart.js +1 -1
  180. package/dist/ui/charts/radar-chart.js.map +1 -1
  181. package/dist/ui/chat/date-separator.d.ts +8 -1
  182. package/dist/ui/chat/date-separator.d.ts.map +1 -1
  183. package/dist/ui/chat/message-list.d.ts.map +1 -1
  184. package/dist/ui/chat/message.d.ts.map +1 -1
  185. package/dist/ui/chat/typing-indicator.d.ts.map +1 -1
  186. package/dist/ui/checkbox.js +1 -1
  187. package/dist/ui/checkbox.js.map +1 -1
  188. package/dist/ui/code.js +2 -2
  189. package/dist/ui/code.js.map +1 -1
  190. package/dist/ui/color-input.d.ts.map +1 -1
  191. package/dist/ui/color-input.js +151 -150
  192. package/dist/ui/color-input.js.map +1 -1
  193. package/dist/ui/combobox.d.ts +14 -0
  194. package/dist/ui/combobox.d.ts.map +1 -1
  195. package/dist/ui/combobox.js +156 -152
  196. package/dist/ui/combobox.js.map +1 -1
  197. package/dist/ui/context-menu.d.ts.map +1 -1
  198. package/dist/ui/context-menu.js +70 -69
  199. package/dist/ui/context-menu.js.map +1 -1
  200. package/dist/ui/data-table-body.d.ts +3 -1
  201. package/dist/ui/data-table-body.d.ts.map +1 -1
  202. package/dist/ui/data-table-body.js +93 -92
  203. package/dist/ui/data-table-body.js.map +1 -1
  204. package/dist/ui/data-table-bulk-actions.d.ts +7 -1
  205. package/dist/ui/data-table-bulk-actions.d.ts.map +1 -1
  206. package/dist/ui/data-table-bulk-actions.js +14 -8
  207. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  208. package/dist/ui/data-table-card.d.ts.map +1 -1
  209. package/dist/ui/data-table-card.js +66 -47
  210. package/dist/ui/data-table-card.js.map +1 -1
  211. package/dist/ui/data-table-context.d.ts +4 -0
  212. package/dist/ui/data-table-context.d.ts.map +1 -1
  213. package/dist/ui/data-table-context.js +2 -2
  214. package/dist/ui/data-table-context.js.map +1 -1
  215. package/dist/ui/data-table-header.d.ts.map +1 -1
  216. package/dist/ui/data-table-header.js +50 -46
  217. package/dist/ui/data-table-header.js.map +1 -1
  218. package/dist/ui/data-table-pagination.js +3 -3
  219. package/dist/ui/data-table-pagination.js.map +1 -1
  220. package/dist/ui/data-table-toolbar.d.ts +11 -1
  221. package/dist/ui/data-table-toolbar.d.ts.map +1 -1
  222. package/dist/ui/data-table-toolbar.js +7 -7
  223. package/dist/ui/data-table-toolbar.js.map +1 -1
  224. package/dist/ui/data-table.d.ts +52 -5
  225. package/dist/ui/data-table.d.ts.map +1 -1
  226. package/dist/ui/data-table.js +181 -169
  227. package/dist/ui/data-table.js.map +1 -1
  228. package/dist/ui/dialog.d.ts.map +1 -1
  229. package/dist/ui/dialog.js +62 -61
  230. package/dist/ui/dialog.js.map +1 -1
  231. package/dist/ui/dot.d.ts.map +1 -1
  232. package/dist/ui/dot.js +10 -41
  233. package/dist/ui/dot.js.map +1 -1
  234. package/dist/ui/dropdown-menu.d.ts.map +1 -1
  235. package/dist/ui/dropdown-menu.js +79 -78
  236. package/dist/ui/dropdown-menu.js.map +1 -1
  237. package/dist/ui/file-upload.d.ts.map +1 -1
  238. package/dist/ui/file-upload.js +117 -116
  239. package/dist/ui/file-upload.js.map +1 -1
  240. package/dist/ui/form.d.ts.map +1 -1
  241. package/dist/ui/form.js +27 -26
  242. package/dist/ui/form.js.map +1 -1
  243. package/dist/ui/hover-card.d.ts.map +1 -1
  244. package/dist/ui/hover-card.js +26 -25
  245. package/dist/ui/hover-card.js.map +1 -1
  246. package/dist/ui/icon.js +7 -7
  247. package/dist/ui/index.d.ts +2 -2
  248. package/dist/ui/index.d.ts.map +1 -1
  249. package/dist/ui/index.js +3 -3
  250. package/dist/ui/index.js.map +1 -1
  251. package/dist/ui/input-otp.js +1 -1
  252. package/dist/ui/input-otp.js.map +1 -1
  253. package/dist/ui/input.js +8 -8
  254. package/dist/ui/input.js.map +1 -1
  255. package/dist/ui/menubar.d.ts.map +1 -1
  256. package/dist/ui/menubar.js +73 -72
  257. package/dist/ui/menubar.js.map +1 -1
  258. package/dist/ui/navigation-menu.d.ts.map +1 -1
  259. package/dist/ui/navigation-menu.js +80 -79
  260. package/dist/ui/navigation-menu.js.map +1 -1
  261. package/dist/ui/number-input.js +3 -3
  262. package/dist/ui/number-input.js.map +1 -1
  263. package/dist/ui/pagination.js +1 -1
  264. package/dist/ui/pagination.js.map +1 -1
  265. package/dist/ui/popover.d.ts.map +1 -1
  266. package/dist/ui/progress-ring.js +2 -2
  267. package/dist/ui/progress-ring.js.map +1 -1
  268. package/dist/ui/progress.d.ts.map +1 -1
  269. package/dist/ui/progress.js +82 -74
  270. package/dist/ui/progress.js.map +1 -1
  271. package/dist/ui/radio.d.ts.map +1 -1
  272. package/dist/ui/radio.js +32 -31
  273. package/dist/ui/radio.js.map +1 -1
  274. package/dist/ui/search-input.d.ts.map +1 -1
  275. package/dist/ui/search-input.js +28 -27
  276. package/dist/ui/search-input.js.map +1 -1
  277. package/dist/ui/select.d.ts.map +1 -1
  278. package/dist/ui/select.js +67 -66
  279. package/dist/ui/select.js.map +1 -1
  280. package/dist/ui/sheet.js +1 -1
  281. package/dist/ui/sheet.js.map +1 -1
  282. package/dist/ui/sidebar.d.ts.map +1 -1
  283. package/dist/ui/sidebar.js +14 -14
  284. package/dist/ui/sidebar.js.map +1 -1
  285. package/dist/ui/slider.d.ts +63 -9
  286. package/dist/ui/slider.d.ts.map +1 -1
  287. package/dist/ui/slider.js +75 -33
  288. package/dist/ui/slider.js.map +1 -1
  289. package/dist/ui/split-button.d.ts +8 -2
  290. package/dist/ui/split-button.d.ts.map +1 -1
  291. package/dist/ui/split-button.js +49 -95
  292. package/dist/ui/split-button.js.map +1 -1
  293. package/dist/ui/stat-card.d.ts.map +1 -1
  294. package/dist/ui/stat-card.js +89 -88
  295. package/dist/ui/stat-card.js.map +1 -1
  296. package/dist/ui/stat-flash.js +16 -16
  297. package/dist/ui/stepper.d.ts.map +1 -1
  298. package/dist/ui/stepper.js +63 -62
  299. package/dist/ui/stepper.js.map +1 -1
  300. package/dist/ui/surface.d.ts.map +1 -1
  301. package/dist/ui/surface.js +2 -2
  302. package/dist/ui/surface.js.map +1 -1
  303. package/dist/ui/switch.js +1 -1
  304. package/dist/ui/switch.js.map +1 -1
  305. package/dist/ui/table.js +3 -3
  306. package/dist/ui/table.js.map +1 -1
  307. package/dist/ui/tabs.d.ts.map +1 -1
  308. package/dist/ui/tabs.js +68 -67
  309. package/dist/ui/tabs.js.map +1 -1
  310. package/dist/ui/textarea.js +5 -5
  311. package/dist/ui/textarea.js.map +1 -1
  312. package/dist/ui/toast.d.ts.map +1 -1
  313. package/dist/ui/toast.js +196 -195
  314. package/dist/ui/toast.js.map +1 -1
  315. package/dist/ui/toggle.d.ts.map +1 -1
  316. package/dist/ui/toggle.js +26 -24
  317. package/dist/ui/toggle.js.map +1 -1
  318. package/dist/ui/tooltip.d.ts.map +1 -1
  319. package/dist/ui/tooltip.js +37 -36
  320. package/dist/ui/tooltip.js.map +1 -1
  321. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  322. package/docs/components/composed/avatar-group.md +4 -4
  323. package/docs/components/composed/diff.md +10 -2
  324. package/docs/components/composed/schedule-view.md +1 -1
  325. package/docs/components/shell/app-shell.md +132 -0
  326. package/docs/components/ui/avatar.md +1 -1
  327. package/docs/components/ui/button.md +1 -1
  328. package/docs/components/ui/chat.md +7 -1
  329. package/docs/components/ui/color-swatch.md +1 -1
  330. package/docs/components/ui/data-table-toolbar.md +6 -2
  331. package/docs/components/ui/data-table.md +41 -7
  332. package/docs/components/ui/dot.md +1 -1
  333. package/docs/components/ui/progress.md +1 -0
  334. package/docs/components/ui/surface.md +3 -3
  335. package/docs/components/ui/table.md +2 -2
  336. package/docs/recipes/customize-brand.md +58 -0
  337. package/docs/recipes/install-astro.md +1 -0
  338. package/docs/recipes/install-next-app-router.md +1 -0
  339. package/docs/recipes/install-next-pages.md +22 -1
  340. package/docs/recipes/install-remix.md +1 -0
  341. package/docs/recipes/install-tanstack-start.md +1 -0
  342. package/docs/recipes/install-vite.md +2 -0
  343. package/docs/recipes/server-components.md +7 -4
  344. package/docs/recipes/troubleshoot.md +1 -0
  345. package/llms.txt +2 -1
  346. package/make-kit/Guidelines.md +2 -2
  347. package/make-kit/components/button.md +1 -1
  348. package/make-kit/components/card.md +6 -6
  349. package/make-kit/components/surface.md +4 -4
  350. package/make-kit/foundations/color.md +4 -4
  351. package/make-kit/foundations/dark-mode.md +1 -1
  352. package/make-kit/foundations/radius.md +1 -1
  353. package/make-kit/foundations/surfaces.md +9 -9
  354. package/mcp-manifest.json +358 -35
  355. package/package.json +8 -4
  356. package/skill/SKILL.md +12 -6
  357. package/skill/references/components.md +2 -1
  358. package/skill/references/customize-brand.md +58 -0
  359. package/skill/references/server-components.md +7 -4
  360. package/skill/references/setup-astro.md +1 -0
  361. package/skill/references/setup-next-app-router.md +1 -0
  362. package/skill/references/setup-next-pages.md +22 -1
  363. package/skill/references/setup-remix.md +1 -0
  364. package/skill/references/setup-tanstack-start.md +1 -0
  365. package/skill/references/setup-vite.md +2 -0
  366. package/skill/references/troubleshoot.md +1 -0
  367. package/dist/motion/check-motion-provider.d.ts +0 -2
  368. package/dist/motion/check-motion-provider.d.ts.map +0 -1
  369. package/dist/motion/index.js.map +0 -1
  370. package/dist/primitives/react-toast.d.ts +0 -120
  371. package/dist/ui/charts/_internal/scales.d.ts +0 -5
  372. package/dist/ui/charts/_internal/scales.d.ts.map +0 -1
  373. package/dist/ui/lib/slot.d.ts +0 -8
  374. package/dist/ui/lib/slot.d.ts.map +0 -1
@@ -17,7 +17,7 @@ var T = _.forwardRef(({ className: e, children: n, ...r }, i) => {
17
17
  return /* @__PURE__ */ y("header", {
18
18
  ...r,
19
19
  ref: i,
20
- className: t("z-sticky w-full border-b border-surface-border-strong bg-surface-chrome px-ds-05 py-ds-04 md:px-ds-06", a ? "grid grid-cols-[1fr_auto_1fr] items-center" : "flex items-center", e),
20
+ className: t("z-sticky w-full border-b border-surface-border-strong bg-surface-base px-ds-05 py-ds-04 md:px-ds-06", a ? "grid grid-cols-[1fr_auto_1fr] items-center" : "flex items-center", e),
21
21
  children: n
22
22
  });
23
23
  });
@@ -60,7 +60,7 @@ var j = _.forwardRef(({ icon: n, tooltip: r, className: i, ...a }, s) => /* @__P
60
60
  ref: s,
61
61
  type: "button",
62
62
  "aria-label": r,
63
- className: t("flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-raised-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-raised-active active:scale-90 duration-fast-01 ease-productive-standard", i),
63
+ className: t("flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-surface-border-interactive bg-surface-panel-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-panel-active active:scale-90 duration-fast-01 ease-productive-standard", i),
64
64
  ...a,
65
65
  children: /* @__PURE__ */ y("span", {
66
66
  className: "[&>svg]:h-ico-sm [&>svg]:w-ico-sm",
@@ -100,7 +100,7 @@ var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, c
100
100
  src: T.image,
101
101
  alt: T.name
102
102
  }) : null, /* @__PURE__ */ y(i, {
103
- className: "bg-surface-raised-hover text-surface-fg",
103
+ className: "bg-surface-panel-hover text-surface-fg",
104
104
  children: T.name?.charAt(0).toUpperCase()
105
105
  })]
106
106
  })
@@ -128,7 +128,7 @@ var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, c
128
128
  })]
129
129
  }),
130
130
  /* @__PURE__ */ b(l, {
131
- className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
131
+ className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover",
132
132
  onClick: () => E?.("/profile"),
133
133
  children: [/* @__PURE__ */ y(n, {
134
134
  icon: w,
@@ -147,7 +147,7 @@ var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, c
147
147
  info: "text-info-11"
148
148
  }[n.color] ?? "text-surface-fg-muted" : "text-surface-fg-muted";
149
149
  return /* @__PURE__ */ b(_.Fragment, { children: [n.separator && /* @__PURE__ */ y(u, { className: "bg-surface-border" }), /* @__PURE__ */ b(l, {
150
- className: t("flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised", n.disabled && "pointer-events-none opacity-action-disabled"),
150
+ className: t("flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover", n.disabled && "pointer-events-none opacity-action-disabled"),
151
151
  disabled: n.disabled,
152
152
  onClick: () => {
153
153
  n.disabled || (n.onClick ? n.onClick() : n.href && E?.(n.href));
@@ -172,7 +172,7 @@ var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, c
172
172
  })] }, n.label + r);
173
173
  }),
174
174
  /* @__PURE__ */ b(l, {
175
- className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
175
+ className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover",
176
176
  onClick: M,
177
177
  children: [j === "dark" ? /* @__PURE__ */ y(n, {
178
178
  icon: C,
@@ -188,7 +188,7 @@ var N = _.forwardRef(({ user: T, onNavigate: E, onLogout: D, userMenuItems: O, c
188
188
  })]
189
189
  }),
190
190
  D && /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(u, { className: "bg-surface-border" }), /* @__PURE__ */ b(l, {
191
- className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised",
191
+ className: "flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover",
192
192
  onClick: D,
193
193
  children: [/* @__PURE__ */ y(n, {
194
194
  icon: x,
@@ -1 +1 @@
1
- {"version":3,"file":"top-bar.js","names":[],"sources":["../../src/shell/top-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * TopBar v2 — Composition-based application top bar.\n *\n * Subcomponents: TopBar.Left, TopBar.Center, TopBar.Right,\n * TopBar.Section, TopBar.IconButton, TopBar.Title, TopBar.UserMenu.\n */\nimport { IconLogout, IconMoon, IconSun,IconUser } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { useColorMode } from '../hooks/use-color-mode'\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\nimport { TruncatedText } from '../ui/truncated-text'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface TopBarUser {\n name: string\n email?: string\n image?: string | null\n}\n\nexport interface UserMenuItem {\n /** Display label */\n label: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n /** Navigate via onNavigate when clicked */\n href?: string\n /** Custom click handler */\n onClick?: () => void\n /** Render a separator before this item */\n separator?: boolean\n /** Text color semantic token (e.g. \"error\") — maps to text-{color} */\n color?: string\n /** Badge content — string for count, true for dot indicator */\n badge?: string | boolean\n /** Whether the item is disabled */\n disabled?: boolean\n}\n\n// -----------------------------------------------------------------------\n// TopBar (root)\n// -----------------------------------------------------------------------\n\ninterface TopBarRootProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n className?: string\n}\n\nconst TopBarRoot = React.forwardRef<HTMLElement, TopBarRootProps>(\n ({ className, children, ...props }, ref) => {\n // Detect if a Center zone is present to switch to grid layout\n const hasCenter = React.Children.toArray(children).some(\n (child) => React.isValidElement(child) && child.type === TopBarCenter,\n )\n\n return (\n <header\n {...props}\n ref={ref}\n className={cn(\n 'z-sticky w-full border-b border-surface-border-strong bg-surface-chrome px-ds-05 py-ds-04 md:px-ds-06',\n hasCenter\n ? 'grid grid-cols-[1fr_auto_1fr] items-center'\n : 'flex items-center',\n className,\n )}\n >\n {children}\n </header>\n )\n },\n)\nTopBarRoot.displayName = 'TopBar'\n\n// -----------------------------------------------------------------------\n// TopBar.Left\n// -----------------------------------------------------------------------\n\ninterface TopBarLeftProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarLeft = React.forwardRef<HTMLDivElement, TopBarLeftProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarLeft.displayName = 'TopBar.Left'\n\n// -----------------------------------------------------------------------\n// TopBar.Center\n// -----------------------------------------------------------------------\n\ninterface TopBarCenterProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarCenter = React.forwardRef<HTMLDivElement, TopBarCenterProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center justify-center px-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarCenter.displayName = 'TopBar.Center'\n\n// -----------------------------------------------------------------------\n// TopBar.Right\n// -----------------------------------------------------------------------\n\ninterface TopBarRightProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarRight = React.forwardRef<HTMLDivElement, TopBarRightProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('ml-auto flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarRight.displayName = 'TopBar.Right'\n\n// -----------------------------------------------------------------------\n// TopBar.Section\n// -----------------------------------------------------------------------\n\nconst gapMap = {\n tight: 'gap-ds-02',\n default: 'gap-ds-04',\n loose: 'gap-ds-06',\n} as const\n\ninterface TopBarSectionProps extends React.HTMLAttributes<HTMLDivElement> {\n gap?: keyof typeof gapMap\n children: React.ReactNode\n}\n\nconst TopBarSection = React.forwardRef<HTMLDivElement, TopBarSectionProps>(\n ({ gap = 'default', className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center', gapMap[gap], className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarSection.displayName = 'TopBar.Section'\n\n// -----------------------------------------------------------------------\n// TopBar.IconButton\n// -----------------------------------------------------------------------\n\ninterface TopBarIconButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon: IconInput\n tooltip: string\n}\n\nconst TopBarIconButton = React.forwardRef<\n HTMLButtonElement,\n TopBarIconButtonProps\n>(({ icon, tooltip, className, ...props }, ref) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n aria-label={tooltip}\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-card-strong bg-surface-raised-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-raised-active active:scale-90 duration-fast-01 ease-productive-standard',\n className,\n )}\n {...props}\n >\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n))\nTopBarIconButton.displayName = 'TopBar.IconButton'\n\n// -----------------------------------------------------------------------\n// TopBar.Title\n// -----------------------------------------------------------------------\n\ninterface TopBarTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n children: React.ReactNode\n}\n\nconst TopBarTitle = React.forwardRef<HTMLHeadingElement, TopBarTitleProps>(\n ({ className, children, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'hidden text-heading-xs text-surface-fg md:block',\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n)\nTopBarTitle.displayName = 'TopBar.Title'\n\n// -----------------------------------------------------------------------\n// TopBar.UserMenu\n// -----------------------------------------------------------------------\n\ninterface TopBarUserMenuProps {\n user: TopBarUser\n onNavigate?: (path: string) => void\n onLogout?: () => void\n userMenuItems?: UserMenuItem[]\n className?: string\n}\n\nconst TopBarUserMenu = React.forwardRef<HTMLButtonElement, TopBarUserMenuProps>(\n ({ user, onNavigate, onLogout, userMenuItems, className }, ref) => {\n const { colorMode, toggleColorMode } = useColorMode()\n\n return (\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n className={cn('flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2', className)}\n >\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus cursor-pointer\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-raised-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n User Menu\n </TooltipContent>\n </Tooltip>\n\n <DropdownMenuContent\n className=\"w-[200px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n sideOffset={8}\n align=\"end\"\n >\n {/* User Info */}\n <div className=\"border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <p className=\"text-body-md text-surface-fg\">{user.name}</p>\n {user.email && (\n <TruncatedText as=\"p\" mode=\"middle\" className=\"text-body-sm text-surface-fg-subtle\">\n {user.email}\n </TruncatedText>\n )}\n </div>\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={() => onNavigate?.('/profile')}\n >\n <Icon icon={IconUser} size=\"sm\" className=\"text-surface-fg-muted\" />\n <span className=\"text-body-md text-surface-fg-muted\">Profile</span>\n </DropdownMenuItem>\n\n {/* Custom user menu items */}\n {userMenuItems?.map((item, index) => {\n const colorMap: Record<string, string> = {\n error: 'text-error-11',\n success: 'text-success-11',\n warning: 'text-warning-11',\n info: 'text-info-11',\n }\n const textColor = item.color\n ? (colorMap[item.color] ?? 'text-surface-fg-muted')\n : 'text-surface-fg-muted'\n return (\n <React.Fragment key={item.label + index}>\n {item.separator && (\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n )}\n <DropdownMenuItem\n className={cn(\n 'flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised',\n item.disabled && 'pointer-events-none opacity-action-disabled',\n )}\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return\n if (item.onClick) item.onClick()\n else if (item.href) onNavigate?.(item.href)\n }}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm',\n textColor,\n )}\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <span className={cn('text-body-md', textColor)}>\n {item.label}\n </span>\n {item.badge != null &&\n item.badge !== false &&\n (typeof item.badge === 'string' ? (\n <span className=\"ml-auto inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-pill bg-error-9 px-ds-02 text-[10px] font-semibold leading-none text-error-fg\">\n {item.badge}\n </span>\n ) : (\n <span className=\"ml-auto h-[8px] w-[8px] rounded-pill bg-error-9\" />\n ))}\n </DropdownMenuItem>\n </React.Fragment>\n )\n })}\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={toggleColorMode}\n >\n {colorMode === 'dark' ? (\n <Icon icon={IconSun} size=\"sm\" className=\"text-surface-fg-muted\" />\n ) : (\n <Icon icon={IconMoon} size=\"sm\" className=\"text-surface-fg-muted\" />\n )}\n <span className=\"text-body-md text-surface-fg-muted\">\n {colorMode === 'dark' ? 'Light Mode' : 'Dark Mode'}\n </span>\n </DropdownMenuItem>\n\n {onLogout && (\n <>\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-raised\"\n onClick={onLogout}\n >\n <Icon icon={IconLogout} size=\"sm\" className=\"text-error-11\" />\n <span className=\"text-body-md text-error-11\">Logout</span>\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n },\n)\nTopBarUserMenu.displayName = 'TopBar.UserMenu'\n\n// -----------------------------------------------------------------------\n// Compound export\n// -----------------------------------------------------------------------\n\nexport type TopBarProps = TopBarRootProps\n\nconst TopBar = Object.assign(TopBarRoot, {\n Left: TopBarLeft,\n Center: TopBarCenter,\n Right: TopBarRight,\n Section: TopBarSection,\n IconButton: TopBarIconButton,\n Title: TopBarTitle,\n UserMenu: TopBarUserMenu,\n})\n\nexport { TopBar }\n"],"mappings":"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"}
1
+ {"version":3,"file":"top-bar.js","names":[],"sources":["../../src/shell/top-bar.tsx"],"sourcesContent":["'use client'\n\n/**\n * TopBar v2 — Composition-based application top bar.\n *\n * Subcomponents: TopBar.Left, TopBar.Center, TopBar.Right,\n * TopBar.Section, TopBar.IconButton, TopBar.Title, TopBar.UserMenu.\n */\nimport { IconLogout, IconMoon, IconSun,IconUser } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { useColorMode } from '../hooks/use-color-mode'\nimport { Avatar, AvatarFallback, AvatarImage } from '../ui/avatar'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../ui/dropdown-menu'\nimport { Icon } from '../ui/icon'\nimport { IconProvider } from '../ui/icon-context'\nimport type { IconInput } from '../ui/lib/icon-input'\nimport { normalizeIcon } from '../ui/lib/normalize-icon'\nimport { cn } from '../ui/lib/utils'\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '../ui/tooltip'\nimport { TruncatedText } from '../ui/truncated-text'\n\n// -----------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------\n\nexport interface TopBarUser {\n name: string\n email?: string\n image?: string | null\n}\n\nexport interface UserMenuItem {\n /** Display label */\n label: string\n /** Optional icon. Accepts any `IconInput`. */\n icon?: IconInput\n /** Navigate via onNavigate when clicked */\n href?: string\n /** Custom click handler */\n onClick?: () => void\n /** Render a separator before this item */\n separator?: boolean\n /** Text color semantic token (e.g. \"error\") — maps to text-{color} */\n color?: string\n /** Badge content — string for count, true for dot indicator */\n badge?: string | boolean\n /** Whether the item is disabled */\n disabled?: boolean\n}\n\n// -----------------------------------------------------------------------\n// TopBar (root)\n// -----------------------------------------------------------------------\n\ninterface TopBarRootProps extends React.HTMLAttributes<HTMLElement> {\n children: React.ReactNode\n className?: string\n}\n\nconst TopBarRoot = React.forwardRef<HTMLElement, TopBarRootProps>(\n ({ className, children, ...props }, ref) => {\n // Detect if a Center zone is present to switch to grid layout\n const hasCenter = React.Children.toArray(children).some(\n (child) => React.isValidElement(child) && child.type === TopBarCenter,\n )\n\n return (\n <header\n {...props}\n ref={ref}\n className={cn(\n 'z-sticky w-full border-b border-surface-border-strong bg-surface-base px-ds-05 py-ds-04 md:px-ds-06',\n hasCenter\n ? 'grid grid-cols-[1fr_auto_1fr] items-center'\n : 'flex items-center',\n className,\n )}\n >\n {children}\n </header>\n )\n },\n)\nTopBarRoot.displayName = 'TopBar'\n\n// -----------------------------------------------------------------------\n// TopBar.Left\n// -----------------------------------------------------------------------\n\ninterface TopBarLeftProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarLeft = React.forwardRef<HTMLDivElement, TopBarLeftProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarLeft.displayName = 'TopBar.Left'\n\n// -----------------------------------------------------------------------\n// TopBar.Center\n// -----------------------------------------------------------------------\n\ninterface TopBarCenterProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarCenter = React.forwardRef<HTMLDivElement, TopBarCenterProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center justify-center px-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarCenter.displayName = 'TopBar.Center'\n\n// -----------------------------------------------------------------------\n// TopBar.Right\n// -----------------------------------------------------------------------\n\ninterface TopBarRightProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nconst TopBarRight = React.forwardRef<HTMLDivElement, TopBarRightProps>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('ml-auto flex items-center gap-ds-04', className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarRight.displayName = 'TopBar.Right'\n\n// -----------------------------------------------------------------------\n// TopBar.Section\n// -----------------------------------------------------------------------\n\nconst gapMap = {\n tight: 'gap-ds-02',\n default: 'gap-ds-04',\n loose: 'gap-ds-06',\n} as const\n\ninterface TopBarSectionProps extends React.HTMLAttributes<HTMLDivElement> {\n gap?: keyof typeof gapMap\n children: React.ReactNode\n}\n\nconst TopBarSection = React.forwardRef<HTMLDivElement, TopBarSectionProps>(\n ({ gap = 'default', className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center', gapMap[gap], className)}\n {...props}\n >\n {children}\n </div>\n ),\n)\nTopBarSection.displayName = 'TopBar.Section'\n\n// -----------------------------------------------------------------------\n// TopBar.IconButton\n// -----------------------------------------------------------------------\n\ninterface TopBarIconButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n icon: IconInput\n tooltip: string\n}\n\nconst TopBarIconButton = React.forwardRef<\n HTMLButtonElement,\n TopBarIconButtonProps\n>(({ icon, tooltip, className, ...props }, ref) => (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n aria-label={tooltip}\n className={cn(\n 'flex h-ds-sm-plus w-ds-sm-plus items-center justify-center rounded-pill border border-surface-border-interactive bg-surface-panel-hover text-surface-fg-muted transition-[color,background-color,border-color,transform] hover:bg-surface-panel-active active:scale-90 duration-fast-01 ease-productive-standard',\n className,\n )}\n {...props}\n >\n <span className=\"[&>svg]:h-ico-sm [&>svg]:w-ico-sm\" aria-hidden=\"true\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n {tooltip}\n </TooltipContent>\n </Tooltip>\n))\nTopBarIconButton.displayName = 'TopBar.IconButton'\n\n// -----------------------------------------------------------------------\n// TopBar.Title\n// -----------------------------------------------------------------------\n\ninterface TopBarTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n children: React.ReactNode\n}\n\nconst TopBarTitle = React.forwardRef<HTMLHeadingElement, TopBarTitleProps>(\n ({ className, children, ...props }, ref) => (\n <h2\n ref={ref}\n className={cn(\n 'hidden text-heading-xs text-surface-fg md:block',\n className,\n )}\n {...props}\n >\n {children}\n </h2>\n ),\n)\nTopBarTitle.displayName = 'TopBar.Title'\n\n// -----------------------------------------------------------------------\n// TopBar.UserMenu\n// -----------------------------------------------------------------------\n\ninterface TopBarUserMenuProps {\n user: TopBarUser\n onNavigate?: (path: string) => void\n onLogout?: () => void\n userMenuItems?: UserMenuItem[]\n className?: string\n}\n\nconst TopBarUserMenu = React.forwardRef<HTMLButtonElement, TopBarUserMenuProps>(\n ({ user, onNavigate, onLogout, userMenuItems, className }, ref) => {\n const { colorMode, toggleColorMode } = useColorMode()\n\n return (\n <DropdownMenu>\n <Tooltip>\n <TooltipTrigger asChild>\n <DropdownMenuTrigger asChild>\n <button\n ref={ref}\n type=\"button\"\n className={cn('flex items-center gap-ds-03 outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9 focus-visible:ring-offset-2', className)}\n >\n <Avatar className=\"h-ds-sm-plus w-ds-sm-plus cursor-pointer\">\n {user.image ? (\n <AvatarImage src={user.image} alt={user.name} />\n ) : null}\n <AvatarFallback className=\"bg-surface-panel-hover text-surface-fg\">\n {user.name?.charAt(0).toUpperCase()}\n </AvatarFallback>\n </Avatar>\n </button>\n </DropdownMenuTrigger>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\" align=\"center\">\n User Menu\n </TooltipContent>\n </Tooltip>\n\n <DropdownMenuContent\n className=\"w-[200px] rounded-overlay-lg bg-surface-overlay p-0 shadow-floating\"\n sideOffset={8}\n align=\"end\"\n >\n {/* User Info */}\n <div className=\"border-b border-surface-border-strong px-ds-05 py-ds-04\">\n <p className=\"text-body-md text-surface-fg\">{user.name}</p>\n {user.email && (\n <TruncatedText as=\"p\" mode=\"middle\" className=\"text-body-sm text-surface-fg-subtle\">\n {user.email}\n </TruncatedText>\n )}\n </div>\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover\"\n onClick={() => onNavigate?.('/profile')}\n >\n <Icon icon={IconUser} size=\"sm\" className=\"text-surface-fg-muted\" />\n <span className=\"text-body-md text-surface-fg-muted\">Profile</span>\n </DropdownMenuItem>\n\n {/* Custom user menu items */}\n {userMenuItems?.map((item, index) => {\n const colorMap: Record<string, string> = {\n error: 'text-error-11',\n success: 'text-success-11',\n warning: 'text-warning-11',\n info: 'text-info-11',\n }\n const textColor = item.color\n ? (colorMap[item.color] ?? 'text-surface-fg-muted')\n : 'text-surface-fg-muted'\n return (\n <React.Fragment key={item.label + index}>\n {item.separator && (\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n )}\n <DropdownMenuItem\n className={cn(\n 'flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover',\n item.disabled && 'pointer-events-none opacity-action-disabled',\n )}\n disabled={item.disabled}\n onClick={() => {\n if (item.disabled) return\n if (item.onClick) item.onClick()\n else if (item.href) onNavigate?.(item.href)\n }}\n >\n {item.icon && (\n <span\n className={cn(\n '[&>svg]:h-ico-sm [&>svg]:w-ico-sm',\n textColor,\n )}\n >\n <IconProvider size=\"sm\">{normalizeIcon(item.icon)}</IconProvider>\n </span>\n )}\n <span className={cn('text-body-md', textColor)}>\n {item.label}\n </span>\n {item.badge != null &&\n item.badge !== false &&\n (typeof item.badge === 'string' ? (\n <span className=\"ml-auto inline-flex h-[18px] min-w-[18px] items-center justify-center rounded-pill bg-error-9 px-ds-02 text-[10px] font-semibold leading-none text-error-fg\">\n {item.badge}\n </span>\n ) : (\n <span className=\"ml-auto h-[8px] w-[8px] rounded-pill bg-error-9\" />\n ))}\n </DropdownMenuItem>\n </React.Fragment>\n )\n })}\n\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover\"\n onClick={toggleColorMode}\n >\n {colorMode === 'dark' ? (\n <Icon icon={IconSun} size=\"sm\" className=\"text-surface-fg-muted\" />\n ) : (\n <Icon icon={IconMoon} size=\"sm\" className=\"text-surface-fg-muted\" />\n )}\n <span className=\"text-body-md text-surface-fg-muted\">\n {colorMode === 'dark' ? 'Light Mode' : 'Dark Mode'}\n </span>\n </DropdownMenuItem>\n\n {onLogout && (\n <>\n <DropdownMenuSeparator className=\"bg-surface-border\" />\n <DropdownMenuItem\n className=\"flex w-full cursor-pointer items-center gap-ds-03 px-ds-05 py-ds-04 hover:bg-surface-panel-hover\"\n onClick={onLogout}\n >\n <Icon icon={IconLogout} size=\"sm\" className=\"text-error-11\" />\n <span className=\"text-body-md text-error-11\">Logout</span>\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n )\n },\n)\nTopBarUserMenu.displayName = 'TopBar.UserMenu'\n\n// -----------------------------------------------------------------------\n// Compound export\n// -----------------------------------------------------------------------\n\nexport type TopBarProps = TopBarRootProps\n\nconst TopBar = Object.assign(TopBarRoot, {\n Left: TopBarLeft,\n Center: TopBarCenter,\n Right: TopBarRight,\n Section: TopBarSection,\n IconButton: TopBarIconButton,\n Title: TopBarTitle,\n UserMenu: TopBarUserMenu,\n})\n\nexport { TopBar }\n"],"mappings":"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"}
@@ -12,6 +12,29 @@ export interface ScaleOptions {
12
12
  peakChroma: number;
13
13
  /** When true, keeps chroma very low across all steps */
14
14
  isNeutral?: boolean;
15
+ /**
16
+ * Per-ramp lightness corrections for the solid steps, in OKLCH L units.
17
+ *
18
+ * Steps 9 and 10 are the solid fills that carry text. The generic curve does
19
+ * not clear WCAG for every hue — green and blue at the default dark L of 0.63
20
+ * are too light under white text — so the ramps used as semantic intents carry
21
+ * a hand-verified correction.
22
+ *
23
+ * Discovered 2026-08-18: without these, `generateScale` could not reproduce the
24
+ * palette in `primitives.css`. Regenerating a ramp silently reverted the
25
+ * contrast fix on pink, red, green, blue and neutral.
26
+ *
27
+ * Decorative ramps (purple, teal, amber, slate, indigo, cyan, orange, emerald)
28
+ * need no correction — they never sit under text.
29
+ */
30
+ correction?: {
31
+ /** Added to step 9's light-mode L */
32
+ light9?: number;
33
+ /** Added to step 9's dark-mode L */
34
+ dark9?: number;
35
+ /** Added to step 10's dark-mode L */
36
+ dark10?: number;
37
+ };
15
38
  }
16
39
  export interface ScaleStep {
17
40
  /** 1-based step number */
@@ -24,10 +47,20 @@ export interface Scale {
24
47
  dark: ScaleStep[];
25
48
  }
26
49
  export declare function generateScale(options: ScaleOptions): Scale;
50
+ /**
51
+ * Ramp seeds. The five ramps that back semantic intents carry `correction`
52
+ * values on steps 9/10 — the solid fills that sit under text. Verified against
53
+ * `primitives.css` by `figma-plugin/verify-parity.mjs`; without them the
54
+ * generator does not reproduce the shipped palette.
55
+ */
27
56
  export declare const BRAND_PALETTES: {
28
57
  readonly pink: {
29
58
  readonly hue: 360;
30
59
  readonly peakChroma: 0.19;
60
+ readonly correction: {
61
+ readonly dark9: -0.09;
62
+ readonly dark10: -0.09;
63
+ };
31
64
  };
32
65
  readonly purple: {
33
66
  readonly hue: 300;
@@ -37,14 +70,26 @@ export declare const BRAND_PALETTES: {
37
70
  readonly hue: 350;
38
71
  readonly peakChroma: 0.01;
39
72
  readonly isNeutral: true;
73
+ readonly correction: {
74
+ readonly light9: -0.01;
75
+ };
40
76
  };
41
77
  readonly red: {
42
78
  readonly hue: 25;
43
79
  readonly peakChroma: 0.18;
80
+ readonly correction: {
81
+ readonly dark9: -0.09;
82
+ readonly dark10: -0.09;
83
+ };
44
84
  };
45
85
  readonly green: {
46
86
  readonly hue: 145;
47
87
  readonly peakChroma: 0.14;
88
+ readonly correction: {
89
+ readonly light9: -0.03;
90
+ readonly dark9: -0.09;
91
+ readonly dark10: -0.09;
92
+ };
48
93
  };
49
94
  readonly yellow: {
50
95
  readonly hue: 85;
@@ -53,6 +98,10 @@ export declare const BRAND_PALETTES: {
53
98
  readonly blue: {
54
99
  readonly hue: 240;
55
100
  readonly peakChroma: 0.12;
101
+ readonly correction: {
102
+ readonly dark9: -0.09;
103
+ readonly dark10: -0.09;
104
+ };
56
105
  };
57
106
  readonly teal: {
58
107
  readonly hue: 175;
@@ -1 +1 @@
1
- {"version":3,"file":"generate-scale.d.ts","sourceRoot":"","sources":["../../src/tokens/generate-scale.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,IAAI,EAAE,SAAS,EAAE,CAAA;CAClB;AAyGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,KAAK,CAsC1D;AAMD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAesB,CAAA"}
1
+ {"version":3,"file":"generate-scale.d.ts","sourceRoot":"","sources":["../../src/tokens/generate-scale.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,MAAM,WAAW,YAAY;IAC3B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE;QACX,qCAAqC;QACrC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,oCAAoC;QACpC,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,qCAAqC;QACrC,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAED,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,IAAI,EAAE,SAAS,EAAE,CAAA;CAClB;AAyGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,KAAK,CA0C1D;AAMD;;;;;GAKG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAesB,CAAA"}
@@ -18,6 +18,7 @@
18
18
  */
19
19
  @import './primitives.css';
20
20
  @import './semantic.css';
21
+ @import './palettes.css';
21
22
  @import './typography.css';
22
23
  @import './typography-semantic.css';
23
24
  @import './base.css';
@@ -0,0 +1,292 @@
1
+ /* ═══════════════════════════════════════════════════════════════════
2
+ PALETTE — one indirection so a component references *a* colour role
3
+ rather than *a* colour.
4
+
5
+ A component styles itself once:
6
+
7
+ bg-palette-solid text-palette-fg hover:bg-palette-solid-hover
8
+
9
+ and the palette is chosen by an ancestor or by the element itself:
10
+
11
+ <button data-palette="error" class="bg-palette-solid …">
12
+
13
+ This replaces the variants × colours cross-product. Adding a colour is
14
+ one block here, not N rows in every component. See
15
+ docs/plans/2026-08-27-colour-palette-indirection.md.
16
+
17
+ WHY NAMED ROLES AND NOT palette-1..12
18
+ -------------------------------------
19
+ `neutral` does not follow the chromatic mapping: its solid is step 5
20
+ (step 9 is a mid grey that reads as disabled), its on-solid text is
21
+ `surface-fg`, and half its roles resolve from the *surface* family
22
+ rather than a ramp. Under numeric naming it would have to claim
23
+ `--color-palette-9: var(--color-neutral-5)`, which is a lie in the
24
+ token name. Roles let each palette resolve from wherever is correct.
25
+
26
+ THEME
27
+ -----
28
+ Nothing here is duplicated per theme. Every source token — the
29
+ `--color-*` semantics and the private primitives alike — is already
30
+ redefined under `.dark`, so a palette inherits dark mode for free.
31
+
32
+ CASCADE
33
+ -------
34
+ `[data-palette]` inherits, so a palette set on a container themes
35
+ everything inside it. An explicit `data-palette` on a descendant wins,
36
+ because it is the nearer rule. Radix Themes and Chakra both behave this
37
+ way. Unlayered rules beat `@layer theme`, so these always override the
38
+ defaults below regardless of import order.
39
+ ═══════════════════════════════════════════════════════════════════ */
40
+
41
+ /* The contract. Eleven roles. Defaults are `accent`, matching the current
42
+ default of every component that has a `color` prop.
43
+
44
+ `solid-active` and `text` resolve to the same step on every chromatic
45
+ palette, which looks redundant until you reach `neutral`, where one is
46
+ `neutral-8` and the other is `surface-fg-muted`. Two roles, one value, is
47
+ exactly what a role contract is for. */
48
+ @theme {
49
+ --color-palette-subtle: var(--color-accent-2); /* faintest tinted ground */
50
+ --color-palette-soft: var(--color-accent-3); /* soft fill */
51
+ --color-palette-soft-hover: var(--color-accent-4); /* soft fill, hovered */
52
+ --color-palette-soft-active: var(--color-accent-5); /* soft fill, pressed */
53
+ --color-palette-border-subtle: var(--color-accent-6); /* divider inside a coloured thing */
54
+ /* The object's edge. Step 4, not 7 — a deliberate call to keep coloured
55
+ edges a whisper. Measured 1.37–1.49:1 against white, where the plain
56
+ uncoloured edge we already ship is 1.23:1, so the colour barely reads.
57
+ Recorded as PALETTE-EDGE-WHISPER in docs/deviations.md. */
58
+ --color-palette-border: var(--color-accent-4); --color-palette-border-strong: var(--color-accent-7);
59
+ --color-palette-solid: var(--color-accent-9); /* filled control */
60
+ --color-palette-solid-hover: var(--color-accent-10); /* filled control, hovered */
61
+ --color-palette-solid-active: var(--color-accent-11); /* filled control, pressed */
62
+ --color-palette-text: var(--color-accent-11); /* coloured text on a light ground */
63
+ --color-palette-fg: var(--color-accent-fg); /* text ON the solid fill */
64
+ }
65
+
66
+ /* Derived on-solid text, for palettes we do not ship.
67
+
68
+ Declared BEFORE the built-ins deliberately: every block below has the
69
+ same specificity (0,1,0), so source order decides and each built-in
70
+ overwrites this with its measured value. Only a consumer-registered
71
+ palette that omits `--color-palette-fg` keeps it.
72
+
73
+ Black or white by the solid's lightness. Readable, but blunt on
74
+ mid-tone brand colours — supply the value explicitly and you get
75
+ exactly what you chose. `contrast-color()` would be the purpose-built
76
+ answer; it is Safari 26+ only, so not yet. */
77
+ @supports (color: oklch(from white l c h)) {
78
+ [data-palette] {
79
+ --color-palette-fg: oklch(from var(--color-palette-solid)
80
+ clamp(0, (0.62 - l) * 1000, 1) 0 0);
81
+ }
82
+ }
83
+
84
+ /* ───────────────────────────────────────────────────────────────────
85
+ Brand-following palettes — resolve from the SEMANTIC layer, so a
86
+ consumer who overrides `--color-accent-*` to rebrand gets it here too.
87
+ ─────────────────────────────────────────────────────────────────── */
88
+
89
+ [data-palette='accent'] {
90
+ --color-palette-subtle: var(--color-accent-2);
91
+ --color-palette-soft: var(--color-accent-3);
92
+ --color-palette-soft-hover: var(--color-accent-4);
93
+ --color-palette-soft-active: var(--color-accent-5);
94
+ --color-palette-border-subtle: var(--color-accent-6);
95
+ --color-palette-border: var(--color-accent-4); --color-palette-border-strong: var(--color-accent-7);
96
+ --color-palette-solid: var(--color-accent-9);
97
+ --color-palette-solid-hover: var(--color-accent-10);
98
+ --color-palette-solid-active: var(--color-accent-11);
99
+ --color-palette-text: var(--color-accent-11);
100
+ --color-palette-fg: var(--color-accent-fg);
101
+ }
102
+
103
+ [data-palette='secondary'] {
104
+ --color-palette-subtle: var(--color-secondary-2);
105
+ --color-palette-soft: var(--color-secondary-3);
106
+ --color-palette-soft-hover: var(--color-secondary-4);
107
+ --color-palette-soft-active: var(--color-secondary-5);
108
+ --color-palette-border-subtle: var(--color-secondary-6);
109
+ --color-palette-border: var(--color-secondary-4); --color-palette-border-strong: var(--color-secondary-7);
110
+ --color-palette-solid: var(--color-secondary-9);
111
+ --color-palette-solid-hover: var(--color-secondary-10);
112
+ --color-palette-solid-active: var(--color-secondary-11);
113
+ --color-palette-text: var(--color-secondary-11);
114
+ --color-palette-fg: var(--color-secondary-fg);
115
+ }
116
+
117
+ [data-palette='error'] {
118
+ --color-palette-subtle: var(--color-error-2);
119
+ --color-palette-soft: var(--color-error-3);
120
+ --color-palette-soft-hover: var(--color-error-4);
121
+ --color-palette-soft-active: var(--color-error-5);
122
+ --color-palette-border-subtle: var(--color-error-6);
123
+ --color-palette-border: var(--color-error-4); --color-palette-border-strong: var(--color-error-7);
124
+ --color-palette-solid: var(--color-error-9);
125
+ --color-palette-solid-hover: var(--color-error-10);
126
+ --color-palette-solid-active: var(--color-error-11);
127
+ --color-palette-text: var(--color-error-11);
128
+ --color-palette-fg: var(--color-error-fg);
129
+ }
130
+
131
+ [data-palette='success'] {
132
+ --color-palette-subtle: var(--color-success-2);
133
+ --color-palette-soft: var(--color-success-3);
134
+ --color-palette-soft-hover: var(--color-success-4);
135
+ --color-palette-soft-active: var(--color-success-5);
136
+ --color-palette-border-subtle: var(--color-success-6);
137
+ --color-palette-border: var(--color-success-4); --color-palette-border-strong: var(--color-success-7);
138
+ --color-palette-solid: var(--color-success-9);
139
+ --color-palette-solid-hover: var(--color-success-10);
140
+ --color-palette-solid-active: var(--color-success-11);
141
+ --color-palette-text: var(--color-success-11);
142
+ --color-palette-fg: var(--color-success-fg);
143
+ }
144
+
145
+ [data-palette='warning'] {
146
+ --color-palette-subtle: var(--color-warning-2);
147
+ --color-palette-soft: var(--color-warning-3);
148
+ --color-palette-soft-hover: var(--color-warning-4);
149
+ --color-palette-soft-active: var(--color-warning-5);
150
+ --color-palette-border-subtle: var(--color-warning-6);
151
+ --color-palette-border: var(--color-warning-4); --color-palette-border-strong: var(--color-warning-7);
152
+ --color-palette-solid: var(--color-warning-9);
153
+ --color-palette-solid-hover: var(--color-warning-10);
154
+ --color-palette-solid-active: var(--color-warning-11);
155
+ --color-palette-text: var(--color-warning-11);
156
+ --color-palette-fg: var(--color-warning-fg);
157
+ }
158
+
159
+ [data-palette='info'] {
160
+ --color-palette-subtle: var(--color-info-2);
161
+ --color-palette-soft: var(--color-info-3);
162
+ --color-palette-soft-hover: var(--color-info-4);
163
+ --color-palette-soft-active: var(--color-info-5);
164
+ --color-palette-border-subtle: var(--color-info-6);
165
+ --color-palette-border: var(--color-info-4); --color-palette-border-strong: var(--color-info-7);
166
+ --color-palette-solid: var(--color-info-9);
167
+ --color-palette-solid-hover: var(--color-info-10);
168
+ --color-palette-solid-active: var(--color-info-11);
169
+ --color-palette-text: var(--color-info-11);
170
+ --color-palette-fg: var(--color-info-fg);
171
+ }
172
+
173
+ /* `neutral` is the reason this file uses roles rather than step numbers.
174
+ Its solid is step 5 — step 9 is a mid grey that reads as a disabled
175
+ control, not a filled one — and more than half its roles resolve from
176
+ the SURFACE family, which is a different token tree entirely. This
177
+ mirrors what `Component/Intent` already does in the Figma library. */
178
+ [data-palette='neutral'] {
179
+ --color-palette-subtle: var(--color-surface-panel-hover);
180
+ --color-palette-soft: var(--color-surface-panel-hover);
181
+ --color-palette-soft-hover: var(--color-surface-panel-active);
182
+ --color-palette-soft-active: var(--color-neutral-5);
183
+ --color-palette-border-subtle: var(--color-surface-border-subtle);
184
+ --color-palette-border: var(--color-surface-border);
185
+ --color-palette-border-strong: var(--color-surface-border-strong);
186
+ --color-palette-solid: var(--color-neutral-5);
187
+ --color-palette-solid-hover: var(--color-neutral-7);
188
+ --color-palette-solid-active: var(--color-neutral-8);
189
+ --color-palette-text: var(--color-surface-fg-muted);
190
+ --color-palette-fg: var(--color-surface-fg);
191
+ }
192
+
193
+ /* ───────────────────────────────────────────────────────────────────
194
+ Category palettes — a fixed, non-rebrandable set for labelling things
195
+ that are different rather than better or worse (teams, tags, projects).
196
+
197
+ These resolve from the PRIVATE PRIMITIVES rather than the semantic
198
+ layer, because the semantic layer exposes only six steps for them
199
+ (2, 3, 4, 7, 9, 11) while the roles need ten. Exposing the missing
200
+ four semantically would add 84 declarations and generate a utility
201
+ surface (`bg-category-teal-5`, …) nobody asked for. The primitives are
202
+ already complete and already theme-aware.
203
+
204
+ On-solid text uses `--color-category-fg`, which inverts with the theme
205
+ — category step 9 lightens in dark, the opposite of the intent ramps.
206
+ That token exists because a hardcoded white failed AA in dark; see the
207
+ 0.57.0 changelog.
208
+ ─────────────────────────────────────────────────────────────────── */
209
+
210
+ [data-palette='teal'] {
211
+ --color-palette-subtle: var(--teal-2); --color-palette-soft: var(--teal-3);
212
+ --color-palette-soft-hover: var(--teal-4); --color-palette-soft-active: var(--teal-5);
213
+ --color-palette-border-subtle: var(--teal-6);--color-palette-border: var(--teal-4); --color-palette-border-strong: var(--teal-7);
214
+ --color-palette-solid: var(--teal-9); --color-palette-solid-hover: var(--teal-10);
215
+ --color-palette-solid-active: var(--teal-11);
216
+ --color-palette-text: var(--teal-11); --color-palette-fg: var(--color-category-fg);
217
+ }
218
+
219
+ [data-palette='amber'] {
220
+ --color-palette-subtle: var(--amber-2); --color-palette-soft: var(--amber-3);
221
+ --color-palette-soft-hover: var(--amber-4); --color-palette-soft-active: var(--amber-5);
222
+ --color-palette-border-subtle: var(--amber-6);--color-palette-border: var(--amber-4); --color-palette-border-strong: var(--amber-7);
223
+ --color-palette-solid: var(--amber-9); --color-palette-solid-hover: var(--amber-10);
224
+ --color-palette-solid-active: var(--amber-11);
225
+ --color-palette-text: var(--amber-11); --color-palette-fg: var(--color-category-fg);
226
+ }
227
+
228
+ [data-palette='slate'] {
229
+ --color-palette-subtle: var(--slate-2); --color-palette-soft: var(--slate-3);
230
+ --color-palette-soft-hover: var(--slate-4); --color-palette-soft-active: var(--slate-5);
231
+ --color-palette-border-subtle: var(--slate-6);--color-palette-border: var(--slate-4); --color-palette-border-strong: var(--slate-7);
232
+ --color-palette-solid: var(--slate-9); --color-palette-solid-hover: var(--slate-10);
233
+ --color-palette-solid-active: var(--slate-11);
234
+ --color-palette-text: var(--slate-11); --color-palette-fg: var(--color-category-fg);
235
+ }
236
+
237
+ [data-palette='indigo'] {
238
+ --color-palette-subtle: var(--indigo-2); --color-palette-soft: var(--indigo-3);
239
+ --color-palette-soft-hover: var(--indigo-4); --color-palette-soft-active: var(--indigo-5);
240
+ --color-palette-border-subtle: var(--indigo-6);--color-palette-border: var(--indigo-4); --color-palette-border-strong: var(--indigo-7);
241
+ --color-palette-solid: var(--indigo-9); --color-palette-solid-hover: var(--indigo-10);
242
+ --color-palette-solid-active: var(--indigo-11);
243
+ --color-palette-text: var(--indigo-11); --color-palette-fg: var(--color-category-fg);
244
+ }
245
+
246
+ [data-palette='cyan'] {
247
+ --color-palette-subtle: var(--cyan-2); --color-palette-soft: var(--cyan-3);
248
+ --color-palette-soft-hover: var(--cyan-4); --color-palette-soft-active: var(--cyan-5);
249
+ --color-palette-border-subtle: var(--cyan-6);--color-palette-border: var(--cyan-4); --color-palette-border-strong: var(--cyan-7);
250
+ --color-palette-solid: var(--cyan-9); --color-palette-solid-hover: var(--cyan-10);
251
+ --color-palette-solid-active: var(--cyan-11);
252
+ --color-palette-text: var(--cyan-11); --color-palette-fg: var(--color-category-fg);
253
+ }
254
+
255
+ [data-palette='orange'] {
256
+ --color-palette-subtle: var(--orange-2); --color-palette-soft: var(--orange-3);
257
+ --color-palette-soft-hover: var(--orange-4); --color-palette-soft-active: var(--orange-5);
258
+ --color-palette-border-subtle: var(--orange-6);--color-palette-border: var(--orange-4); --color-palette-border-strong: var(--orange-7);
259
+ --color-palette-solid: var(--orange-9); --color-palette-solid-hover: var(--orange-10);
260
+ --color-palette-solid-active: var(--orange-11);
261
+ --color-palette-text: var(--orange-11); --color-palette-fg: var(--color-category-fg);
262
+ }
263
+
264
+ [data-palette='emerald'] {
265
+ --color-palette-subtle: var(--emerald-2); --color-palette-soft: var(--emerald-3);
266
+ --color-palette-soft-hover: var(--emerald-4); --color-palette-soft-active: var(--emerald-5);
267
+ --color-palette-border-subtle: var(--emerald-6);--color-palette-border: var(--emerald-4); --color-palette-border-strong: var(--emerald-7);
268
+ --color-palette-solid: var(--emerald-9); --color-palette-solid-hover: var(--emerald-10);
269
+ --color-palette-solid-active: var(--emerald-11);
270
+ --color-palette-text: var(--emerald-11); --color-palette-fg: var(--color-category-fg);
271
+ }
272
+
273
+ /* ───────────────────────────────────────────────────────────────────
274
+ Registering your own palette
275
+
276
+ [data-palette='brand-purple'] {
277
+ --color-palette-solid: #6d28d9;
278
+ --color-palette-solid-hover: #5b21b6;
279
+ --color-palette-fg: #ffffff; ← supply this
280
+
281
+ }
282
+
283
+ Supply `--color-palette-fg` explicitly. If you omit it, the derivation
284
+ near the top of this file gives you black-or-white from the solid's
285
+ lightness — readable, but blunt on a mid-tone brand colour, and outside
286
+ the contrast guarantee we measure for the built-in palettes.
287
+
288
+ That derivation is declared once, before the built-in blocks, so every
289
+ built-in overwrites it and only an unrecognised palette keeps it. See
290
+ the note there for why source order rather than specificity does the
291
+ work.
292
+ ─────────────────────────────────────────────────────────────────── */
@@ -51,24 +51,26 @@
51
51
  --neutral-0: #ffffff;
52
52
  /* Sunken well. Chroma follows the neutral cadence (was H:360 C:0.008 — an
53
53
  outlier that read visibly pink on sunken surfaces). */
54
- --color-surface-0: oklch(0.945 0.0013 350);
55
- --neutral-1: oklch(0.99 0.0003 350);
56
- --neutral-2: oklch(0.97 0.0008 350);
57
- --neutral-3: oklch(0.93 0.0018 350);
58
- --neutral-4: oklch(0.89 0.0029 350);
59
- --neutral-5: oklch(0.84 0.0042 350);
60
- --neutral-6: oklch(0.78 0.0053 350);
61
- --neutral-7: oklch(0.7 0.0074 350);
62
- --neutral-8: oklch(0.62 0.0089 350);
54
+ /* Sunken wells. Sits below the page and clears panel-hover; see
55
+ docs/plans/2026-08-26-surface-model-rebuild.md */
56
+ --neutral-sunken: oklch(0.95 0 0);
57
+ --neutral-1: oklch(0.99 0 0);
58
+ --neutral-2: oklch(0.97 0 0);
59
+ --neutral-3: oklch(0.93 0 0);
60
+ --neutral-4: oklch(0.89 0 0);
61
+ --neutral-5: oklch(0.84 0 0);
62
+ --neutral-6: oklch(0.78 0 0);
63
+ --neutral-7: oklch(0.7 0 0);
64
+ --neutral-8: oklch(0.62 0 0);
63
65
  /* 0.55 → 0.54: at 0.55 this measured 4.472:1 on --neutral-2 (the light
64
66
  surface-base), just under WCAG AA's 4.5 for normal text. 0.54 gives
65
67
  4.664:1. The intermediate 0.545 also clears at 4.567, but with only
66
68
  0.067 of headroom — a later tweak to surface-base would silently push it
67
69
  back under, which is how the previous attempt at this fix landed short. */
68
- --neutral-9: oklch(0.54 0.01 350);
69
- --neutral-10: oklch(0.5 0.01 350);
70
- --neutral-11: oklch(0.43 0.0074 350);
71
- --neutral-12: oklch(0.32 0.0042 350);
70
+ --neutral-9: oklch(0.54 0 0);
71
+ --neutral-10: oklch(0.5 0 0);
72
+ --neutral-11: oklch(0.43 0 0);
73
+ --neutral-12: oklch(0.32 0 0);
72
74
 
73
75
  /* ── Red — H:25 ── */
74
76
  --red-1: oklch(0.99 0.0047 25);
@@ -271,19 +273,20 @@
271
273
  /* ── Neutral — Warm grays — H:350 ── */
272
274
  /* Sunken well (deep). Chroma follows the neutral cadence — was H:360 C:0.008,
273
275
  an outlier that read tinted rather than neutral. */
274
- --color-surface-0: oklch(0.07 0.0004 350);
275
- --neutral-1: oklch(0.11 0.0002 350);
276
- --neutral-2: oklch(0.17 0.0007 350);
277
- --neutral-3: oklch(0.23 0.0019 350);
278
- --neutral-4: oklch(0.29 0.0029 350);
279
- --neutral-5: oklch(0.34 0.0038 350);
280
- --neutral-6: oklch(0.38 0.0048 350);
281
- --neutral-7: oklch(0.44 0.0062 350);
282
- --neutral-8: oklch(0.53 0.0086 350);
283
- --neutral-9: oklch(0.63 0.01 350);
284
- --neutral-10: oklch(0.58 0.01 350);
285
- --neutral-11: oklch(0.76 0.0062 350);
286
- --neutral-12: oklch(0.88 0.0024 350);
276
+ /* Dark has no room below the page, so a well simply IS the page. */
277
+ --neutral-sunken: oklch(0.147 0 0);
278
+ --neutral-1: oklch(0.147 0 0);
279
+ --neutral-2: oklch(0.207 0 0);
280
+ --neutral-3: oklch(0.267 0 0);
281
+ --neutral-4: oklch(0.327 0 0);
282
+ --neutral-5: oklch(0.377 0 0);
283
+ --neutral-6: oklch(0.417 0 0);
284
+ --neutral-7: oklch(0.477 0 0);
285
+ --neutral-8: oklch(0.567 0 0);
286
+ --neutral-9: oklch(0.667 0 0);
287
+ --neutral-10: oklch(0.617 0 0);
288
+ --neutral-11: oklch(0.797 0 0);
289
+ --neutral-12: oklch(0.917 0 0);
287
290
 
288
291
  /* ── Red — H:25 ── */
289
292
  --red-1: oklch(0.11 0.0047 25);