@crisp-ui-kit/crisp 0.57.2 → 0.57.4

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 (200) hide show
  1. package/dist/assigneepicker.css +13 -0
  2. package/dist/assigneepicker.d.ts +7 -0
  3. package/dist/assigneepicker.layered.css +15 -0
  4. package/dist/button.css +3 -0
  5. package/dist/button.d.ts +2 -2
  6. package/dist/button.layered.css +3 -0
  7. package/dist/chip.css +1 -1
  8. package/dist/chip.layered.css +1 -1
  9. package/dist/cjs/components/breadcrumb/breadcrumb.js +1 -1
  10. package/dist/cjs/components/button/button.recipe.js +33 -0
  11. package/dist/cjs/components/chip/chip.recipe.js +3 -1
  12. package/dist/cjs/components/datatable/datatable.js +6 -3
  13. package/dist/cjs/components/datatable/datatable.recipe.js +45 -6
  14. package/dist/cjs/components/datepickerfield/datepickerfield.js +2 -2
  15. package/dist/cjs/components/datepickerfield/datepickerfield.recipe.js +16 -3
  16. package/dist/cjs/components/menu/menu.js +65 -9
  17. package/dist/cjs/components/multiselect/multiselect.js +3 -0
  18. package/dist/cjs/components/multiselect/multiselect.recipe.js +18 -0
  19. package/dist/cjs/components/select/select.js +2 -2
  20. package/dist/cjs/components/select/select.recipe.js +19 -0
  21. package/dist/cjs/components/table/table.recipe.js +7 -1
  22. package/dist/cjs/core/floating-portal.js +7 -4
  23. package/dist/cjs/core/index.js +2 -1
  24. package/dist/cjs/core/place-floating.js +38 -0
  25. package/dist/cjs/index.js +8 -0
  26. package/dist/cjs/product/assigneepicker/assigneepicker.js +127 -0
  27. package/dist/cjs/product/assigneepicker/assigneepicker.recipe.js +36 -0
  28. package/dist/cjs/product/assigneepicker/index.js +7 -0
  29. package/dist/cjs/product/inbox/inbox.js +11 -3
  30. package/dist/cjs/product/notesgallery/index.js +7 -0
  31. package/dist/cjs/product/notesgallery/notesgallery.js +80 -0
  32. package/dist/cjs/product/notesgallery/notesgallery.recipe.js +46 -0
  33. package/dist/cjs/product/objectpagemenu/index.js +17 -0
  34. package/dist/cjs/product/objectpagemenu/objectpagemenu.js +26 -0
  35. package/dist/cjs/product/objectpagemenu/objectpagemenu.recipe.js +30 -0
  36. package/dist/cjs/product/objectsettings/objectsettings.js +107 -14
  37. package/dist/cjs/product/recordpage/index.js +2 -1
  38. package/dist/cjs/product/recordpage/recordpage.js +112 -7
  39. package/dist/cjs/product/recordpage/recordpage.recipe.js +63 -0
  40. package/dist/cjs/product/recordpicker/index.js +7 -0
  41. package/dist/cjs/product/recordpicker/recordpicker.js +100 -0
  42. package/dist/cjs/product/recordpicker/recordpicker.recipe.js +36 -0
  43. package/dist/cjs/product/savedviews/index.js +2 -1
  44. package/dist/cjs/product/savedviews/savedviews.js +22 -0
  45. package/dist/cjs/product/savedviews/savedviews.recipe.js +47 -0
  46. package/dist/cjs/product/share/index.js +7 -0
  47. package/dist/cjs/product/share/share.js +179 -0
  48. package/dist/cjs/product/share/share.recipe.js +114 -0
  49. package/dist/cjs/product/shortcutssheet/index.js +17 -0
  50. package/dist/cjs/product/shortcutssheet/shortcutssheet.js +125 -0
  51. package/dist/cjs/product/shortcutssheet/shortcutssheet.recipe.js +50 -0
  52. package/dist/cjs/product/taskeditpopover/index.js +7 -0
  53. package/dist/cjs/product/taskeditpopover/taskeditpopover.js +159 -0
  54. package/dist/cjs/product/taskeditpopover/taskeditpopover.recipe.js +68 -0
  55. package/dist/cjs/product/workspaceswitchermenu/index.js +17 -0
  56. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.js +38 -0
  57. package/dist/cjs/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +34 -0
  58. package/dist/cjs/tokens/palette.js +27 -0
  59. package/dist/cjs/tokens/semantic.js +20 -0
  60. package/dist/datatable.css +50 -11
  61. package/dist/datatable.layered.css +50 -11
  62. package/dist/datepickerfield.css +8 -2
  63. package/dist/datepickerfield.d.ts +2 -2
  64. package/dist/datepickerfield.layered.css +8 -2
  65. package/dist/esm/components/breadcrumb/breadcrumb.js +1 -1
  66. package/dist/esm/components/button/button.recipe.js +33 -0
  67. package/dist/esm/components/chip/chip.recipe.js +3 -1
  68. package/dist/esm/components/datatable/datatable.js +6 -3
  69. package/dist/esm/components/datatable/datatable.recipe.js +45 -6
  70. package/dist/esm/components/datepickerfield/datepickerfield.js +2 -2
  71. package/dist/esm/components/datepickerfield/datepickerfield.recipe.js +16 -3
  72. package/dist/esm/components/menu/menu.js +64 -8
  73. package/dist/esm/components/multiselect/multiselect.js +3 -0
  74. package/dist/esm/components/multiselect/multiselect.recipe.js +18 -0
  75. package/dist/esm/components/select/select.js +2 -2
  76. package/dist/esm/components/select/select.recipe.js +19 -0
  77. package/dist/esm/components/table/table.recipe.js +7 -1
  78. package/dist/esm/core/floating-portal.js +7 -4
  79. package/dist/esm/core/index.js +1 -1
  80. package/dist/esm/core/place-floating.js +37 -0
  81. package/dist/esm/index.js +8 -0
  82. package/dist/esm/product/assigneepicker/assigneepicker.js +91 -0
  83. package/dist/esm/product/assigneepicker/assigneepicker.recipe.js +33 -0
  84. package/dist/esm/product/assigneepicker/index.js +2 -0
  85. package/dist/esm/product/inbox/inbox.js +11 -3
  86. package/dist/esm/product/notesgallery/index.js +2 -0
  87. package/dist/esm/product/notesgallery/notesgallery.js +44 -0
  88. package/dist/esm/product/notesgallery/notesgallery.recipe.js +43 -0
  89. package/dist/esm/product/objectpagemenu/index.js +1 -0
  90. package/dist/esm/product/objectpagemenu/objectpagemenu.js +23 -0
  91. package/dist/esm/product/objectpagemenu/objectpagemenu.recipe.js +27 -0
  92. package/dist/esm/product/objectsettings/objectsettings.js +106 -13
  93. package/dist/esm/product/recordpage/index.js +1 -1
  94. package/dist/esm/product/recordpage/recordpage.js +112 -8
  95. package/dist/esm/product/recordpage/recordpage.recipe.js +63 -0
  96. package/dist/esm/product/recordpicker/index.js +2 -0
  97. package/dist/esm/product/recordpicker/recordpicker.js +64 -0
  98. package/dist/esm/product/recordpicker/recordpicker.recipe.js +33 -0
  99. package/dist/esm/product/savedviews/index.js +1 -1
  100. package/dist/esm/product/savedviews/savedviews.js +22 -1
  101. package/dist/esm/product/savedviews/savedviews.recipe.js +47 -0
  102. package/dist/esm/product/share/index.js +2 -0
  103. package/dist/esm/product/share/share.js +143 -0
  104. package/dist/esm/product/share/share.recipe.js +111 -0
  105. package/dist/esm/product/shortcutssheet/index.js +1 -0
  106. package/dist/esm/product/shortcutssheet/shortcutssheet.js +88 -0
  107. package/dist/esm/product/shortcutssheet/shortcutssheet.recipe.js +47 -0
  108. package/dist/esm/product/taskeditpopover/index.js +2 -0
  109. package/dist/esm/product/taskeditpopover/taskeditpopover.js +123 -0
  110. package/dist/esm/product/taskeditpopover/taskeditpopover.recipe.js +65 -0
  111. package/dist/esm/product/workspaceswitchermenu/index.js +1 -0
  112. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.js +35 -0
  113. package/dist/esm/product/workspaceswitchermenu/workspaceswitchermenu.recipe.js +31 -0
  114. package/dist/esm/tokens/palette.js +27 -0
  115. package/dist/esm/tokens/semantic.js +20 -0
  116. package/dist/multiselect.css +18 -0
  117. package/dist/multiselect.layered.css +18 -0
  118. package/dist/native/tokens.d.ts +1 -1
  119. package/dist/native/tokens.js +56 -4
  120. package/dist/notesgallery.css +15 -0
  121. package/dist/notesgallery.d.ts +7 -0
  122. package/dist/notesgallery.layered.css +17 -0
  123. package/dist/objectpagemenu.css +3 -0
  124. package/dist/objectpagemenu.d.ts +7 -0
  125. package/dist/objectpagemenu.layered.css +5 -0
  126. package/dist/recordpage.css +59 -0
  127. package/dist/recordpage.layered.css +59 -0
  128. package/dist/recordpicker.css +13 -0
  129. package/dist/recordpicker.d.ts +7 -0
  130. package/dist/recordpicker.layered.css +15 -0
  131. package/dist/savedviews.css +47 -0
  132. package/dist/savedviews.layered.css +47 -0
  133. package/dist/select.css +19 -0
  134. package/dist/select.layered.css +19 -0
  135. package/dist/share.css +84 -0
  136. package/dist/share.d.ts +7 -0
  137. package/dist/share.layered.css +86 -0
  138. package/dist/shortcutssheet.css +24 -0
  139. package/dist/shortcutssheet.d.ts +7 -0
  140. package/dist/shortcutssheet.layered.css +26 -0
  141. package/dist/styles.css +438 -16
  142. package/dist/styles.layered.css +438 -16
  143. package/dist/table.css +7 -2
  144. package/dist/table.layered.css +7 -2
  145. package/dist/taskeditpopover.css +36 -0
  146. package/dist/taskeditpopover.d.ts +7 -0
  147. package/dist/taskeditpopover.layered.css +38 -0
  148. package/dist/tokens.css +26 -0
  149. package/dist/tokens.json +56 -4
  150. package/dist/types/components/breadcrumb/breadcrumb.d.ts +9 -1
  151. package/dist/types/components/button/button.d.ts +2 -0
  152. package/dist/types/components/button/button.recipe.d.ts +12 -0
  153. package/dist/types/components/chip/chip.recipe.d.ts +1 -1
  154. package/dist/types/components/datatable/datatable.d.ts +8 -0
  155. package/dist/types/components/datepickerfield/datepickerfield.d.ts +4 -1
  156. package/dist/types/components/datepickerfield/datepickerfield.recipe.d.ts +18 -3
  157. package/dist/types/components/menu/menu.d.ts +50 -7
  158. package/dist/types/components/multiselect/multiselect.d.ts +9 -0
  159. package/dist/types/components/select/select.d.ts +10 -0
  160. package/dist/types/core/floating-portal.d.ts +6 -5
  161. package/dist/types/core/index.d.ts +1 -1
  162. package/dist/types/core/place-floating.d.ts +37 -0
  163. package/dist/types/index.d.ts +8 -0
  164. package/dist/types/product/assigneepicker/assigneepicker.d.ts +36 -0
  165. package/dist/types/product/assigneepicker/assigneepicker.recipe.d.ts +3 -0
  166. package/dist/types/product/assigneepicker/index.d.ts +2 -0
  167. package/dist/types/product/inbox/inbox.d.ts +13 -1
  168. package/dist/types/product/notesgallery/index.d.ts +2 -0
  169. package/dist/types/product/notesgallery/notesgallery.d.ts +54 -0
  170. package/dist/types/product/notesgallery/notesgallery.recipe.d.ts +3 -0
  171. package/dist/types/product/objectpagemenu/index.d.ts +1 -0
  172. package/dist/types/product/objectpagemenu/objectpagemenu.d.ts +40 -0
  173. package/dist/types/product/objectpagemenu/objectpagemenu.recipe.d.ts +17 -0
  174. package/dist/types/product/objectsettings/objectsettings.d.ts +71 -15
  175. package/dist/types/product/recordpage/index.d.ts +1 -1
  176. package/dist/types/product/recordpage/recordpage.d.ts +142 -1
  177. package/dist/types/product/recordpicker/index.d.ts +2 -0
  178. package/dist/types/product/recordpicker/recordpicker.d.ts +38 -0
  179. package/dist/types/product/recordpicker/recordpicker.recipe.d.ts +3 -0
  180. package/dist/types/product/savedviews/index.d.ts +1 -1
  181. package/dist/types/product/savedviews/savedviews.d.ts +36 -0
  182. package/dist/types/product/share/index.d.ts +2 -0
  183. package/dist/types/product/share/share.d.ts +85 -0
  184. package/dist/types/product/share/share.recipe.d.ts +3 -0
  185. package/dist/types/product/shortcutssheet/index.d.ts +1 -0
  186. package/dist/types/product/shortcutssheet/shortcutssheet.d.ts +49 -0
  187. package/dist/types/product/shortcutssheet/shortcutssheet.recipe.d.ts +3 -0
  188. package/dist/types/product/taskeditpopover/index.d.ts +2 -0
  189. package/dist/types/product/taskeditpopover/taskeditpopover.d.ts +67 -0
  190. package/dist/types/product/taskeditpopover/taskeditpopover.recipe.d.ts +3 -0
  191. package/dist/types/product/workspaceswitchermenu/index.d.ts +1 -0
  192. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.d.ts +54 -0
  193. package/dist/types/product/workspaceswitchermenu/workspaceswitchermenu.recipe.d.ts +19 -0
  194. package/dist/types/tokens/contract.d.ts +13 -0
  195. package/dist/types/tokens/palette.d.ts +52 -0
  196. package/dist/types/tokens/semantic.d.ts +20 -0
  197. package/dist/workspaceswitchermenu.css +4 -0
  198. package/dist/workspaceswitchermenu.d.ts +7 -0
  199. package/dist/workspaceswitchermenu.layered.css +6 -0
  200. package/package.json +41 -1
