@crisp-ui-kit/crisp 0.57.1 → 0.57.3

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 (277) hide show
  1. package/dist/authshell.css +9 -4
  2. package/dist/authshell.layered.css +9 -4
  3. package/dist/badge.css +3 -3
  4. package/dist/badge.layered.css +3 -3
  5. package/dist/board.css +28 -8
  6. package/dist/board.layered.css +28 -8
  7. package/dist/bottomsheet.css +26 -0
  8. package/dist/bottomsheet.d.ts +7 -0
  9. package/dist/bottomsheet.layered.css +28 -0
  10. package/dist/button.css +10 -6
  11. package/dist/button.d.ts +2 -2
  12. package/dist/button.layered.css +10 -6
  13. package/dist/checkbox.css +7 -3
  14. package/dist/checkbox.layered.css +7 -3
  15. package/dist/chip.css +16 -1
  16. package/dist/chip.d.ts +3 -1
  17. package/dist/chip.layered.css +16 -1
  18. package/dist/chipgroup.css +5 -0
  19. package/dist/chipgroup.d.ts +7 -0
  20. package/dist/chipgroup.layered.css +7 -0
  21. package/dist/cjs/components/badge/badge.recipe.js +22 -8
  22. package/dist/cjs/components/bottomsheet/bottomsheet.js +90 -0
  23. package/dist/cjs/components/bottomsheet/bottomsheet.recipe.js +77 -0
  24. package/dist/cjs/components/bottomsheet/index.js +9 -0
  25. package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
  26. package/dist/cjs/components/button/button.recipe.js +67 -15
  27. package/dist/cjs/components/checkbox/checkbox.recipe.js +61 -9
  28. package/dist/cjs/components/chip/chip.js +14 -2
  29. package/dist/cjs/components/chip/chip.recipe.js +72 -2
  30. package/dist/cjs/components/chipgroup/chipgroup.js +51 -0
  31. package/dist/cjs/components/chipgroup/chipgroup.recipe.js +36 -0
  32. package/dist/cjs/components/chipgroup/index.js +7 -0
  33. package/dist/cjs/components/datatable/datatable.js +5 -1
  34. package/dist/cjs/components/datatable/datatable.recipe.js +21 -6
  35. package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
  36. package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
  37. package/dist/cjs/components/dialog/dialog.recipe.js +21 -10
  38. package/dist/cjs/components/emptystate/emptystate.recipe.js +7 -2
  39. package/dist/cjs/components/fileupload/fileupload.js +21 -4
  40. package/dist/cjs/components/input/index.js +2 -1
  41. package/dist/cjs/components/input/input.js +31 -1
  42. package/dist/cjs/components/input/input.recipe.js +16 -9
  43. package/dist/cjs/components/menu/menu.js +18 -2
  44. package/dist/cjs/components/menu/menu.recipe.js +21 -7
  45. package/dist/cjs/components/menusheet/index.js +9 -0
  46. package/dist/cjs/components/menusheet/menusheet.js +133 -0
  47. package/dist/cjs/components/menusheet/menusheet.recipe.js +103 -0
  48. package/dist/cjs/components/multiselect/multiselect.js +1 -1
  49. package/dist/cjs/components/multiselect/multiselect.recipe.js +33 -9
  50. package/dist/cjs/components/select/select.js +1 -1
  51. package/dist/cjs/components/select/select.recipe.js +38 -12
  52. package/dist/cjs/components/snackbar/index.js +8 -0
  53. package/dist/cjs/components/snackbar/snackbar.js +121 -0
  54. package/dist/cjs/components/snackbar/snackbar.recipe.js +71 -0
  55. package/dist/cjs/components/table/table.recipe.js +7 -1
  56. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  57. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +37 -12
  58. package/dist/cjs/components/tabs/tabs.js +10 -4
  59. package/dist/cjs/components/tabs/tabs.recipe.js +23 -6
  60. package/dist/cjs/components/textarea/textarea.recipe.js +11 -8
  61. package/dist/cjs/core/floating-portal.js +7 -4
  62. package/dist/cjs/index.js +7 -0
  63. package/dist/cjs/product/authshell/authshell.recipe.js +5 -1
  64. package/dist/cjs/product/command/command.recipe.js +4 -1
  65. package/dist/cjs/product/comments/comments.js +7 -2
  66. package/dist/cjs/product/comments/comments.recipe.js +25 -7
  67. package/dist/cjs/product/inbox/inbox.js +11 -3
  68. package/dist/cjs/product/memberssettings/index.js +6 -0
  69. package/dist/cjs/product/memberssettings/memberssettings.js +99 -0
  70. package/dist/cjs/product/memberssettings/memberssettings.recipe.js +83 -0
  71. package/dist/cjs/product/notificationssettings/index.js +5 -0
  72. package/dist/cjs/product/notificationssettings/notificationssettings.js +19 -0
  73. package/dist/cjs/product/notificationssettings/notificationssettings.recipe.js +44 -0
  74. package/dist/cjs/product/recordpage/index.js +2 -1
  75. package/dist/cjs/product/recordpage/recordpage.js +106 -9
  76. package/dist/cjs/product/recordpage/recordpage.recipe.js +68 -6
  77. package/dist/cjs/product/workspacegeneralsettings/index.js +5 -0
  78. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.js +21 -0
  79. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +51 -0
  80. package/dist/cjs/tokens/contract.js +1 -0
  81. package/dist/cjs/tokens/elevation.js +8 -5
  82. package/dist/cjs/tokens/palette.js +28 -8
  83. package/dist/cjs/tokens/scale.js +44 -2
  84. package/dist/cjs/tokens/semantic.js +2 -0
  85. package/dist/columncalc.css +15 -7
  86. package/dist/columncalc.layered.css +15 -7
  87. package/dist/command.css +23 -19
  88. package/dist/command.layered.css +23 -19
  89. package/dist/comments.css +28 -19
  90. package/dist/comments.d.ts +2 -2
  91. package/dist/comments.layered.css +28 -19
  92. package/dist/datatable.css +171 -71
  93. package/dist/datatable.layered.css +171 -71
  94. package/dist/datepicker.css +13 -41
  95. package/dist/datepicker.layered.css +13 -41
  96. package/dist/datepickerfield.css +12 -3
  97. package/dist/datepickerfield.d.ts +2 -2
  98. package/dist/datepickerfield.layered.css +12 -3
  99. package/dist/dialog.css +12 -7
  100. package/dist/dialog.layered.css +12 -7
  101. package/dist/emptystate.css +5 -3
  102. package/dist/emptystate.layered.css +5 -3
  103. package/dist/esm/components/badge/badge.recipe.js +22 -8
  104. package/dist/esm/components/bottomsheet/bottomsheet.js +52 -0
  105. package/dist/esm/components/bottomsheet/bottomsheet.recipe.js +74 -0
  106. package/dist/esm/components/bottomsheet/index.js +2 -0
  107. package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
  108. package/dist/esm/components/button/button.recipe.js +68 -16
  109. package/dist/esm/components/checkbox/checkbox.recipe.js +61 -9
  110. package/dist/esm/components/chip/chip.js +14 -2
  111. package/dist/esm/components/chip/chip.recipe.js +72 -2
  112. package/dist/esm/components/chipgroup/chipgroup.js +15 -0
  113. package/dist/esm/components/chipgroup/chipgroup.recipe.js +33 -0
  114. package/dist/esm/components/chipgroup/index.js +2 -0
  115. package/dist/esm/components/datatable/datatable.js +5 -1
  116. package/dist/esm/components/datatable/datatable.recipe.js +21 -6
  117. package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
  118. package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
  119. package/dist/esm/components/dialog/dialog.recipe.js +22 -11
  120. package/dist/esm/components/emptystate/emptystate.recipe.js +7 -2
  121. package/dist/esm/components/fileupload/fileupload.js +20 -5
  122. package/dist/esm/components/input/index.js +1 -1
  123. package/dist/esm/components/input/input.js +30 -0
  124. package/dist/esm/components/input/input.recipe.js +17 -10
  125. package/dist/esm/components/menu/menu.js +18 -2
  126. package/dist/esm/components/menu/menu.recipe.js +21 -7
  127. package/dist/esm/components/menusheet/index.js +2 -0
  128. package/dist/esm/components/menusheet/menusheet.js +95 -0
  129. package/dist/esm/components/menusheet/menusheet.recipe.js +100 -0
  130. package/dist/esm/components/multiselect/multiselect.js +1 -1
  131. package/dist/esm/components/multiselect/multiselect.recipe.js +33 -9
  132. package/dist/esm/components/select/select.js +1 -1
  133. package/dist/esm/components/select/select.recipe.js +38 -12
  134. package/dist/esm/components/snackbar/index.js +2 -0
  135. package/dist/esm/components/snackbar/snackbar.js +84 -0
  136. package/dist/esm/components/snackbar/snackbar.recipe.js +68 -0
  137. package/dist/esm/components/table/table.recipe.js +7 -1
  138. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  139. package/dist/esm/components/tabletoolbar/tabletoolbar.js +37 -12
  140. package/dist/esm/components/tabs/tabs.js +10 -4
  141. package/dist/esm/components/tabs/tabs.recipe.js +23 -6
  142. package/dist/esm/components/textarea/textarea.recipe.js +12 -9
  143. package/dist/esm/core/floating-portal.js +7 -4
  144. package/dist/esm/index.js +7 -0
  145. package/dist/esm/product/authshell/authshell.recipe.js +5 -1
  146. package/dist/esm/product/command/command.recipe.js +4 -1
  147. package/dist/esm/product/comments/comments.js +7 -2
  148. package/dist/esm/product/comments/comments.recipe.js +25 -7
  149. package/dist/esm/product/inbox/inbox.js +11 -3
  150. package/dist/esm/product/memberssettings/index.js +1 -0
  151. package/dist/esm/product/memberssettings/memberssettings.js +62 -0
  152. package/dist/esm/product/memberssettings/memberssettings.recipe.js +80 -0
  153. package/dist/esm/product/notificationssettings/index.js +1 -0
  154. package/dist/esm/product/notificationssettings/notificationssettings.js +16 -0
  155. package/dist/esm/product/notificationssettings/notificationssettings.recipe.js +41 -0
  156. package/dist/esm/product/recordpage/index.js +1 -1
  157. package/dist/esm/product/recordpage/recordpage.js +106 -10
  158. package/dist/esm/product/recordpage/recordpage.recipe.js +68 -6
  159. package/dist/esm/product/workspacegeneralsettings/index.js +1 -0
  160. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.js +18 -0
  161. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +48 -0
  162. package/dist/esm/tokens/contract.js +2 -1
  163. package/dist/esm/tokens/elevation.js +8 -5
  164. package/dist/esm/tokens/palette.js +28 -8
  165. package/dist/esm/tokens/scale.js +43 -1
  166. package/dist/esm/tokens/semantic.js +2 -0
  167. package/dist/fileupload.css +3 -1
  168. package/dist/fileupload.layered.css +3 -1
  169. package/dist/input.css +6 -4
  170. package/dist/input.layered.css +6 -4
  171. package/dist/listpage.css +3 -1
  172. package/dist/listpage.layered.css +3 -1
  173. package/dist/memberssettings.css +67 -0
  174. package/dist/memberssettings.d.ts +7 -0
  175. package/dist/memberssettings.layered.css +69 -0
  176. package/dist/menu.css +2 -2
  177. package/dist/menu.layered.css +2 -2
  178. package/dist/menusheet.css +36 -0
  179. package/dist/menusheet.d.ts +7 -0
  180. package/dist/menusheet.layered.css +38 -0
  181. package/dist/multiselect.css +13 -6
  182. package/dist/multiselect.layered.css +13 -6
  183. package/dist/native/tokens.d.ts +2 -1
  184. package/dist/native/tokens.js +20 -3
  185. package/dist/notificationssettings.css +22 -0
  186. package/dist/notificationssettings.d.ts +7 -0
  187. package/dist/notificationssettings.layered.css +24 -0
  188. package/dist/objectsettings.css +4 -4
  189. package/dist/objectsettings.layered.css +4 -4
  190. package/dist/recordpage.css +90 -23
  191. package/dist/recordpage.layered.css +90 -23
  192. package/dist/recordpanel.css +35 -16
  193. package/dist/recordpanel.layered.css +35 -16
  194. package/dist/resizablepanel.css +8 -5
  195. package/dist/resizablepanel.layered.css +8 -5
  196. package/dist/richtext.css +24 -8
  197. package/dist/richtext.layered.css +24 -8
  198. package/dist/savedviews.css +9 -2
  199. package/dist/savedviews.layered.css +9 -2
  200. package/dist/select.css +25 -5
  201. package/dist/select.layered.css +25 -5
  202. package/dist/settingsshell.css +2 -3
  203. package/dist/settingsshell.layered.css +2 -3
  204. package/dist/slider.css +6 -27
  205. package/dist/slider.layered.css +6 -27
  206. package/dist/snackbar.css +24 -0
  207. package/dist/snackbar.d.ts +7 -0
  208. package/dist/snackbar.layered.css +26 -0
  209. package/dist/statcard.css +3 -1
  210. package/dist/statcard.layered.css +3 -1
  211. package/dist/styles.css +911 -354
  212. package/dist/styles.layered.css +911 -354
  213. package/dist/table.css +35 -12
  214. package/dist/table.layered.css +35 -12
  215. package/dist/tabletoolbar.css +35 -24
  216. package/dist/tabletoolbar.layered.css +35 -24
  217. package/dist/tabs.css +18 -4
  218. package/dist/tabs.layered.css +18 -4
  219. package/dist/textarea.css +2 -6
  220. package/dist/textarea.layered.css +2 -6
  221. package/dist/themepicker.css +2 -1
  222. package/dist/themepicker.layered.css +2 -1
  223. package/dist/tokens.css +13 -2
  224. package/dist/tokens.json +20 -3
  225. package/dist/types/components/bottomsheet/bottomsheet.d.ts +35 -0
  226. package/dist/types/components/bottomsheet/bottomsheet.recipe.d.ts +3 -0
  227. package/dist/types/components/bottomsheet/index.d.ts +2 -0
  228. package/dist/types/components/breadcrumb/breadcrumb.d.ts +9 -1
  229. package/dist/types/components/button/button.d.ts +2 -0
  230. package/dist/types/components/button/button.recipe.d.ts +24 -6
  231. package/dist/types/components/checkbox/checkbox.recipe.d.ts +28 -5
  232. package/dist/types/components/chip/chip.d.ts +22 -0
  233. package/dist/types/components/chip/chip.recipe.d.ts +49 -1
  234. package/dist/types/components/chipgroup/chipgroup.d.ts +14 -0
  235. package/dist/types/components/chipgroup/chipgroup.recipe.d.ts +5 -0
  236. package/dist/types/components/chipgroup/index.d.ts +2 -0
  237. package/dist/types/components/datatable/datatable.d.ts +19 -0
  238. package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
  239. package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
  240. package/dist/types/components/fileupload/fileupload.d.ts +26 -0
  241. package/dist/types/components/input/index.d.ts +1 -1
  242. package/dist/types/components/input/input.d.ts +72 -0
  243. package/dist/types/components/menusheet/index.d.ts +2 -0
  244. package/dist/types/components/menusheet/menusheet.d.ts +42 -0
  245. package/dist/types/components/menusheet/menusheet.recipe.d.ts +3 -0
  246. package/dist/types/components/snackbar/index.d.ts +2 -0
  247. package/dist/types/components/snackbar/snackbar.d.ts +36 -0
  248. package/dist/types/components/snackbar/snackbar.recipe.d.ts +5 -0
  249. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +28 -1
  250. package/dist/types/components/tabs/tabs.d.ts +11 -1
  251. package/dist/types/core/floating-portal.d.ts +6 -5
  252. package/dist/types/index.d.ts +7 -0
  253. package/dist/types/product/comments/comments.d.ts +9 -3
  254. package/dist/types/product/comments/comments.recipe.d.ts +12 -2
  255. package/dist/types/product/inbox/inbox.d.ts +13 -1
  256. package/dist/types/product/memberssettings/index.d.ts +1 -0
  257. package/dist/types/product/memberssettings/memberssettings.d.ts +85 -0
  258. package/dist/types/product/memberssettings/memberssettings.recipe.d.ts +3 -0
  259. package/dist/types/product/notificationssettings/index.d.ts +1 -0
  260. package/dist/types/product/notificationssettings/notificationssettings.d.ts +37 -0
  261. package/dist/types/product/notificationssettings/notificationssettings.recipe.d.ts +3 -0
  262. package/dist/types/product/recordpage/index.d.ts +1 -1
  263. package/dist/types/product/recordpage/recordpage.d.ts +99 -2
  264. package/dist/types/product/workspacegeneralsettings/index.d.ts +1 -0
  265. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.d.ts +48 -0
  266. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.recipe.d.ts +3 -0
  267. package/dist/types/tokens/contract.d.ts +4 -1
  268. package/dist/types/tokens/elevation.d.ts +8 -5
  269. package/dist/types/tokens/palette.d.ts +9 -1
  270. package/dist/types/tokens/scale.d.ts +11 -1
  271. package/dist/types/tokens/semantic.d.ts +2 -0
  272. package/dist/wheelpicker.css +4 -2
  273. package/dist/wheelpicker.layered.css +4 -2
  274. package/dist/workspacegeneralsettings.css +30 -0
  275. package/dist/workspacegeneralsettings.d.ts +7 -0
  276. package/dist/workspacegeneralsettings.layered.css +32 -0
  277. package/package.json +36 -1