@@ -98,7 +98,13 @@
98
98
  & .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
99
99
  & .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
100
100
  & .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
101
- & .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
101
+ /* #719: overflow: clip, not hidden, on every truncation rule below --
102
+ hidden still honours a programmatic scrollLeft assignment (found via
103
+ a screenshot tool that pans anything with scrollWidth > clientWidth),
104
+ blanking or fragmenting the visible text even though real user
105
+ scrolling was already blocked. clip renders the ellipsis identically
106
+ and leaves no scroll position to move. */
107
+ & .crisp-datatable-th-label { overflow: clip; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
102
108
  /* #465: 12px per the comment above (and Attio's measured header cell
103
109
  padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
104
110
  own documented value. */
@@ -185,7 +191,7 @@
185
191
  /* reference picker: a leading 16px avatar per option, plus a trailing
186
192
  "Create X" row when the consumer supplies one (#449) -- same measured
187
193
  values as RecordsTable's own .crisp-recordstable-refoption*. */
188
- & .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
194
+ & .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: clip; text-overflow: ellipsis; }
189
195
  & .crisp-datatable-refoption-avatar { flex-shrink: 0; }
190
196
  & .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
191
197
  & .crisp-datatable-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; color: var(--crisp-fg-muted); font-size: var(--crisp-text-lg); }
@@ -261,7 +267,7 @@
261
267
  (#833/#835/#848) that happened to apply the same 500 to every
262
268
  primary-column body cell regardless of type. Made explicit here so
263
269
  fixing that leak doesn't also (wrongly) drop entity names to 400. */
264
- & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
270
+ & .crisp-datatable-entity-name { overflow: clip; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
265
271
  /* #893: shared by the button (onEntityClick, a different record) and
266
272
  the anchor (href, the row's own record) -- was button-only, which
267
273
  silently left a real <a> unstyled the day #893 added one. */
@@ -284,14 +290,29 @@
284
290
  Avatar's own already-shipped shape="rounded" value, not a new number.
285
291
  shape="circle" reuses Avatar's own shape="circle" value (radius.full)
286
292
  the same way, measured live on a real Attio person avatar. */
287
- & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
293
+ & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-tone); background: var(--crisp-bg-brand-solid); }
288
294
  & .crisp-datatable-avatar[data-shape="circle"] { border-radius: var(--crisp-radius-full); }
289
- & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
290
- & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
291
- & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
292
- & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
293
- & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
294
- & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
295
+ /* your-moon/crisp#891: every data-tone override painted ONLY a
296
+ background, inheriting the base rule's white fgOnBrand -- white
297
+ clears AA against none of these seven fills (brand 3.23:1, success
298
+ 3.96, warning 4.12, danger 3.76, purple 3.58, cyan 2.30, orange
299
+ 2.77). fgOnTone (ink, #101112 -- semantic.ts's own comment: "dark ink
300
+ clears AA on every tone in both themes") clears 4.5:1+ on every fill
301
+ here with a comfortable margin (brand 5.85, success 4.77/6.29,
302
+ danger 5.03/6.19, purple 5.27, cyan 8.23, orange 6.83, light/dark),
303
+ so the base rule's colour moves there and every override keeps it --
304
+ EXCEPT warning, whose raw fill (bgWarning) only clears 4.59:1 in
305
+ light, too thin a margin to rely on: it takes bgWarningSolid instead,
306
+ the same solid-warning-plus-ink pair Badge's own solid variant
307
+ already established (13.98/7.83), for the same reason (see
308
+ tokens/palette.ts's amberSolid comment). No background changes
309
+ otherwise -- the fills themselves are unaffected, only the text. */
310
+ & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); color: var(--crisp-fg-on-tone); }
311
+ & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning-solid); color: var(--crisp-fg-on-tone); }
312
+ & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); color: var(--crisp-fg-on-tone); }
313
+ & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); color: var(--crisp-fg-on-tone); }
314
+ & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); color: var(--crisp-fg-on-tone); }
315
+ & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); color: var(--crisp-fg-on-tone); }
295
316
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
296
317
  & .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
297
318
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
@@ -302,6 +323,24 @@
302
323
  & .crisp-datatable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
303
324
  & .crisp-datatable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
304
325
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); }
326
+ /* your-moon/crisp#998: Attio's own 12-colour tag palette (measured
327
+ live, see tokens/palette.ts's tagSwatch1 comment) -- flat black
328
+ text, no ring, unlike the tone family above. 7px radius/10px text
329
+ are measured literals (no matching step in the shared scale, same
330
+ as Select's own .crisp-select-swatch). */
331
+ & .crisp-datatable-swatch { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: 7px; font-size: 10px; font-weight: var(--crisp-weight-regular); white-space: nowrap; color: var(--crisp-fg-tag-swatch); }
332
+ & .crisp-datatable-swatch[data-swatch="1"] { background: var(--crisp-bg-tag-swatch1); }
333
+ & .crisp-datatable-swatch[data-swatch="2"] { background: var(--crisp-bg-tag-swatch2); }
334
+ & .crisp-datatable-swatch[data-swatch="3"] { background: var(--crisp-bg-tag-swatch3); }
335
+ & .crisp-datatable-swatch[data-swatch="4"] { background: var(--crisp-bg-tag-swatch4); }
336
+ & .crisp-datatable-swatch[data-swatch="5"] { background: var(--crisp-bg-tag-swatch5); }
337
+ & .crisp-datatable-swatch[data-swatch="6"] { background: var(--crisp-bg-tag-swatch6); }
338
+ & .crisp-datatable-swatch[data-swatch="7"] { background: var(--crisp-bg-tag-swatch7); }
339
+ & .crisp-datatable-swatch[data-swatch="8"] { background: var(--crisp-bg-tag-swatch8); }
340
+ & .crisp-datatable-swatch[data-swatch="9"] { background: var(--crisp-bg-tag-swatch9); }
341
+ & .crisp-datatable-swatch[data-swatch="10"] { background: var(--crisp-bg-tag-swatch10); }
342
+ & .crisp-datatable-swatch[data-swatch="11"] { background: var(--crisp-bg-tag-swatch11); }
343
+ & .crisp-datatable-swatch[data-swatch="12"] { background: var(--crisp-bg-tag-swatch12); }
305
344
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
306
345
  & .crisp-datatable-muted { color: var(--crisp-fg-muted); }