@@ -26,6 +26,21 @@ const config = (0, core_1.defineRecipe)({
26
26
  & * { box-sizing: border-box; }
27
27
 
28
28
  & .crisp-recordpage-topbar { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; height: 44px; flex-shrink: 0; padding: 0 ${tokens_1.contract.space["3"]}; border-bottom: 1px solid ${tokens_1.contract.borderSubtle}; }
29
+ /* #624: expanding a peek to its full record keeps a hybrid header
30
+ (Close/Previous/Next/counter) instead of reverting to the plain
31
+ breadcrumb above -- measured live on a real expanded record: 49px
32
+ tall (not 44px), 8px/10px padding, same borderSubtle hairline. Same
33
+ tokens as product/recordpanel's own already-shipped toolbar, not
34
+ new values -- this is the same row, reused in a second component. */
35
+ & .crisp-recordpage-topbar[data-peek] { height: 49px; padding: ${tokens_1.contract.space["2"]} ${tokens_1.contract.space["2.5"]}; }
36
+ & .crisp-recordpage-peekbar { display: flex; align-items: center; }
37
+ & .crisp-recordpage-peek-iconbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: transparent; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 55%, transparent); font-family: inherit; cursor: pointer; transition: background-color .12s; }
38
+ & .crisp-recordpage-peek-iconbtn:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
39
+ & .crisp-recordpage-peek-pager { display: flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; margin-inline-start: ${tokens_1.contract.space["3"]}; }
40
+ & .crisp-recordpage-peek-navbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: ${tokens_1.contract.bgSurface}; box-shadow: ${tokens_1.elevation.field}; color: ${tokens_1.contract.fgPrimary}; font-family: inherit; cursor: pointer; }
41
+ & .crisp-recordpage-peek-navbtn:hover:not(:disabled) { background: ${tokens_1.contract.bgRaised}; }
42
+ & .crisp-recordpage-peek-navbtn:disabled { opacity: 0.4; cursor: not-allowed; }
43
+ & .crisp-recordpage-peek-counter { margin-inline-start: ${tokens_1.contract.space["3"]}; font-size: 12px; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
29
44
  & .crisp-recordpage-crumbs { display: inline-flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; min-width: 0; }
30
45
  & .crisp-recordpage-crumb { display: inline-flex; align-items: center; height: 26px; padding: 0 ${tokens_1.contract.space["1.5"]}; margin: 0 calc(-1 * ${tokens_1.contract.space["1.5"]}) 0 0; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; font-family: inherit; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgMuted}; cursor: pointer; }