307
346
  /* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
@@ -312,7 +351,7 @@
312
351
  own .crisp-recordstable-link, which this mirrors: no underline at
313
352
  rest, underline on hover, own-colour text rather than a browser-blue
314
353
  link. */
315
- & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
354
+ & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: clip; text-overflow: ellipsis; }
316
355
  & .crisp-datatable-link:hover { text-decoration: underline; }
317
356
  /* phone cell type/editor (#765) -- measured live: the dial-code prefix
318
357
  is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
@@ -99,7 +99,13 @@
99
99
  & .crisp-datatable-group-count { margin-inline-start: var(--crisp-space-1-5); color: var(--crisp-fg-muted); font-variant-numeric: tabular-nums; }
100
100
  & .crisp-datatable-th-rename { width: 100%; min-width: 0; height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-1); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); outline: none; }
101
101
  & .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
102
- & .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
102
+ /* #719: overflow: clip, not hidden, on every truncation rule below --
103
+ hidden still honours a programmatic scrollLeft assignment (found via
104
+ a screenshot tool that pans anything with scrollWidth > clientWidth),
105
+ blanking or fragmenting the visible text even though real user
106
+ scrolling was already blocked. clip renders the ellipsis identically
107
+ and leaves no scroll position to move. */
108
+ & .crisp-datatable-th-label { overflow: clip; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
103
109
  /* #465: 12px per the comment above (and Attio's measured header cell
104
110
  padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
105
111
  own documented value. */
@@ -186,7 +192,7 @@
186
192
  /* reference picker: a leading 16px avatar per option, plus a trailing
187
193
  "Create X" row when the consumer supplies one (#449) -- same measured
188
194
  values as RecordsTable's own .crisp-recordstable-refoption*. */
189
- & .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
195
+ & .crisp-datatable-refoption { display: flex; align-items: center; gap: var(--crisp-space-2); min-width: 0; overflow: clip; text-overflow: ellipsis; }
190
196
  & .crisp-datatable-refoption-avatar { flex-shrink: 0; }
191
197
  & .crisp-datatable-refoption--create { color: var(--crisp-fg-muted); }
192
198
  & .crisp-datatable-empty { padding: var(--crisp-space-8) var(--crisp-space-3); text-align: center; color: var(--crisp-fg-muted); font-size: var(--crisp-text-lg); }
@@ -262,7 +268,7 @@
262
268
  (#833/#835/#848) that happened to apply the same 500 to every
263
269
  primary-column body cell regardless of type. Made explicit here so
264
270
  fixing that leak doesn't also (wrongly) drop entity names to 400. */
265
- & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
271
+ & .crisp-datatable-entity-name { overflow: clip; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--crisp-weight-medium); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--crisp-fg-primary) 9%, transparent); }
266
272
  /* #893: shared by the button (onEntityClick, a different record) and
267
273
  the anchor (href, the row's own record) -- was button-only, which
268
274
  silently left a real <a> unstyled the day #893 added one. */
@@ -285,14 +291,29 @@
285
291
  Avatar's own already-shipped shape="rounded" value, not a new number.
286
292
  shape="circle" reuses Avatar's own shape="circle" value (radius.full)
287
293
  the same way, measured live on a real Attio person avatar. */
288
- & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-brand); background: var(--crisp-bg-brand-solid); }
294
+ & .crisp-datatable-avatar { width: var(--crisp-size-icon); height: var(--crisp-size-icon); border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: var(--crisp-weight-semibold); text-transform: uppercase; color: var(--crisp-fg-on-tone); background: var(--crisp-bg-brand-solid); }
289
295
  & .crisp-datatable-avatar[data-shape="circle"] { border-radius: var(--crisp-radius-full); }
290
- & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); }
291
- & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning); }
292
- & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); }
293
- & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); }
294
- & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); }
295
- & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); }
296
+ /* your-moon/crisp#891: every data-tone override painted ONLY a
297
+ background, inheriting the base rule's white fgOnBrand -- white
298
+ clears AA against none of these seven fills (brand 3.23:1, success
299
+ 3.96, warning 4.12, danger 3.76, purple 3.58, cyan 2.30, orange
300
+ 2.77). fgOnTone (ink, #101112 -- semantic.ts's own comment: "dark ink
301
+ clears AA on every tone in both themes") clears 4.5:1+ on every fill
302
+ here with a comfortable margin (brand 5.85, success 4.77/6.29,
303
+ danger 5.03/6.19, purple 5.27, cyan 8.23, orange 6.83, light/dark),
304
+ so the base rule's colour moves there and every override keeps it --
305
+ EXCEPT warning, whose raw fill (bgWarning) only clears 4.59:1 in
306
+ light, too thin a margin to rely on: it takes bgWarningSolid instead,
307
+ the same solid-warning-plus-ink pair Badge's own solid variant
308
+ already established (13.98/7.83), for the same reason (see
309
+ tokens/palette.ts's amberSolid comment). No background changes
310
+ otherwise -- the fills themselves are unaffected, only the text. */
311
+ & .crisp-datatable-avatar[data-tone="success"] { background: var(--crisp-bg-success); color: var(--crisp-fg-on-tone); }
312
+ & .crisp-datatable-avatar[data-tone="warning"] { background: var(--crisp-bg-warning-solid); color: var(--crisp-fg-on-tone); }
313
+ & .crisp-datatable-avatar[data-tone="danger"] { background: var(--crisp-bg-danger); color: var(--crisp-fg-on-tone); }
314
+ & .crisp-datatable-avatar[data-tone="purple"] { background: var(--crisp-bg-purple); color: var(--crisp-fg-on-tone); }
315
+ & .crisp-datatable-avatar[data-tone="cyan"] { background: var(--crisp-bg-cyan); color: var(--crisp-fg-on-tone); }
316
+ & .crisp-datatable-avatar[data-tone="orange"] { background: var(--crisp-bg-orange); color: var(--crisp-fg-on-tone); }
296
317
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
297
318
  & .crisp-datatable-tags { display: flex; align-items: center; gap: var(--crisp-space-1); overflow: hidden; }
298
319
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
@@ -303,6 +324,24 @@
303
324
  & .crisp-datatable-tag[data-tone="purple"] { background: color-mix(in srgb, var(--crisp-bg-purple) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-purple) 80%, var(--crisp-fg-primary)); }
304
325
  & .crisp-datatable-tag[data-tone="cyan"] { background: color-mix(in srgb, var(--crisp-bg-cyan) 18%, transparent); color: color-mix(in srgb, var(--crisp-bg-cyan) 82%, var(--crisp-fg-primary)); }