31
46
  & .crisp-recordpage-crumb:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
@@ -45,6 +60,17 @@ const config = (0, core_1.defineRecipe)({
45
60
  & .crisp-recordpage-resizer::before { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: -4px; width: 9px; }
46
61
  & .crisp-recordpage-resizer::after { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: -1px; width: 2px; background: transparent; transition: background-color .12s ease; }
47
62
  & .crisp-recordpage-resizer:hover::after, & .crisp-recordpage-resizer[data-active]::after { background: color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 55%, transparent); }
63
+ /* #930: RecordDetails' own standalone resize handle -- same visible
64
+ hit-slop/line-highlight shape as .crisp-recordpage-resizer just above,
65
+ just absolutely positioned at the trailing edge instead of a 0-width
66
+ flex sibling, since RecordDetails always returns a single root (the
67
+ same internal-strip placement RecordPanel's own resize handle uses,
68
+ mirrored to the opposite edge -- this column is leading, RecordPanel
69
+ is trailing). */
70
+ & .crisp-recordpage-section[data-resizable] { position: relative; }
71
+ & .crisp-recordpage-detailresize { position: absolute; top: 0; bottom: 0; inset-inline-end: -4px; width: 9px; cursor: col-resize; z-index: 5; touch-action: none; }
72
+ & .crisp-recordpage-detailresize::after { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-end: 3px; width: 2px; background: transparent; transition: background-color .12s ease; }
73
+ & .crisp-recordpage-detailresize:hover::after, & .crisp-recordpage-detailresize[data-active]::after { background: color-mix(in srgb, ${tokens_1.contract.bgBrandSolid} 55%, transparent); }
48
74
  & .crisp-recordpage-entity { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; padding: ${tokens_1.contract.space["1"]} ${tokens_1.contract.space["1"]} ${tokens_1.contract.space["2"]}; }
49
75
  & .crisp-recordpage-entity-logo { width: 32px; height: 32px; border-radius: 30%; flex-shrink: 0; object-fit: cover; background: ${tokens_1.contract.bgRaised}; }
50
76
  & .crisp-recordpage-entity-name { flex: 0 1 auto; min-width: 0; font-size: ${tokens_1.contract.text.xl}; font-weight: ${tokens_1.contract.weight.semibold}; letter-spacing: -0.3px; color: ${tokens_1.contract.fgPrimary}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -178,12 +204,23 @@ const config = (0, core_1.defineRecipe)({
178
204
  & .crisp-recordpage-btn--primary { box-shadow: none; background: ${tokens_1.contract.bgBrandSolid}; color: ${tokens_1.contract.fgOnBrand}; }
179
205
  & .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
180
206
 
181
- & .crisp-recordpage-note { display: flex; gap: ${tokens_1.contract.space["2.5"]}; padding: ${tokens_1.contract.space["2.5"]} 0; border-top: 1px solid ${tokens_1.contract.borderSubtle}; }
182
- & .crisp-recordpage-note-body { flex: 1; min-width: 0; }
183
- & .crisp-recordpage-note-head { display: flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; margin-bottom: ${tokens_1.contract.space["0.5"]}; }
184
- & .crisp-recordpage-note-author { font-size: ${tokens_1.contract.text.md}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; }
185
- & .crisp-recordpage-note-time { font-size: ${tokens_1.contract.text.sm}; color: ${tokens_1.contract.fgMuted}; }
186
- & .crisp-recordpage-note-text { font-size: ${tokens_1.contract.text.lg}; color: ${tokens_1.contract.fgPrimary}; white-space: pre-wrap; word-break: break-word; }
207
+ /* #871: one bordered card per note (border-radius.xl, borderSubtle),
208
+ not a flush divider-list row -- measured live on a real populated
209
+ note: the whole row is flex space-between, avatar+title+body on the
210
+ left (its own flex, gap.2), the relative time alone on the right.
211
+ The real DOM nests an inner clickable button (padding 6/8, radius.md)
212
+ inside an outer card (padding 4px, radius.xl) -- collapsed into this
213
+ one non-interactive div's own combined padding (2.5/3) since crisp's
214
+ NotesSection has no click-to-open behaviour to justify the extra
215
+ layer. The 6px gap between stacked cards is NOT independently
216
+ measured (this workspace only ever had one real note to check) --
217
+ a judgement call off the existing space scale, not a live value. */
218
+ & .crisp-recordpage-note { display: flex; align-items: center; justify-content: space-between; gap: ${tokens_1.contract.space["3"]}; padding: ${tokens_1.contract.space["2.5"]} ${tokens_1.contract.space["3"]}; border: 1px solid ${tokens_1.contract.borderSubtle}; border-radius: ${tokens_1.contract.radius.xl}; }
219
+ & .crisp-recordpage-note + .crisp-recordpage-note { margin-top: ${tokens_1.contract.space["1.5"]}; }
220
+ & .crisp-recordpage-note-left { display: flex; align-items: center; gap: ${tokens_1.contract.space["2"]}; min-width: 0; overflow: hidden; }
221
+ & .crisp-recordpage-note-title { flex-shrink: 0; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; }
222
+ & .crisp-recordpage-note-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); }
223
+ & .crisp-recordpage-note-time { flex-shrink: 0; font-size: ${tokens_1.contract.text.sm}; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 50%, transparent); }
187
224
 
188
225
  & .crisp-recordpage-task { display: flex; align-items: flex-start; gap: ${tokens_1.contract.space["2"]}; padding: ${tokens_1.contract.space["1.5"]} 0; border-top: 1px solid ${tokens_1.contract.borderSubtle}; }
189
226
  & .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: ${tokens_1.contract.text.lg}; color: ${tokens_1.contract.fgPrimary}; padding-top: 1px; }