305
326
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, var(--crisp-bg-orange) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-orange) 82%, var(--crisp-fg-primary)); }
327
+ /* your-moon/crisp#998: Attio's own 12-colour tag palette (measured
328
+ live, see tokens/palette.ts's tagSwatch1 comment) -- flat black
329
+ text, no ring, unlike the tone family above. 7px radius/10px text
330
+ are measured literals (no matching step in the shared scale, same
331
+ as Select's own .crisp-select-swatch). */
332
+ & .crisp-datatable-swatch { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: 7px; font-size: 10px; font-weight: var(--crisp-weight-regular); white-space: nowrap; color: var(--crisp-fg-tag-swatch); }
333
+ & .crisp-datatable-swatch[data-swatch="1"] { background: var(--crisp-bg-tag-swatch1); }
334
+ & .crisp-datatable-swatch[data-swatch="2"] { background: var(--crisp-bg-tag-swatch2); }
335
+ & .crisp-datatable-swatch[data-swatch="3"] { background: var(--crisp-bg-tag-swatch3); }
336
+ & .crisp-datatable-swatch[data-swatch="4"] { background: var(--crisp-bg-tag-swatch4); }
337
+ & .crisp-datatable-swatch[data-swatch="5"] { background: var(--crisp-bg-tag-swatch5); }
338
+ & .crisp-datatable-swatch[data-swatch="6"] { background: var(--crisp-bg-tag-swatch6); }
339
+ & .crisp-datatable-swatch[data-swatch="7"] { background: var(--crisp-bg-tag-swatch7); }
340
+ & .crisp-datatable-swatch[data-swatch="8"] { background: var(--crisp-bg-tag-swatch8); }
341
+ & .crisp-datatable-swatch[data-swatch="9"] { background: var(--crisp-bg-tag-swatch9); }
342
+ & .crisp-datatable-swatch[data-swatch="10"] { background: var(--crisp-bg-tag-swatch10); }
343
+ & .crisp-datatable-swatch[data-swatch="11"] { background: var(--crisp-bg-tag-swatch11); }
344
+ & .crisp-datatable-swatch[data-swatch="12"] { background: var(--crisp-bg-tag-swatch12); }
306
345
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
307
346
  & .crisp-datatable-muted { color: var(--crisp-fg-muted); }
308
347
  /* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
@@ -313,7 +352,7 @@
313
352
  own .crisp-recordstable-link, which this mirrors: no underline at
314
353
  rest, underline on hover, own-colour text rather than a browser-blue
315
354
  link. */
316
- & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
355
+ & .crisp-datatable-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: clip; text-overflow: ellipsis; }
317
356
  & .crisp-datatable-link:hover { text-decoration: underline; }