@@ -192,6 +229,31 @@ const config = (0, core_1.defineRecipe)({
192
229
  & .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; padding: ${tokens_1.contract.space["6"]} ${tokens_1.contract.space["3"]}; border: 1px dashed ${tokens_1.contract.borderDefault}; border-radius: ${tokens_1.contract.radius.xl}; color: ${tokens_1.contract.fgMuted}; font-size: ${tokens_1.contract.text.md}; text-align: center; }
193
230
  & .crisp-recordpage-emptycard svg { color: ${tokens_1.contract.fgMuted}; opacity: 0.7; }
194
231
 
232
+ /* #622: the Activity tab's own toolbar -- "Filters" + "+ Add meeting",
233
+ both the same measured button chrome as the topbar's own action
234
+ buttons (28px, e.field shadow, 14/500 label). */
235
+ & .crisp-recordpage-tabtoolbar { display: inline-flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; }
236
+
237
+ /* #622: Files tab's empty state -- measured live on Attio's own record
238
+ page (a company with no files uploaded). The 138x138 dotted-grid
239
+ backdrop is the same measured tile EmptyState's records variant uses
240
+ (crisp/#603), duplicated here rather than composed through that
241
+ component because this surface's title (16/600) and body (14/500,
242
+ 63%-mixed fgPrimary, not the flat fgMuted EmptyState uses) measure to
243
+ their own values, matching neither of that component's existing
244
+ variants. */
245
+ & .crisp-recordpage-panel--center { flex: 1; align-items: center; justify-content: center; }
246
+ & .crisp-recordpage-illustrated { display: flex; flex-direction: column; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; text-align: center; }
247
+ & .crisp-recordpage-illustrated-icon { display: flex; align-items: center; justify-content: center; width: 138px; height: 138px; margin-bottom: ${tokens_1.contract.space["2"]}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 22%, transparent); background: radial-gradient(circle, color-mix(in srgb, ${tokens_1.contract.fgPrimary} 12%, transparent) 1.2px, transparent 1.2px) 0 0 / 16px 16px; }
248
+ & .crisp-recordpage-illustrated-title { font-size: ${tokens_1.contract.text.xl}; font-weight: ${tokens_1.contract.weight.semibold}; color: ${tokens_1.contract.fgPrimary}; }
249
+ /* #988: the Calls tab's own gated state measures a larger 20/24 title
250
+ than Files/Deals' 16/600 -- Attio's own "empty view" pattern (the
251
+ same 20/600 EmptyState's page/records variants already carry, not a
252
+ one-off). */
253
+ & .crisp-recordpage-illustrated-title--lg { font-size: 20px; line-height: 24px; }
254
+ & .crisp-recordpage-illustrated-desc { max-width: 320px; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); }
255
+ & .crisp-recordpage-illustrated-actions { display: inline-flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: ${tokens_1.contract.space["1.5"]}; margin-top: ${tokens_1.contract.space["2"]}; }
256
+
195
257
  & .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
196
258
 
197
259
  & .crisp-recordstable-tag { display: inline-flex; align-items: center; height: ${tokens_1.contract.size.chip}; padding: 0 ${tokens_1.contract.space["1"]}; border-radius: ${tokens_1.contract.radius.chip}; font-size: ${tokens_1.contract.text.lg}; line-height: 20px; font-weight: ${tokens_1.contract.weight.medium}; white-space: nowrap; background: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 6%, transparent); color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 82%, transparent); }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkspaceGeneralSettings = void 0;