318
357
  /* phone cell type/editor (#765) -- measured live: the dial-code prefix
319
358
  is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
@@ -1,9 +1,9 @@
1
1
  .crisp-datepickerfield {
2
2
  display: inline-flex; font-family: var(--crisp-font-sans);
3
- & .crisp-datepickerfield-box { display: inline-flex; align-items: center; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
3
+ & .crisp-datepickerfield-box { display: inline-flex; align-items: center; width: 100%; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
4
4
  & .crisp-datepickerfield-box[data-ghost] { background: transparent; box-shadow: none; }
5
5
  & .crisp-datepickerfield-box[data-ghost]:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
6
- & .crisp-datepickerfield-trigger { display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
6
+ & .crisp-datepickerfield-trigger { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
7
7
  & .crisp-datepickerfield-box[data-placeholder] .crisp-datepickerfield-trigger { color: var(--crisp-fg-muted); }
8
8
  & .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
9
9
  /* Reuses TableToolbar's measured filter-chip remove button
@@ -18,3 +18,9 @@
18
18
  & .crisp-datepickerfield-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
19
19
  & .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
20
20
  }
21
+ .crisp-datepickerfield--width_full {
22
+ width: 100%;
23
+ }
24
+ .crisp-datepickerfield--width_auto {
25
+ width: auto;
26
+ }
@@ -1,7 +1,7 @@
1
1
  import type { RecipeFn } from "../core/types";
2
2
 
3
3
  export interface DatepickerfieldVariants {
4
-
4
+ width?: "full" | "auto";
5
5
  }
6
6
 
7
- export declare const datepickerfieldRecipe: RecipeFn<{ }>;
7
+ export declare const datepickerfieldRecipe: RecipeFn<{ width: { full: string; auto: string } }>;
@@ -1,10 +1,10 @@
1
1
  @layer crisp-components {
2
2
  .crisp-datepickerfield {
3
3
  display: inline-flex; font-family: var(--crisp-font-sans);
4
- & .crisp-datepickerfield-box { display: inline-flex; align-items: center; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
4
+ & .crisp-datepickerfield-box { display: inline-flex; align-items: center; width: 100%; box-sizing: border-box; height: 32px; margin: 0; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); }
5
5
  & .crisp-datepickerfield-box[data-ghost] { background: transparent; box-shadow: none; }
6
6
  & .crisp-datepickerfield-box[data-ghost]:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
7
- & .crisp-datepickerfield-trigger { display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
7
+ & .crisp-datepickerfield-trigger { flex: 1; min-width: 0; display: inline-flex; align-items: center; gap: var(--crisp-space-2); height: 100%; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; background: none; color: inherit; font-family: inherit; font-size: inherit; white-space: nowrap; cursor: pointer; }
8
8
  & .crisp-datepickerfield-box[data-placeholder] .crisp-datepickerfield-trigger { color: var(--crisp-fg-muted); }
9
9
  & .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
10
10
  /* Reuses TableToolbar's measured filter-chip remove button
@@ -19,4 +19,10 @@
19
19
  & .crisp-datepickerfield-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
20
20
  & .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
21
21
  }
22
+ .crisp-datepickerfield--width_full {
23
+ width: 100%;
24
+ }
25
+ .crisp-datepickerfield--width_auto {
26
+ width: auto;
27
+ }
22
28
  }
@@ -19,7 +19,7 @@ export function Breadcrumb({ items, separator, "aria-label": ariaLabelProp, clas
19
19
  return (_jsx("nav", { "aria-label": ariaLabel, className: breadcrumbRecipe({ className }), ...rest, children: items.map((item, i) => {
20
20
  const last = i === items.length - 1;
21
21
  const content = (_jsxs(_Fragment, { children: [item.icon, item.label] }));
22
- return (_jsxs(React.Fragment, { children: [last ? (_jsx("span", { className: "crisp-breadcrumb-item", "aria-current": "page", children: content })) : item.href ? (_jsx("a", { className: "crisp-breadcrumb-item", href: item.href, children: content })) : (_jsx("button", { type: "button", className: "crisp-breadcrumb-item", onClick: item.onClick, children: content })), !last && _jsx("span", { className: "crisp-breadcrumb-sep", children: sep })] }, i));
22
+ return (_jsxs(React.Fragment, { children: [last ? (_jsx("span", { className: "crisp-breadcrumb-item", "aria-current": "page", children: content })) : item.href ? (_jsx("a", { className: "crisp-breadcrumb-item", href: item.href, onClick: item.onClick, children: content })) : (_jsx("button", { type: "button", className: "crisp-breadcrumb-item", onClick: item.onClick, children: content })), !last && _jsx("span", { className: "crisp-breadcrumb-sep", children: sep })] }, i));
23
23
  }) }));
24
24
  }
25
25
  Breadcrumb.displayName = "Breadcrumb";
@@ -121,6 +121,39 @@ const spec = defineSpec({
121
121
  fontSize: c.text.md,
122
122
  borderRadius: c.radius.md,
123
123
  },
124
+ // crisp#688: Attio's own 20px small button, split out of #682 rather
125
+ // than redefining `sm` -- 72 existing `size="sm"` call sites (sidebar,
126
+ // comments, recordpage, workspacegeneralsettings, personchip,
127
+ // datatable) already rely on sm's 24px, unverified against `xs`'s own
128
+ // context. Box measured live on app.attio.com Home/Tasks ("View all",
129
+ // "Today, <date>", the date-stepper's Previous/Next-day icon
130
+ // buttons): 20px height, 6px radius, 6px inline padding on text
131
+ // buttons (a 20x20 icon-only button centers a 16px icon the same way
132
+ // shape="icon" already does for every other size, so it needs no
133
+ // extra rule), 4px gap between multiple children.
134
+ //
135
+ // Follow-up correction (still #688): the label is 12px/500(medium)/
136
+ // 16px line-height/normal tracking -- NOT #682's 14px button tracking,
137
+ // and NOT the 10px/regular/15px this file shipped with first. That
138
+ // first pass read getComputedStyle on the `<button>` element itself;
139
+ // Attio's actual label lives in an inner `<div>` that overrides
140
+ // font-size/weight/line-height on top of it (confirmed by walking the
141
+ // full child tree, on "View all" AND "Today, <date>", both Home and
142
+ // the savedviews toolbar's own "Save for everyone") -- the outer
143
+ // button's own 10px/400/15px is real but never what's on screen.
144
+ // 12px is already `c.text.sm` and 500 is already the base's own
145
+ // default `fontWeight` (no override needed for either); only
146
+ // line-height and tracking still diverge from the base's 20px/
147
+ // -0.07px and need their own values here.
148
+ xs: {
149
+ height: "20px",
150
+ paddingInline: c.space["1.5"],
151
+ fontSize: c.text.sm,
152
+ lineHeight: "16px",
153
+ letterSpacing: "normal",
154
+ borderRadius: c.radius.sm,
155
+ gap: c.space["1"],
156
+ },
124
157
  md: {
125
158
  decls: {
126
159
  height: "28px",
@@ -73,7 +73,9 @@ const spec = defineSpec({
73
73
  selector: "& .crisp-chip-label",
74
74
  decls: {
75
75
  minWidth: 0,
76
- overflow: "hidden",
76
+ // #719: `clip`, not `hidden` -- immune to a programmatic
77
+ // `scrollLeft` assignment; renders the ellipsis identically.
78
+ overflow: "clip",
77
79
  textOverflow: "ellipsis",
78
80
  whiteSpace: "nowrap",
79
81
  display: "block",
@@ -390,14 +390,17 @@ function renderTyped(col, value, avatarTone, row, display, locale = "en-US", ope
390
390
  const tags = Array.isArray(value) ? value : [];
391
391
  if (!tags.length)
392
392
  return empty;
393
- return (_jsx("span", { className: "crisp-datatable-tags", children: tags.map((t) => (_jsx("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[t] ?? toneFor(t), children: t }, t))) }));
393
+ return (_jsx("span", { className: "crisp-datatable-tags", children: tags.map((t) => col.swatches?.[t] ? (_jsx("span", { className: "crisp-datatable-swatch", "data-swatch": col.swatches[t], children: t }, t)) : (_jsx("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[t] ?? toneFor(t), children: t }, t))) }));
394
394
  }
395
395
  case "status": {
396
396
  const s = asText(value);
397
397
  if (!s)
398
398
  return empty;
399
- // tone is looked up by the RAW status, so formatting the label (casing,
400
- // translation) can never silently repaint the chip
399
+ // tone/swatch is looked up by the RAW status, so formatting the label
400
+ // (casing, translation) can never silently repaint the chip
401
+ if (col.swatches?.[s]) {
402
+ return (_jsx("span", { className: "crisp-datatable-swatch", "data-swatch": col.swatches[s], children: display || s }));
403
+ }
401
404
  return (_jsx("span", { className: "crisp-datatable-tag", "data-tone": col.tones?.[s] ?? toneFor(s), children: display || s }));
402
405
  }
403
406
  case "rating": {
@@ -113,7 +113,13 @@ const config = defineRecipe({
113
113
  & .crisp-datatable-group-count { margin-inline-start: ${c.space["1.5"]}; color: ${c.fgMuted}; font-variant-numeric: tabular-nums; }
114
114
  & .crisp-datatable-th-rename { width: 100%; min-width: 0; height: ${c.size.row}; margin: 0; padding: 0 ${c.space["1"]}; border: none; border-radius: ${c.radius.md}; background: ${c.bgSurface}; box-shadow: inset 0 0 0 1px ${c.bgBrandSolid}; font-family: inherit; font-size: ${c.text.lg}; font-weight: ${c.weight.medium}; color: ${c.fgPrimary}; outline: none; }
115
115
  & .crisp-datatable-th-rename:focus { box-shadow: inset 0 0 0 1px ${c.bgBrandSolid}; }
116
- & .crisp-datatable-th-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
116
+ /* #719: overflow: clip, not hidden, on every truncation rule below --
117
+ hidden still honours a programmatic scrollLeft assignment (found via
118
+ a screenshot tool that pans anything with scrollWidth > clientWidth),
119
+ blanking or fragmenting the visible text even though real user
120
+ scrolling was already blocked. clip renders the ellipsis identically
121
+ and leaves no scroll position to move. */
122
+ & .crisp-datatable-th-label { overflow: clip; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
117
123
  /* #465: 12px per the comment above (and Attio's measured header cell
118
124
  padding: 0 12px) -- was still c.space["2"] (8px), drifted from its
119
125
  own documented value. */
@@ -200,7 +206,7 @@ const config = defineRecipe({
200
206
  /* reference picker: a leading 16px avatar per option, plus a trailing
201
207
  "Create X" row when the consumer supplies one (#449) -- same measured
202
208
  values as RecordsTable's own .crisp-recordstable-refoption*. */
203
- & .crisp-datatable-refoption { display: flex; align-items: center; gap: ${c.space["2"]}; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
209
+ & .crisp-datatable-refoption { display: flex; align-items: center; gap: ${c.space["2"]}; min-width: 0; overflow: clip; text-overflow: ellipsis; }
204
210
  & .crisp-datatable-refoption-avatar { flex-shrink: 0; }
205
211
  & .crisp-datatable-refoption--create { color: ${c.fgMuted}; }
206
212
  & .crisp-datatable-empty { padding: ${c.space["8"]} ${c.space["3"]}; text-align: center; color: ${c.fgMuted}; font-size: ${c.text.lg}; }
@@ -286,7 +292,7 @@ const config = defineRecipe({
286
292
  (#833/#835/#848) that happened to apply the same 500 to every
287
293
  primary-column body cell regardless of type. Made explicit here so
288
294
  fixing that leak doesn't also (wrongly) drop entity names to 400. */
289
- & .crisp-datatable-entity-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: ${c.weight.medium}; text-decoration: underline; text-decoration-color: color-mix(in srgb, ${c.fgPrimary} 9%, transparent); }
295
+ & .crisp-datatable-entity-name { overflow: clip; text-overflow: ellipsis; white-space: nowrap; font-weight: ${c.weight.medium}; text-decoration: underline; text-decoration-color: color-mix(in srgb, ${c.fgPrimary} 9%, transparent); }
290
296
  /* #893: shared by the button (onEntityClick, a different record) and
291
297
  the anchor (href, the row's own record) -- was button-only, which
292
298
  silently left a real <a> unstyled the day #893 added one. */
@@ -309,9 +315,24 @@ const config = defineRecipe({
309
315
  Avatar's own already-shipped shape="rounded" value, not a new number.
310
316
  shape="circle" reuses Avatar's own shape="circle" value (radius.full)
311
317
  the same way, measured live on a real Attio person avatar. */
312
- & .crisp-datatable-avatar { width: ${c.size.icon}; height: ${c.size.icon}; border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: ${c.weight.semibold}; text-transform: uppercase; color: ${c.fgOnBrand}; background: ${c.bgBrandSolid}; }
318
+ & .crisp-datatable-avatar { width: ${c.size.icon}; height: ${c.size.icon}; border-radius: 30%; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; line-height: 1; font-weight: ${c.weight.semibold}; text-transform: uppercase; color: ${c.fgOnTone}; background: ${c.bgBrandSolid}; }
313
319
  & .crisp-datatable-avatar[data-shape="circle"] { border-radius: ${c.radius.full}; }
314
- & .crisp-datatable-avatar[data-tone="success"] { background: ${c.bgSuccess}; } & .crisp-datatable-avatar[data-tone="warning"] { background: ${c.bgWarning}; } & .crisp-datatable-avatar[data-tone="danger"] { background: ${c.bgDanger}; } & .crisp-datatable-avatar[data-tone="purple"] { background: ${c.bgPurple}; } & .crisp-datatable-avatar[data-tone="cyan"] { background: ${c.bgCyan}; } & .crisp-datatable-avatar[data-tone="orange"] { background: ${c.bgOrange}; }
320
+ /* your-moon/crisp#891: every data-tone override painted ONLY a
321
+ background, inheriting the base rule's white fgOnBrand -- white
322
+ clears AA against none of these seven fills (brand 3.23:1, success
323
+ 3.96, warning 4.12, danger 3.76, purple 3.58, cyan 2.30, orange
324
+ 2.77). fgOnTone (ink, #101112 -- semantic.ts's own comment: "dark ink
325
+ clears AA on every tone in both themes") clears 4.5:1+ on every fill
326
+ here with a comfortable margin (brand 5.85, success 4.77/6.29,
327
+ danger 5.03/6.19, purple 5.27, cyan 8.23, orange 6.83, light/dark),
328
+ so the base rule's colour moves there and every override keeps it --
329
+ EXCEPT warning, whose raw fill (bgWarning) only clears 4.59:1 in
330
+ light, too thin a margin to rely on: it takes bgWarningSolid instead,
331
+ the same solid-warning-plus-ink pair Badge's own solid variant
332
+ already established (13.98/7.83), for the same reason (see
333
+ tokens/palette.ts's amberSolid comment). No background changes
334
+ otherwise -- the fills themselves are unaffected, only the text. */
335
+ & .crisp-datatable-avatar[data-tone="success"] { background: ${c.bgSuccess}; color: ${c.fgOnTone}; } & .crisp-datatable-avatar[data-tone="warning"] { background: ${c.bgWarningSolid}; color: ${c.fgOnTone}; } & .crisp-datatable-avatar[data-tone="danger"] { background: ${c.bgDanger}; color: ${c.fgOnTone}; } & .crisp-datatable-avatar[data-tone="purple"] { background: ${c.bgPurple}; color: ${c.fgOnTone}; } & .crisp-datatable-avatar[data-tone="cyan"] { background: ${c.bgCyan}; color: ${c.fgOnTone}; } & .crisp-datatable-avatar[data-tone="orange"] { background: ${c.bgOrange}; color: ${c.fgOnTone}; }
315
336
  & .crisp-datatable-avatar img { width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
316
337
  & .crisp-datatable-tags { display: flex; align-items: center; gap: ${c.space["1"]}; overflow: hidden; }
317
338
  & .crisp-datatable-tag { display: inline-flex; align-items: center; height: ${c.size.chip}; padding: 0 ${c.space["1"]}; border-radius: ${c.radius.chip}; font-size: ${c.text.lg}; line-height: 20px; font-weight: ${c.weight.medium}; white-space: nowrap; background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); color: color-mix(in srgb, ${c.fgPrimary} 82%, transparent); }
@@ -322,6 +343,24 @@ const config = defineRecipe({
322
343
  & .crisp-datatable-tag[data-tone="purple"] { background: color-mix(in srgb, ${c.bgPurple} 16%, transparent); color: color-mix(in srgb, ${c.bgPurple} 80%, ${c.fgPrimary}); }
323
344
  & .crisp-datatable-tag[data-tone="cyan"] { background: color-mix(in srgb, ${c.bgCyan} 18%, transparent); color: color-mix(in srgb, ${c.bgCyan} 82%, ${c.fgPrimary}); }
324
345
  & .crisp-datatable-tag[data-tone="orange"] { background: color-mix(in srgb, ${c.bgOrange} 16%, transparent); color: color-mix(in srgb, ${c.bgOrange} 82%, ${c.fgPrimary}); }
346
+ /* your-moon/crisp#998: Attio's own 12-colour tag palette (measured
347
+ live, see tokens/palette.ts's tagSwatch1 comment) -- flat black
348
+ text, no ring, unlike the tone family above. 7px radius/10px text
349
+ are measured literals (no matching step in the shared scale, same
350
+ as Select's own .crisp-select-swatch). */
351
+ & .crisp-datatable-swatch { display: inline-flex; align-items: center; height: ${c.size.chip}; padding: 0 ${c.space["1"]}; border-radius: 7px; font-size: 10px; font-weight: ${c.weight.regular}; white-space: nowrap; color: ${c.fgTagSwatch}; }
352
+ & .crisp-datatable-swatch[data-swatch="1"] { background: ${c.bgTagSwatch1}; }
353
+ & .crisp-datatable-swatch[data-swatch="2"] { background: ${c.bgTagSwatch2}; }
354
+ & .crisp-datatable-swatch[data-swatch="3"] { background: ${c.bgTagSwatch3}; }
355
+ & .crisp-datatable-swatch[data-swatch="4"] { background: ${c.bgTagSwatch4}; }
356
+ & .crisp-datatable-swatch[data-swatch="5"] { background: ${c.bgTagSwatch5}; }
357
+ & .crisp-datatable-swatch[data-swatch="6"] { background: ${c.bgTagSwatch6}; }
358
+ & .crisp-datatable-swatch[data-swatch="7"] { background: ${c.bgTagSwatch7}; }
359
+ & .crisp-datatable-swatch[data-swatch="8"] { background: ${c.bgTagSwatch8}; }
360
+ & .crisp-datatable-swatch[data-swatch="9"] { background: ${c.bgTagSwatch9}; }
361
+ & .crisp-datatable-swatch[data-swatch="10"] { background: ${c.bgTagSwatch10}; }
362
+ & .crisp-datatable-swatch[data-swatch="11"] { background: ${c.bgTagSwatch11}; }
363
+ & .crisp-datatable-swatch[data-swatch="12"] { background: ${c.bgTagSwatch12}; }
325
364
  & .crisp-datatable-num { font-variant-numeric: tabular-nums; }
326
365
  & .crisp-datatable-muted { color: ${c.fgMuted}; }
327
366
  /* crisp#822 -- a date/datetime cell's danger/overdue tone: same token as
@@ -332,7 +371,7 @@ const config = defineRecipe({
332
371
  own .crisp-recordstable-link, which this mirrors: no underline at
333
372
  rest, underline on hover, own-colour text rather than a browser-blue
334
373
  link. */
335
- & .crisp-datatable-link { color: ${c.fgPrimary}; text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
374
+ & .crisp-datatable-link { color: ${c.fgPrimary}; text-decoration: none; overflow: clip; text-overflow: ellipsis; }
336
375
  & .crisp-datatable-link:hover { text-decoration: underline; }
337
376
  /* phone cell type/editor (#765) -- measured live: the dial-code prefix
338
377
  is a muted rgba(0,0,0,0.63) at 14px, matching every other muted-text
@@ -22,7 +22,7 @@ const fromDate = (d) => ({
22
22
  * popover. This is what `DatePicker` used to be; `DatePicker` is now
23
23
  * seed-design's bare calendar, and this composes it.
24
24
  */
25
- export function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder: placeholderProp, variant = "default", format = defaultFormat, clearable = true, clearLabel: clearLabelProp, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }) {
25
+ export function DatePickerField({ value, defaultValue, onValueChange, onChange, placeholder: placeholderProp, variant = "default", width = "full", format = defaultFormat, clearable = true, clearLabel: clearLabelProp, presets, calendarProps, "aria-label": ariaLabel, className, ...rest }) {
26
26
  // crisp/#471: same resolution order as Select's own.
27
27
  const placeholder = useCrispMessage(placeholderProp, "Set date…");
28
28
  const clearLabel = useCrispMessage(clearLabelProp, "Clear date");
@@ -43,7 +43,7 @@ export function DatePickerField({ value, defaultValue, onValueChange, onChange,
43
43
  onValueChange?.(null);
44
44
  onChange?.(null);
45
45
  };
46
- return (_jsx("div", { className: datepickerfieldRecipe({ className }), ...rest, children: _jsxs("div", { className: "crisp-datepickerfield-box", "data-ghost": variant === "ghost" ? "" : undefined, "data-placeholder": selected ? undefined : "", children: [_jsx(Popover, { open: open, onOpenChange: setOpen, "aria-label": ariaLabel, trigger: _jsxs("button", { type: "button", className: "crisp-datepickerfield-trigger", "aria-label": ariaLabel, children: [_jsx(CalendarDays, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), selected ? format(selected) : placeholder] }), children: _jsxs("div", { className: "crisp-datepickerfield-panel", children: [_jsx(DatePicker
46
+ return (_jsx("div", { className: datepickerfieldRecipe({ width, className }), ...rest, children: _jsxs("div", { className: "crisp-datepickerfield-box", "data-ghost": variant === "ghost" ? "" : undefined, "data-placeholder": selected ? undefined : "", children: [_jsx(Popover, { open: open, onOpenChange: setOpen, "aria-label": ariaLabel, trigger: _jsxs("button", { type: "button", className: "crisp-datepickerfield-trigger", "aria-label": ariaLabel, children: [_jsx(CalendarDays, { size: 15, strokeWidth: 1.75, "aria-hidden": "true" }), selected ? format(selected) : placeholder] }), children: _jsxs("div", { className: "crisp-datepickerfield-panel", children: [_jsx(DatePicker
47
47
  // DatePickerProps is a union over selectionMode, and TypeScript
48
48
  // cannot narrow it through a spread: it tries every branch and
49
49
  // reports the range one as missing props. The field is always
@@ -10,7 +10,7 @@ const config = defineRecipe({
10
10
  display: inline-flex; font-family: ${c.font.sans};
11
11
 
12
12
  & .crisp-datepickerfield-box {
13
- display: inline-flex; align-items: center;
13
+ display: inline-flex; align-items: center; width: 100%;
14
14
  box-sizing: border-box; height: 32px; margin: 0;
15
15
  border-radius: ${c.radius.md}; background: transparent;
16
16
  box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 7%, transparent);
@@ -19,6 +19,7 @@ const config = defineRecipe({
19
19
  & .crisp-datepickerfield-box[data-ghost] { background: transparent; box-shadow: none; }
20
20
  & .crisp-datepickerfield-box[data-ghost]:hover { background: color-mix(in srgb, ${c.fgPrimary} 4%, transparent); }
21
21
  & .crisp-datepickerfield-trigger {
22
+ flex: 1; min-width: 0;
22
23
  display: inline-flex; align-items: center; gap: ${c.space["2"]};
23
24
  height: 100%; padding: 0 ${c.space["2.5"]}; margin: 0;
24
25
  border: none; background: none; color: inherit; font-family: inherit;
@@ -48,8 +49,20 @@ const config = defineRecipe({
48
49
  }
49
50
  & .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, ${c.fgPrimary} 8%, transparent); }
50
51
  `,
51
- variants: {},
52
- defaultVariants: {},
52
+ variants: {
53
+ // crisp#980: full (default) fills its container, matching Select's own
54
+ // width variant/default -- so a form composing DatePickerField alongside
55
+ // Input/Select via FormField gets one consistent column width across
56
+ // every field type, not just some of them. auto sizes to content, the
57
+ // behaviour every consumer got unconditionally before this.
58
+ width: {
59
+ full: `width: 100%;`,
60
+ auto: `width: auto;`,
61
+ },
62
+ },
63
+ defaultVariants: {
64
+ width: "full",
65
+ },
53
66
  compoundVariants: [],
54
67
  });
55
68
  export const datepickerfieldRecipe = Object.assign(resolveRecipe(config), {