4
+ var workspacegeneralsettings_1 = require("./workspacegeneralsettings");
5
+ Object.defineProperty(exports, "WorkspaceGeneralSettings", { enumerable: true, get: function () { return workspacegeneralsettings_1.WorkspaceGeneralSettings; } });
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkspaceGeneralSettings = WorkspaceGeneralSettings;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const lucide_react_1 = require("lucide-react");
6
+ const avatar_1 = require("../../components/avatar");
7
+ const button_1 = require("../../components/button");
8
+ const formfield_1 = require("../../components/formfield");
9
+ const input_1 = require("../../components/input");
10
+ const table_1 = require("../../components/table");
11
+ const textlink_1 = require("../../components/textlink");
12
+ const workspacegeneralsettings_recipe_1 = require("./workspacegeneralsettings.recipe");
13
+ /**
14
+ * Attio's Settings → Workspace → General page (crisp#638, P-128), measured
15
+ * live: a logo + Name/Slug section, an "Export workspace data" table, and a
16
+ * "Danger zone" delete-workspace row.
17
+ */
18
+ function WorkspaceGeneralSettings({ logoSrc, workspaceInitial, onUploadLogo, name, onNameChange, slug, onCopySlug, exports: exportRows, onStartExport, onDeleteWorkspace, className, title = "General", description = "Change the settings for your current workspace.", learnMoreLabel = "Learn more", learnMoreHref = "#", logoHelpText = "We only support PNGs, JPEGs and GIFs under 10MB", uploadLogoLabel = "Upload logo", nameFieldLabel = "Name", slugFieldLabel = "Slug", copySlugLabel = "Copy slug", exportSectionTitle = "Export workspace data", exportSectionDescription = "Exports are in CSV format and can be downloaded within 7 days", startExportLabel = "Start new export", typeColumnLabel = "Type", dateColumnLabel = "Date", noExportsLabel = "No exports yet", dangerSectionTitle = "Danger zone", deleteWorkspaceTitle = "Delete workspace", deleteWorkspaceWarning = "Once deleted, your workspace cannot be recovered", deleteWorkspaceLabel = "Delete workspace", ...rest }) {
19
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, workspacegeneralsettings_recipe_1.workspacegeneralsettingsRecipe)({ className }), ...rest, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-page", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-heading", children: [(0, jsx_runtime_1.jsx)("h1", { className: "crisp-workspacegeneralsettings-title", children: title }), (0, jsx_runtime_1.jsxs)("p", { className: "crisp-workspacegeneralsettings-desc", children: [description, " ", (0, jsx_runtime_1.jsx)(textlink_1.TextLink, { href: learnMoreHref, children: learnMoreLabel })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-section", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-logorow", children: [logoSrc ? ((0, jsx_runtime_1.jsx)("img", { src: logoSrc, alt: "", width: 48, height: 48, style: { borderRadius: "30%", objectFit: "cover" } })) : ((0, jsx_runtime_1.jsx)(avatar_1.Avatar, { size: "xl", shape: "rounded", tone: "brand", children: workspaceInitial })), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-logotext", children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-workspacegeneralsettings-logohelp", children: logoHelpText }), (0, jsx_runtime_1.jsx)(button_1.Button, { intent: "neutral", size: "sm", onClick: onUploadLogo, children: uploadLogoLabel })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-fieldrow", children: [(0, jsx_runtime_1.jsx)(formfield_1.FormField, { label: nameFieldLabel, children: (0, jsx_runtime_1.jsx)(input_1.Input, { value: name, onChange: (e) => onNameChange(e.target.value) }) }), (0, jsx_runtime_1.jsx)(formfield_1.FormField, { label: slugFieldLabel, children: (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-slugfield", children: [(0, jsx_runtime_1.jsx)(input_1.Input, { value: slug, readOnly: true }), (0, jsx_runtime_1.jsx)("button", { type: "button", className: "crisp-workspacegeneralsettings-copybtn", "aria-label": copySlugLabel, onClick: onCopySlug, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Copy, { size: 16 }) })] }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-section", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-sectionhead", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-sectionhead-text", children: [(0, jsx_runtime_1.jsx)("h2", { className: "crisp-workspacegeneralsettings-sectiontitle", children: exportSectionTitle }), (0, jsx_runtime_1.jsx)("p", { className: "crisp-workspacegeneralsettings-desc", children: exportSectionDescription })] }), (0, jsx_runtime_1.jsx)(button_1.Button, { intent: "neutral", size: "sm", onClick: onStartExport, children: startExportLabel })] }), (0, jsx_runtime_1.jsxs)(table_1.Table, { children: [(0, jsx_runtime_1.jsx)(table_1.TableHeader, { children: (0, jsx_runtime_1.jsxs)(table_1.TableRow, { children: [(0, jsx_runtime_1.jsx)(table_1.TableHead, { children: typeColumnLabel }), (0, jsx_runtime_1.jsx)(table_1.TableHead, { children: dateColumnLabel })] }) }), (0, jsx_runtime_1.jsx)(table_1.TableBody, { children: exportRows.length === 0 ? ((0, jsx_runtime_1.jsx)(table_1.TableRow, { children: (0, jsx_runtime_1.jsx)(table_1.TableCell, { colSpan: 2, children: (0, jsx_runtime_1.jsx)("div", { className: "crisp-workspacegeneralsettings-emptyrow", children: noExportsLabel }) }) })) : (exportRows.map((row) => ((0, jsx_runtime_1.jsxs)(table_1.TableRow, { children: [(0, jsx_runtime_1.jsx)(table_1.TableCell, { children: row.type }), (0, jsx_runtime_1.jsx)(table_1.TableCell, { children: row.date })] }, row.id)))) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-section", children: [(0, jsx_runtime_1.jsx)("h2", { className: "crisp-workspacegeneralsettings-sectiontitle", children: dangerSectionTitle }), (0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-dangerrow", children: [(0, jsx_runtime_1.jsxs)("div", { className: "crisp-workspacegeneralsettings-dangertext", children: [(0, jsx_runtime_1.jsx)("span", { className: "crisp-workspacegeneralsettings-rowtitle", children: deleteWorkspaceTitle }), (0, jsx_runtime_1.jsx)("span", { className: "crisp-workspacegeneralsettings-dangerwarning", children: deleteWorkspaceWarning })] }), (0, jsx_runtime_1.jsx)(button_1.Button, { intent: "danger", size: "sm", onClick: onDeleteWorkspace, children: deleteWorkspaceLabel })] })] })] }) }));
20
+ }
21
+ WorkspaceGeneralSettings.displayName = "WorkspaceGeneralSettings";
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.workspacegeneralsettingsRecipe = void 0;
4
+ const core_1 = require("../../core");
5
+ const tokens_1 = require("../../tokens");
6
+ // Measured live against app.attio.com/<workspace>/settings/workspace
7
+ // (crisp#638, P-128). Logo tile + Name/Slug fields side by side, an
8
+ // "Export workspace data" section (header row + Type/Date table + empty
9
+ // state), and a "Danger zone" section (a red-tinted bordered row).
10
+ const config = (0, core_1.defineRecipe)({
11
+ name: "workspacegeneralsettings",
12
+ base: `& .crisp-workspacegeneralsettings-page { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["6"]}; font-family: ${tokens_1.contract.font.sans}; }
13
+ & .crisp-workspacegeneralsettings-heading { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["0.5"]}; }
14
+ & .crisp-workspacegeneralsettings-title { font-size: 24px; line-height: 28px; font-weight: ${tokens_1.contract.weight.semibold}; letter-spacing: -0.48px; color: ${tokens_1.contract.fgPrimary}; margin: 0; }
15
+ & .crisp-workspacegeneralsettings-desc { font-size: ${tokens_1.contract.text.lg}; line-height: 20px; color: ${tokens_1.contract.fgMuted}; margin: 0; }
16
+
17
+ & .crisp-workspacegeneralsettings-section { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["4"]}; }
18
+ & .crisp-workspacegeneralsettings-sectiontitle { font-size: 16px; line-height: 20px; font-weight: ${tokens_1.contract.weight.semibold}; color: ${tokens_1.contract.fgPrimary}; margin: 0; }
19
+ & .crisp-workspacegeneralsettings-sectionhead { display: flex; align-items: flex-start; justify-content: space-between; gap: ${tokens_1.contract.space["4"]}; }
20
+ & .crisp-workspacegeneralsettings-sectionhead-text { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["1"]}; }
21
+
22
+ /* Logo row: a tile + helper text + "Upload logo" button. */
23
+ & .crisp-workspacegeneralsettings-logorow { display: flex; align-items: center; gap: ${tokens_1.contract.space["4"]}; }
24
+ & .crisp-workspacegeneralsettings-logohelp { font-size: ${tokens_1.contract.text.sm}; color: ${tokens_1.contract.fgMuted}; }
25
+ & .crisp-workspacegeneralsettings-logotext { display: flex; flex-direction: column; align-items: flex-start; gap: ${tokens_1.contract.space["1"]}; }
26
+
27
+ /* Name + Slug sit side by side, each ~half the content width. */
28
+ & .crisp-workspacegeneralsettings-fieldrow { display: flex; gap: ${tokens_1.contract.space["4"]}; }
29
+ & .crisp-workspacegeneralsettings-fieldrow > * { flex: 1; min-width: 0; }
30
+ & .crisp-workspacegeneralsettings-slugfield { display: flex; align-items: center; gap: ${tokens_1.contract.space["1.5"]}; }
31
+ & .crisp-workspacegeneralsettings-slugfield > :first-child { flex: 1; min-width: 0; }
32
+ & .crisp-workspacegeneralsettings-copybtn { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 32px; height: 32px; border: none; border-radius: ${tokens_1.contract.radius.md}; background: none; font-family: inherit; color: ${tokens_1.contract.fgMuted}; cursor: pointer; }
33
+ & .crisp-workspacegeneralsettings-copybtn:hover { background: ${tokens_1.contract.bgRaised}; color: ${tokens_1.contract.fgPrimary}; }
34
+
35
+ /* Export-data empty state -- measured: 14/500/63%-opacity, centred in a
36
+ 40px row, no border of its own (the Table wrapper already draws it). */
37
+ & .crisp-workspacegeneralsettings-emptyrow { padding: ${tokens_1.contract.space["2.5"]} ${tokens_1.contract.space["4"]}; font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); text-align: center; }
38
+
39
+ /* Danger zone: a red-tinted bordered row, distinct from every other
40
+ card on the page. */
41
+ & .crisp-workspacegeneralsettings-dangerrow { display: flex; align-items: center; justify-content: space-between; gap: ${tokens_1.contract.space["6"]}; padding: ${tokens_1.contract.space["3"]} ${tokens_1.contract.space["4"]}; border: 1px solid color-mix(in srgb, ${tokens_1.contract.bgDanger} 30%, transparent); border-radius: 12px; background: color-mix(in srgb, ${tokens_1.contract.bgDanger} 6%, transparent); }
42
+ & .crisp-workspacegeneralsettings-dangertext { display: flex; flex-direction: column; gap: ${tokens_1.contract.space["1"]}; }
43
+ & .crisp-workspacegeneralsettings-rowtitle { font-size: ${tokens_1.contract.text.lg}; font-weight: ${tokens_1.contract.weight.medium}; color: ${tokens_1.contract.fgPrimary}; }
44
+ & .crisp-workspacegeneralsettings-dangerwarning { font-size: ${tokens_1.contract.text.sm}; font-weight: ${tokens_1.contract.weight.medium}; color: color-mix(in srgb, ${tokens_1.contract.fgPrimary} 63%, transparent); }
45
+ `,
46
+ variants: {},
47
+ defaultVariants: {},
48
+ compoundVariants: [],
49
+ });
50
+ exports.workspacegeneralsettingsRecipe = (0, core_1.resolveRecipe)(config);
51
+ exports.default = config;
@@ -19,4 +19,5 @@ exports.contract = Object.assign(colors, {
19
19
  font: mapScale("font", scale_1.font),
20
20
  text: mapScale("text", scale_1.text),
21
21
  weight: mapScale("weight", scale_1.weight),
22
+ tracking: mapScale("tracking", scale_1.tracking),
22
23
  });
@@ -15,9 +15,11 @@ const contract_1 = require("./contract");
15
15
  */
16
16
  exports.elevation = {
17
17
  /**
18
- * Tier 1 — anything floating and *attached*: menus, popovers, dropdowns,
18
+ * Tier 1 — anything floating and *attached*: popovers, dropdowns,
19
19
  * hover-preview cards, the floating sidebar, the record peek, drawers, the
20
20
  * bulk bar. Pairs with a 10–12px radius and, for panels, an 8px gutter.
21
+ * NOT `Menu` (your-moon/crisp#934) -- that moved to
22
+ * `selectFloating`, seed-design's own flat shadow, below.
21
23
  */
22
24
  floating: `inset 0 0 0 1px ${contract_1.contract.ringPopover}, 0 0 0 1px ${contract_1.contract.shadowPopover1}, 0 4px 8px -4px ${contract_1.contract.shadowPopover2}, 0 4px 12px -2px ${contract_1.contract.shadowPopover3}`,
23
25
  /**
@@ -60,10 +62,11 @@ exports.elevation = {
60
62
  */
61
63
  fieldNoRing: `0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04)`,
62
64
  /**
63
- * Select's own listbox shadow (crisp/#867) — seed-design's `$shadow.s3`, a
64
- * single layer, NOT `floating` above. This component follows seed, not
65
- * Attio, for the same reason `DatePicker` follows seed's calendar
66
- * structure: an explicit owner request to match seed-design exactly.
65
+ * Seed-design's own `$shadow.s3`, a single flat layer, NOT `floating`
66
+ * above. Originally Select's own listbox shadow (crisp/#867); also `Menu`'s
67
+ * (your-moon/crisp#934) -- the raw seed dump confirms Menu
68
+ * is the one component seed's own spec gives a shadow to at all, and it's
69
+ * this exact value. Despite the name, not exclusive to Select.
67
70
  */
68
71
  selectFloating: `0 4px 16px ${contract_1.contract.shadowSelect}`,
69
72
  };
@@ -66,14 +66,34 @@ exports.palette = {
66
66
  ringBrandSoft: { light: "#d6e5ff", dark: "#212224" },
67
67
  tileActive: { light: "#ffffff", dark: "#101112" },
68
68
  tileActiveShadow: { light: "rgba(0,0,0,0.04)", dark: "rgba(0,0,0,0)" },
69
- // Dialog's page-dimming backdrop (crisp#677) — measured live behind the
70
- // Create-attribute FormDialog, both themes: `rgba(0,0,0,.25)` light,
71
- // `rgba(0,0,0,.55)` dark. `Dialog`'s own backdrop had shipped fully
72
- // `transparent` (AUTHORING's Lesson 14 measured the command palette has
73
- // NO dark backdrop and that got generalized to every `Dialog`, which this
74
- // corrects — the palette is a different surface from a plain content
75
- // dialog and really does dim the page).
76
- bgScrim: { light: "rgba(0,0,0,0.25)", dark: "rgba(0,0,0,0.55)" },
69
+ // Dialog's page-dimming backdrop (crisp#677, Attio's own measured value:
70
+ // `rgba(0,0,0,.25)` light, `rgba(0,0,0,.55)` dark — `Dialog`'s own backdrop
71
+ // had shipped fully `transparent`, AUTHORING's Lesson 14 measured the
72
+ // command palette has NO dark backdrop and that got generalized to every
73
+ // `Dialog`, which this corrected).
74
+ //
75
+ // your-moon/crisp#934: light theme moved to seed-design's own scrim
76
+ // (`#00000074` ≈ 45% black, `bg.overlay`) — the owner's flat-dialog
77
+ // directive names "seed's own scrim" specifically, now that elevation is
78
+ // conveyed by the scrim alone (no more frosted-glass shadow/blur). Dark
79
+ // theme's `.55` is UNCHANGED: seed's own token system has no separate
80
+ // dark-theme scrim value to adopt, and `.55` wasn't found wrong -- only
81
+ // light had a sourced replacement value to move to.
82
+ bgScrim: { light: "rgba(0,0,0,0.45)", dark: "rgba(0,0,0,0.55)" },
83
+ // seed-design's `$color.bg.overlay` (BottomSheet/MenuSheet's own backdrop,
84
+ // crisp#911) — kept as its OWN token rather than folded into `bgScrim`
85
+ // above, even though #934 (landed after this one was added) moved
86
+ // `bgScrim`'s LIGHT value to the same `#00000074`: `bgOverlayStrong` is
87
+ // seed's literally theme-CONSTANT value (`color.yaml` gives the same hex
88
+ // for both `theme-light` and `theme-dark`), while `bgScrim` still differs
89
+ // by theme (`.45`/`.55`) -- the two tokens express different design
90
+ // decisions that currently coincide in one theme only.
91
+ bgOverlayStrong: { light: "#00000074", dark: "#00000074" },
92
+ // seed-design's `$color.stroke.neutral-muted` (MenuSheet group divider,
93
+ // crisp#911) -- a faint alpha hairline between grouped rows, theme-flipping
94
+ // (`color.yaml`: `static-black-alpha-300` light / `static-white-alpha-100`
95
+ // dark).
96
+ strokeGroupDivider: { light: "#00000010", dark: "#ffffff17" },
77
97
  // The discard-confirm's description line (crisp#677, `Dialog`'s new
78
98
  // `variant="alert"`) — measured live, both themes, over `popoverBg`: a
79
99
  // theme-relative alpha rather than a flat gray, so it stays legible if
@@ -9,7 +9,7 @@
9
9
  // Recipes MUST reference these through the contract (`c.space[...]`), never a
10
10
  // literal px — this file is the only exception.
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.weight = exports.text = exports.font = exports.size = exports.radius = exports.space = void 0;
12
+ exports.tracking = exports.weight = exports.text = exports.font = exports.size = exports.radius = exports.space = void 0;
13
13
  // Spacing: gaps, padding, margins. Keys follow the Tailwind step convention
14
14
  // (0.5 = half a 4px step = 2px) so the numbers stay legible to consumers.
15
15
  exports.space = {
@@ -30,13 +30,22 @@ exports.space = {
30
30
  // (inputs, rows, tiles); full is the pill.
31
31
  exports.radius = {
32
32
  xs: "4px", // seed-design's $radius.r1 — small badge / checkbox box corner
33
- chip: "7px", // tag / chip corner — the single most used radius
33
+ // your-moon/crisp#919: was `7px` (Attio's own most-measured
34
+ // radius, 70 occurrences) -- now a pill, matching seed-design's own
35
+ // `chip.yaml` (`$radius.full` at every size, no size-based radius step at
36
+ // all, unlike Button/Badge). Same numeric value as `full` below, kept as
37
+ // its own named token because every one of this token's ~9 consumers
38
+ // (Chip, DataTable/RecordPage/RecordsTable/MultiSelect's own tag/mention
39
+ // rules, TableToolbar/DatePickerField's date-preset chips) reasons about
40
+ // "the chip corner" as its own concept, not literally "a generic pill".
41
+ chip: "999px",
34
42
  sm: "6px", // chips, badges
35
43
  md: "8px", // inputs, search box
36
44
  lg: "9px", // rows, tiles, list items
37
45
  xl: "12px", // overlay items (command rows)
38
46
  "2xl": "16px", // overlay panels (command surface)
39
47
  "3xl": "20px", // seed-design's $radius.r5 — Select's listbox corner (crisp/#867)
48
+ "4xl": "24px", // seed-design's $radius.r6 — BottomSheet's top corner radius (crisp/#911)
40
49
  full: "999px", // pills
41
50
  };
42
51
  // Component sizing — recurring measured dimensions that are neither spacing nor
@@ -88,3 +97,36 @@ exports.weight = {
88
97
  semibold: "600",
89
98
  bold: "700", // seed-design's font-weight-bold, for the seed-styled calendar
90
99
  };
100
+ // Size-based letter-spacing ramp for DISPLAY/HEADING type (18px and up —
101
+ // `text.*` above tops out at 16px and stays untracked). crisp's five
102
+ // already-shipped headings tighten as they grow — authshell 20px/-0.4px (2%
103
+ // of size), objectsettings 24px/-0.48px (2%), richtext 32px/-0.6px (1.875%)
104
+ // — all Attio-measured (Inter) and left exactly as they are; this token
105
+ // never touches them, or the button (-0.07px) / table-cell (-0.14px)
106
+ // tracking, which are body sizes, not display type. (statcard's 28px/-0.4px,
107
+ // 1.43%, is a looser outlier — it sets tabular numerals, not prose — and is
108
+ // also left alone.)
109
+ //
110
+ // crisp#909: the study at docs/study/korean/ observed that Naver and Kakao
111
+ // both tighten tracking as type gets bigger, and crisp's OWN large type
112
+ // (EmptyState's 20px title, Dialog's 18px alert title, and any future
113
+ // heading) had no tracking at all — it read as default, not set. The study
114
+ // supplied the PATTERN only, never a number: Naver/Kakao's own values are
115
+ // Korean-specific and were not copied. The numbers below come from rendering
116
+ // real Mongolian Cyrillic ("Эрсдэлийн бүртгэл", "Хяналтын самбар") in VK Sans
117
+ // Display — crisp's own font override, see `font.sans` above — at every
118
+ // display size crisp uses today (18/20/24/26/28/32px), screenshotting six
119
+ // candidates per size (0%, 1%, 1.5%, 2%, 2.5%, 3% of the font-size) and
120
+ // checking for glyph collision. None collided even at 3%, so the pre-existing
121
+ // 2%-of-size rule the five Attio headings already happen to follow was kept
122
+ // as the ramp, rounded to the nearest 0.01px — it reads as deliberately set
123
+ // with headroom to spare, and keeps new display type visually consistent
124
+ // with the Attio-measured headings already shipped.
125
+ exports.tracking = {
126
+ "18": "-0.36px",
127
+ "20": "-0.4px",
128
+ "24": "-0.48px",
129
+ "26": "-0.52px",
130
+ "28": "-0.56px",
131
+ "32": "-0.64px",
132
+ };
@@ -41,6 +41,8 @@ exports.semantic = {
41
41
  bgTileActive: "tileActive",
42
42
  shadowTileActive: "tileActiveShadow",
43
43
  bgScrim: "bgScrim",
44
+ bgOverlayStrong: "bgOverlayStrong",
45
+ strokeGroupDivider: "strokeGroupDivider",
44
46
  fgAlertDescription: "fgAlertDescription",
45
47
  bgOverlayFrost: "overlayFrost",
46
48
  shadowOverlay1: "shadowOverlay1",
@@ -1,30 +1,38 @@
1
1
  .crisp-columncalc {
2
- display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would shrink the button back to its text. Make the wrapper fill too, so the whole cell stays clickable. */
2
+ display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would
3
+ shrink the button back to its text. Make the wrapper fill too, so the
4
+ whole cell stays clickable. */
3
5
  & .crisp-menu { width: 100%; height: 100%; }
4
- /* No radius: the trigger fills the cell, so rounding its own corners leaves the cell's background showing through at the four corners as
6
+ /* No radius: the trigger fills the cell, so rounding its own corners
7
+ leaves the cell's background showing through at the four corners as
5
8
  soon as the hover tint paints. Everything else that fills a grid cell
6
9
  agrees -- recordstable-sum-btn, the same summary trigger, declares no
7
10
  radius, and datatable-grip and the embedded pickers zero theirs. An 8px
8
11
  radius survived the chip-to-full-cell conversion and shipped rounded
9
- until #282, so the spec check now guards it. */
10
- /* The hit target is the WHOLE summary cell -- measured 246x36 with
12
+ until #282, so the spec check now guards it. */ /* The hit target is the WHOLE summary cell -- measured 246x36 with
11
13
  padding 0 12px, not a content-sized chip. Clicking anywhere in the cell
12
14
  opens the aggregation menu.
13
15
  No `min-height` (crisp#834, found reproducing the footer-row-38px-
14
- not-36px bug in an isolated browser test, not table.recipe.ts's own border/box-sizing, the hypothesis the issue itself flagged as unconfirmed): the table cell's OWN `height: tableRow` (36px,
16
+ not-36px bug in an isolated browser test, not table.recipe.ts's own
17
+ border/box-sizing, the hypothesis the issue itself flagged as
18
+ unconfirmed): the table cell's OWN `height: tableRow` (36px,
15
19
  border-box) leaves 34px of content box once its 2px of top+bottom
16
20
  border are counted, and `min-height: tableRow` here demanded 36px
17
21
  of CONTENT height regardless -- overflowing the cell by 2px, which
18
22
  auto-height table layout resolves by growing the whole row to fit,
19
23
  landing at exactly the reported 38. `height: 100%` alone already
20
- fills whatever the cell's real content box is (the doc comment above this rule's own stated intent), with nothing left demanding more. */
24
+ fills whatever the cell's real content box is (the doc comment above
25
+ this rule's own stated intent), with nothing left demanding more. */
21
26
  & .crisp-columncalc-trigger { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
22
27
  & .crisp-columncalc-trigger:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
23
28
  & .crisp-columncalc-trigger svg { flex-shrink: 0; opacity: 0.7; }
24
29
  & .crisp-columncalc-trigger[data-align="right"] { justify-content: flex-end; }
25
30
  & .crisp-columncalc-placeholder { overflow: hidden; text-overflow: ellipsis; }
26
31
  & .crisp-columncalc-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; }
27
- /* crisp#837: re-measured live against Attio's real footer calc label -- 14px (was 13px, `c.text.md`, fixed on the shared trigger rule above) and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this file's own -op label already should have used instead of the flatter
32
+ /* crisp#837: re-measured live against Attio's real footer calc label --
33
+ 14px (was 13px, `c.text.md`, fixed on the shared trigger rule above)
34
+ and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this
35
+ file's own -op label already should have used instead of the flatter
28
36
  `fgMuted` token (a close but not measured match). */
29
37
  & .crisp-columncalc-op { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
30
38
  & .crisp-columncalc-section { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -1,31 +1,39 @@
1
1
  @layer crisp-components {
2
2
  .crisp-columncalc {
3
- display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would shrink the button back to its text. Make the wrapper fill too, so the whole cell stays clickable. */
3
+ display: flex; align-items: stretch; width: 100%; height: 100%; font-family: var(--crisp-font-sans); /* Menu wraps its trigger in a flex div that sizes to content, which would
4
+ shrink the button back to its text. Make the wrapper fill too, so the
5
+ whole cell stays clickable. */
4
6
  & .crisp-menu { width: 100%; height: 100%; }
5
- /* No radius: the trigger fills the cell, so rounding its own corners leaves the cell's background showing through at the four corners as
7
+ /* No radius: the trigger fills the cell, so rounding its own corners
8
+ leaves the cell's background showing through at the four corners as
6
9
  soon as the hover tint paints. Everything else that fills a grid cell
7
10
  agrees -- recordstable-sum-btn, the same summary trigger, declares no
8
11
  radius, and datatable-grip and the embedded pickers zero theirs. An 8px
9
12
  radius survived the chip-to-full-cell conversion and shipped rounded
10
- until #282, so the spec check now guards it. */
11
- /* The hit target is the WHOLE summary cell -- measured 246x36 with
13
+ until #282, so the spec check now guards it. */ /* The hit target is the WHOLE summary cell -- measured 246x36 with
12
14
  padding 0 12px, not a content-sized chip. Clicking anywhere in the cell
13
15
  opens the aggregation menu.
14
16
  No `min-height` (crisp#834, found reproducing the footer-row-38px-
15
- not-36px bug in an isolated browser test, not table.recipe.ts's own border/box-sizing, the hypothesis the issue itself flagged as unconfirmed): the table cell's OWN `height: tableRow` (36px,
17
+ not-36px bug in an isolated browser test, not table.recipe.ts's own
18
+ border/box-sizing, the hypothesis the issue itself flagged as
19
+ unconfirmed): the table cell's OWN `height: tableRow` (36px,
16
20
  border-box) leaves 34px of content box once its 2px of top+bottom
17
21
  border are counted, and `min-height: tableRow` here demanded 36px
18
22
  of CONTENT height regardless -- overflowing the cell by 2px, which
19
23
  auto-height table layout resolves by growing the whole row to fit,
20
24
  landing at exactly the reported 38. `height: 100%` alone already
21
- fills whatever the cell's real content box is (the doc comment above this rule's own stated intent), with nothing left demanding more. */
25
+ fills whatever the cell's real content box is (the doc comment above
26
+ this rule's own stated intent), with nothing left demanding more. */
22
27
  & .crisp-columncalc-trigger { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; height: 100%; margin: 0; padding: 0 var(--crisp-space-3); border: none; background: transparent; color: var(--crisp-fg-muted); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s, color .12s; }
23
28
  & .crisp-columncalc-trigger:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
24
29
  & .crisp-columncalc-trigger svg { flex-shrink: 0; opacity: 0.7; }
25
30
  & .crisp-columncalc-trigger[data-align="right"] { justify-content: flex-end; }
26
31
  & .crisp-columncalc-placeholder { overflow: hidden; text-overflow: ellipsis; }
27
32
  & .crisp-columncalc-value { color: var(--crisp-fg-primary); font-variant-numeric: tabular-nums; }
28
- /* crisp#837: re-measured live against Attio's real footer calc label -- 14px (was 13px, `c.text.md`, fixed on the shared trigger rule above) and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this file's own -op label already should have used instead of the flatter
33
+ /* crisp#837: re-measured live against Attio's real footer calc label --
34
+ 14px (was 13px, `c.text.md`, fixed on the shared trigger rule above)
35
+ and rgba(0,0,0,.63), the same color-mix(fgPrimary, 63%) figure this
36
+ file's own -op label already should have used instead of the flatter
29
37
  `fgMuted` token (a close but not measured match). */
30
38
  & .crisp-columncalc-op { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
31
39
  & .crisp-columncalc-section { padding: var(--crisp-space-1-5) var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
package/dist/command.css CHANGED
@@ -7,28 +7,32 @@
7
7
  & .crisp-command-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
8
8
  & .crisp-command-control { display: flex; align-items: center; gap: var(--crisp-space-2-5); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
9
9
  & .crisp-command-control svg { flex-shrink: 0; }
10
- /* The palette's label element. It exists for the assistive tree only: zag's combobox names the input through it and points the listbox's
10
+ /* The palette's label element. It exists for the assistive tree only: zag's
11
+ combobox names the input through it and points the listbox's
11
12
  aria-labelledby at it, and without it both were unnamed and the reference
12
13
  resolved to nothing (#225). Clipped rather than display:none, which would
13
14
  take it out of the tree it exists for. */
14
- & .crisp-command-srlabel { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
15
- & .crisp-command-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-xl); color: var(--crisp-fg-primary); }
16
- & .crisp-command-input::placeholder { color: var(--crisp-fg-muted); }
17
- & .crisp-command-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-1) var(--crisp-space-2-5); display: flex; flex-direction: column; gap: var(--crisp-space-px); }
18
- & .crisp-command-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
19
- & .crisp-command-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding-inline: var(--crisp-space-2-5); border-radius: var(--crisp-radius-xl); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; }
20
- & .crisp-command-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
21
- & .crisp-command-item[data-highlighted] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
22
- & .crisp-command-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
23
- & .crisp-command-item-shortcut { margin-inline-start: auto; flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
24
- & .crisp-command-group-label { padding: var(--crisp-space-2) var(--crisp-space-2-5) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
25
- & .crisp-command-list > .crisp-command-group-label:first-child { padding-top: var(--crisp-space-1); }
26
- & .crisp-command-footer { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; height: 44px; padding: 0 var(--crisp-space-2-5); border-top: 1px solid var(--crisp-border-subtle); }
27
- & .crisp-command-footer-nav { display: flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
28
- & .crisp-command-footer-action { display: flex; align-items: center; gap: var(--crisp-space-2); height: 28px; max-width: 60%; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
29
- & .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
30
- & .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
31
- & .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
15
+ & .crisp-command-srlabel { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
16
+ & .crisp-command-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-xl); color: var(--crisp-fg-primary); }
17
+ & .crisp-command-input::placeholder { color: var(--crisp-fg-muted); }
18
+ & .crisp-command-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-1) var(--crisp-space-2-5); display: flex; flex-direction: column; gap: var(--crisp-space-px); }
19
+ & .crisp-command-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
20
+ & .crisp-command-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding-inline: var(--crisp-space-2-5); border-radius: var(--crisp-radius-xl); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; }
21
+ & .crisp-command-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
22
+ & .crisp-command-item[data-highlighted] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
23
+ & .crisp-command-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
24
+ & .crisp-command-item-shortcut { margin-inline-start: auto; flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
25
+ & .crisp-command-group-label { padding: var(--crisp-space-2) var(--crisp-space-2-5) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
26
+ & .crisp-command-list > .crisp-command-group-label:first-child { padding-top: var(--crisp-space-1); }
27
+ & .crisp-command-footer { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; height: 44px; padding: 0 var(--crisp-space-2-5); border-top: 1px solid var(--crisp-border-subtle); }
28
+ & .crisp-command-footer-nav { display: flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
29
+ /* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
30
+ the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
31
+ clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897). */
32
+ & .crisp-command-footer-action { display: flex; align-items: center; gap: var(--crisp-space-2); height: 28px; max-width: 60%; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
33
+ & .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
34
+ & .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
35
+ & .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
32
36
  }
33
37
 
34
38
  @media (prefers-reduced-motion: reduce) {
@@ -8,28 +8,32 @@
8
8
  & .crisp-command-card { display: flex; flex-direction: column; flex: 1; min-height: 0; box-sizing: border-box; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); overflow: hidden; }
9
9
  & .crisp-command-control { display: flex; align-items: center; gap: var(--crisp-space-2-5); height: 52px; flex-shrink: 0; padding: 0 var(--crisp-space-4); border-bottom: 1px solid var(--crisp-border-subtle); color: var(--crisp-fg-muted); }
10
10
  & .crisp-command-control svg { flex-shrink: 0; }
11
- /* The palette's label element. It exists for the assistive tree only: zag's combobox names the input through it and points the listbox's
11
+ /* The palette's label element. It exists for the assistive tree only: zag's
12
+ combobox names the input through it and points the listbox's
12
13
  aria-labelledby at it, and without it both were unnamed and the reference
13
14
  resolved to nothing (#225). Clipped rather than display:none, which would
14
15
  take it out of the tree it exists for. */
15
- & .crisp-command-srlabel { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
16
- & .crisp-command-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-xl); color: var(--crisp-fg-primary); }
17
- & .crisp-command-input::placeholder { color: var(--crisp-fg-muted); }
18
- & .crisp-command-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-1) var(--crisp-space-2-5); display: flex; flex-direction: column; gap: var(--crisp-space-px); }
19
- & .crisp-command-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
20
- & .crisp-command-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding-inline: var(--crisp-space-2-5); border-radius: var(--crisp-radius-xl); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; }
21
- & .crisp-command-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
22
- & .crisp-command-item[data-highlighted] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
23
- & .crisp-command-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
24
- & .crisp-command-item-shortcut { margin-inline-start: auto; flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
25
- & .crisp-command-group-label { padding: var(--crisp-space-2) var(--crisp-space-2-5) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
26
- & .crisp-command-list > .crisp-command-group-label:first-child { padding-top: var(--crisp-space-1); }
27
- & .crisp-command-footer { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; height: 44px; padding: 0 var(--crisp-space-2-5); border-top: 1px solid var(--crisp-border-subtle); }
28
- & .crisp-command-footer-nav { display: flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
29
- & .crisp-command-footer-action { display: flex; align-items: center; gap: var(--crisp-space-2); height: 28px; max-width: 60%; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
30
- & .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
31
- & .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
32
- & .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
16
+ & .crisp-command-srlabel { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
17
+ & .crisp-command-input { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-xl); color: var(--crisp-fg-primary); }
18
+ & .crisp-command-input::placeholder { color: var(--crisp-fg-muted); }
19
+ & .crisp-command-list { flex: 1; min-height: 0; overflow-y: auto; padding: var(--crisp-space-1) var(--crisp-space-2-5); display: flex; flex-direction: column; gap: var(--crisp-space-px); }
20
+ & .crisp-command-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
21
+ & .crisp-command-item { box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2); height: 36px; padding-inline: var(--crisp-space-2-5); border-radius: var(--crisp-radius-xl); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; }
22
+ & .crisp-command-item svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
23
+ & .crisp-command-item[data-highlighted] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
24
+ & .crisp-command-item-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
25
+ & .crisp-command-item-shortcut { margin-inline-start: auto; flex-shrink: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
26
+ & .crisp-command-group-label { padding: var(--crisp-space-2) var(--crisp-space-2-5) var(--crisp-space-1); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
27
+ & .crisp-command-list > .crisp-command-group-label:first-child { padding-top: var(--crisp-space-1); }
28
+ & .crisp-command-footer { display: flex; align-items: center; justify-content: space-between; flex-shrink: 0; height: 44px; padding: 0 var(--crisp-space-2-5); border-top: 1px solid var(--crisp-border-subtle); }
29
+ & .crisp-command-footer-nav { display: flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
30
+ /* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
31
+ the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
32
+ clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897). */
33
+ & .crisp-command-footer-action { display: flex; align-items: center; gap: var(--crisp-space-2); height: 28px; max-width: 60%; padding: 0 var(--crisp-space-1) 0 var(--crisp-space-2-5); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-brand-contrast); color: var(--crisp-fg-on-brand); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
34
+ & .crisp-command-footer-action:disabled { opacity: 0.5; cursor: default; }
35
+ & .crisp-command-footer-action-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
36
+ & .crisp-command-footer-key { display: inline-flex; align-items: center; justify-content: center; min-width: 18px; height: 18px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: rgba(255,255,255,0.22); font-size: var(--crisp-text-xs); }
33
37
  }
34
38
 
35
39
  @media (prefers-reduced-motion: reduce) {