@crisp-ui-kit/crisp 0.57.1 → 0.57.2

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 (252) 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 +7 -6
  11. package/dist/button.layered.css +7 -6
  12. package/dist/checkbox.css +7 -3
  13. package/dist/checkbox.layered.css +7 -3
  14. package/dist/chip.css +15 -0
  15. package/dist/chip.d.ts +3 -1
  16. package/dist/chip.layered.css +15 -0
  17. package/dist/chipgroup.css +5 -0
  18. package/dist/chipgroup.d.ts +7 -0
  19. package/dist/chipgroup.layered.css +7 -0
  20. package/dist/cjs/components/badge/badge.recipe.js +22 -8
  21. package/dist/cjs/components/bottomsheet/bottomsheet.js +90 -0
  22. package/dist/cjs/components/bottomsheet/bottomsheet.recipe.js +77 -0
  23. package/dist/cjs/components/bottomsheet/index.js +9 -0
  24. package/dist/cjs/components/button/button.recipe.js +39 -15
  25. package/dist/cjs/components/checkbox/checkbox.recipe.js +61 -9
  26. package/dist/cjs/components/chip/chip.js +14 -2
  27. package/dist/cjs/components/chip/chip.recipe.js +69 -1
  28. package/dist/cjs/components/chipgroup/chipgroup.js +51 -0
  29. package/dist/cjs/components/chipgroup/chipgroup.recipe.js +36 -0
  30. package/dist/cjs/components/chipgroup/index.js +7 -0
  31. package/dist/cjs/components/datatable/datatable.js +5 -1
  32. package/dist/cjs/components/datatable/datatable.recipe.js +11 -2
  33. package/dist/cjs/components/dialog/dialog.recipe.js +21 -10
  34. package/dist/cjs/components/emptystate/emptystate.recipe.js +7 -2
  35. package/dist/cjs/components/fileupload/fileupload.js +21 -4
  36. package/dist/cjs/components/input/index.js +2 -1
  37. package/dist/cjs/components/input/input.js +31 -1
  38. package/dist/cjs/components/input/input.recipe.js +16 -9
  39. package/dist/cjs/components/menu/menu.recipe.js +21 -7
  40. package/dist/cjs/components/menusheet/index.js +9 -0
  41. package/dist/cjs/components/menusheet/menusheet.js +133 -0
  42. package/dist/cjs/components/menusheet/menusheet.recipe.js +103 -0
  43. package/dist/cjs/components/multiselect/multiselect.js +1 -1
  44. package/dist/cjs/components/multiselect/multiselect.recipe.js +33 -9
  45. package/dist/cjs/components/select/select.js +1 -1
  46. package/dist/cjs/components/select/select.recipe.js +38 -12
  47. package/dist/cjs/components/snackbar/index.js +8 -0
  48. package/dist/cjs/components/snackbar/snackbar.js +121 -0
  49. package/dist/cjs/components/snackbar/snackbar.recipe.js +71 -0
  50. package/dist/cjs/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  51. package/dist/cjs/components/tabletoolbar/tabletoolbar.js +37 -12
  52. package/dist/cjs/components/tabs/tabs.js +10 -4
  53. package/dist/cjs/components/tabs/tabs.recipe.js +23 -6
  54. package/dist/cjs/components/textarea/textarea.recipe.js +11 -8
  55. package/dist/cjs/index.js +7 -0
  56. package/dist/cjs/product/authshell/authshell.recipe.js +5 -1
  57. package/dist/cjs/product/command/command.recipe.js +4 -1
  58. package/dist/cjs/product/comments/comments.js +7 -2
  59. package/dist/cjs/product/comments/comments.recipe.js +25 -7
  60. package/dist/cjs/product/memberssettings/index.js +6 -0
  61. package/dist/cjs/product/memberssettings/memberssettings.js +99 -0
  62. package/dist/cjs/product/memberssettings/memberssettings.recipe.js +83 -0
  63. package/dist/cjs/product/notificationssettings/index.js +5 -0
  64. package/dist/cjs/product/notificationssettings/notificationssettings.js +19 -0
  65. package/dist/cjs/product/notificationssettings/notificationssettings.recipe.js +44 -0
  66. package/dist/cjs/product/recordpage/recordpage.js +57 -6
  67. package/dist/cjs/product/recordpage/recordpage.recipe.js +43 -6
  68. package/dist/cjs/product/workspacegeneralsettings/index.js +5 -0
  69. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.js +21 -0
  70. package/dist/cjs/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +51 -0
  71. package/dist/cjs/tokens/contract.js +1 -0
  72. package/dist/cjs/tokens/elevation.js +8 -5
  73. package/dist/cjs/tokens/palette.js +28 -8
  74. package/dist/cjs/tokens/scale.js +44 -2
  75. package/dist/cjs/tokens/semantic.js +2 -0
  76. package/dist/columncalc.css +15 -7
  77. package/dist/columncalc.layered.css +15 -7
  78. package/dist/command.css +23 -19
  79. package/dist/command.layered.css +23 -19
  80. package/dist/comments.css +28 -19
  81. package/dist/comments.d.ts +2 -2
  82. package/dist/comments.layered.css +28 -19
  83. package/dist/datatable.css +161 -67
  84. package/dist/datatable.layered.css +161 -67
  85. package/dist/datepicker.css +13 -41
  86. package/dist/datepicker.layered.css +13 -41
  87. package/dist/datepickerfield.css +4 -1
  88. package/dist/datepickerfield.layered.css +4 -1
  89. package/dist/dialog.css +12 -7
  90. package/dist/dialog.layered.css +12 -7
  91. package/dist/emptystate.css +5 -3
  92. package/dist/emptystate.layered.css +5 -3
  93. package/dist/esm/components/badge/badge.recipe.js +22 -8
  94. package/dist/esm/components/bottomsheet/bottomsheet.js +52 -0
  95. package/dist/esm/components/bottomsheet/bottomsheet.recipe.js +74 -0
  96. package/dist/esm/components/bottomsheet/index.js +2 -0
  97. package/dist/esm/components/button/button.recipe.js +40 -16
  98. package/dist/esm/components/checkbox/checkbox.recipe.js +61 -9
  99. package/dist/esm/components/chip/chip.js +14 -2
  100. package/dist/esm/components/chip/chip.recipe.js +69 -1
  101. package/dist/esm/components/chipgroup/chipgroup.js +15 -0
  102. package/dist/esm/components/chipgroup/chipgroup.recipe.js +33 -0
  103. package/dist/esm/components/chipgroup/index.js +2 -0
  104. package/dist/esm/components/datatable/datatable.js +5 -1
  105. package/dist/esm/components/datatable/datatable.recipe.js +11 -2
  106. package/dist/esm/components/dialog/dialog.recipe.js +22 -11
  107. package/dist/esm/components/emptystate/emptystate.recipe.js +7 -2
  108. package/dist/esm/components/fileupload/fileupload.js +20 -5
  109. package/dist/esm/components/input/index.js +1 -1
  110. package/dist/esm/components/input/input.js +30 -0
  111. package/dist/esm/components/input/input.recipe.js +17 -10
  112. package/dist/esm/components/menu/menu.recipe.js +21 -7
  113. package/dist/esm/components/menusheet/index.js +2 -0
  114. package/dist/esm/components/menusheet/menusheet.js +95 -0
  115. package/dist/esm/components/menusheet/menusheet.recipe.js +100 -0
  116. package/dist/esm/components/multiselect/multiselect.js +1 -1
  117. package/dist/esm/components/multiselect/multiselect.recipe.js +33 -9
  118. package/dist/esm/components/select/select.js +1 -1
  119. package/dist/esm/components/select/select.recipe.js +38 -12
  120. package/dist/esm/components/snackbar/index.js +2 -0
  121. package/dist/esm/components/snackbar/snackbar.js +84 -0
  122. package/dist/esm/components/snackbar/snackbar.recipe.js +68 -0
  123. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +7 -2
  124. package/dist/esm/components/tabletoolbar/tabletoolbar.js +37 -12
  125. package/dist/esm/components/tabs/tabs.js +10 -4
  126. package/dist/esm/components/tabs/tabs.recipe.js +23 -6
  127. package/dist/esm/components/textarea/textarea.recipe.js +12 -9
  128. package/dist/esm/index.js +7 -0
  129. package/dist/esm/product/authshell/authshell.recipe.js +5 -1
  130. package/dist/esm/product/command/command.recipe.js +4 -1
  131. package/dist/esm/product/comments/comments.js +7 -2
  132. package/dist/esm/product/comments/comments.recipe.js +25 -7
  133. package/dist/esm/product/memberssettings/index.js +1 -0
  134. package/dist/esm/product/memberssettings/memberssettings.js +62 -0
  135. package/dist/esm/product/memberssettings/memberssettings.recipe.js +80 -0
  136. package/dist/esm/product/notificationssettings/index.js +1 -0
  137. package/dist/esm/product/notificationssettings/notificationssettings.js +16 -0
  138. package/dist/esm/product/notificationssettings/notificationssettings.recipe.js +41 -0
  139. package/dist/esm/product/recordpage/recordpage.js +58 -7
  140. package/dist/esm/product/recordpage/recordpage.recipe.js +43 -6
  141. package/dist/esm/product/workspacegeneralsettings/index.js +1 -0
  142. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.js +18 -0
  143. package/dist/esm/product/workspacegeneralsettings/workspacegeneralsettings.recipe.js +48 -0
  144. package/dist/esm/tokens/contract.js +2 -1
  145. package/dist/esm/tokens/elevation.js +8 -5
  146. package/dist/esm/tokens/palette.js +28 -8
  147. package/dist/esm/tokens/scale.js +43 -1
  148. package/dist/esm/tokens/semantic.js +2 -0
  149. package/dist/fileupload.css +3 -1
  150. package/dist/fileupload.layered.css +3 -1
  151. package/dist/input.css +6 -4
  152. package/dist/input.layered.css +6 -4
  153. package/dist/listpage.css +3 -1
  154. package/dist/listpage.layered.css +3 -1
  155. package/dist/memberssettings.css +67 -0
  156. package/dist/memberssettings.d.ts +7 -0
  157. package/dist/memberssettings.layered.css +69 -0
  158. package/dist/menu.css +2 -2
  159. package/dist/menu.layered.css +2 -2
  160. package/dist/menusheet.css +36 -0
  161. package/dist/menusheet.d.ts +7 -0
  162. package/dist/menusheet.layered.css +38 -0
  163. package/dist/multiselect.css +13 -6
  164. package/dist/multiselect.layered.css +13 -6
  165. package/dist/native/tokens.d.ts +2 -1
  166. package/dist/native/tokens.js +20 -3
  167. package/dist/notificationssettings.css +22 -0
  168. package/dist/notificationssettings.d.ts +7 -0
  169. package/dist/notificationssettings.layered.css +24 -0
  170. package/dist/objectsettings.css +4 -4
  171. package/dist/objectsettings.layered.css +4 -4
  172. package/dist/recordpage.css +67 -23
  173. package/dist/recordpage.layered.css +67 -23
  174. package/dist/recordpanel.css +35 -16
  175. package/dist/recordpanel.layered.css +35 -16
  176. package/dist/resizablepanel.css +8 -5
  177. package/dist/resizablepanel.layered.css +8 -5
  178. package/dist/richtext.css +24 -8
  179. package/dist/richtext.layered.css +24 -8
  180. package/dist/savedviews.css +9 -2
  181. package/dist/savedviews.layered.css +9 -2
  182. package/dist/select.css +25 -5
  183. package/dist/select.layered.css +25 -5
  184. package/dist/settingsshell.css +2 -3
  185. package/dist/settingsshell.layered.css +2 -3
  186. package/dist/slider.css +6 -27
  187. package/dist/slider.layered.css +6 -27
  188. package/dist/snackbar.css +24 -0
  189. package/dist/snackbar.d.ts +7 -0
  190. package/dist/snackbar.layered.css +26 -0
  191. package/dist/statcard.css +3 -1
  192. package/dist/statcard.layered.css +3 -1
  193. package/dist/styles.css +859 -345
  194. package/dist/styles.layered.css +859 -345
  195. package/dist/table.css +28 -10
  196. package/dist/table.layered.css +28 -10
  197. package/dist/tabletoolbar.css +35 -24
  198. package/dist/tabletoolbar.layered.css +35 -24
  199. package/dist/tabs.css +18 -4
  200. package/dist/tabs.layered.css +18 -4
  201. package/dist/textarea.css +2 -6
  202. package/dist/textarea.layered.css +2 -6
  203. package/dist/themepicker.css +2 -1
  204. package/dist/themepicker.layered.css +2 -1
  205. package/dist/tokens.css +13 -2
  206. package/dist/tokens.json +20 -3
  207. package/dist/types/components/bottomsheet/bottomsheet.d.ts +35 -0
  208. package/dist/types/components/bottomsheet/bottomsheet.recipe.d.ts +3 -0
  209. package/dist/types/components/bottomsheet/index.d.ts +2 -0
  210. package/dist/types/components/button/button.recipe.d.ts +11 -6
  211. package/dist/types/components/checkbox/checkbox.recipe.d.ts +28 -5
  212. package/dist/types/components/chip/chip.d.ts +22 -0
  213. package/dist/types/components/chip/chip.recipe.d.ts +48 -0
  214. package/dist/types/components/chipgroup/chipgroup.d.ts +14 -0
  215. package/dist/types/components/chipgroup/chipgroup.recipe.d.ts +5 -0
  216. package/dist/types/components/chipgroup/index.d.ts +2 -0
  217. package/dist/types/components/datatable/datatable.d.ts +19 -0
  218. package/dist/types/components/fileupload/fileupload.d.ts +26 -0
  219. package/dist/types/components/input/index.d.ts +1 -1
  220. package/dist/types/components/input/input.d.ts +72 -0
  221. package/dist/types/components/menusheet/index.d.ts +2 -0
  222. package/dist/types/components/menusheet/menusheet.d.ts +42 -0
  223. package/dist/types/components/menusheet/menusheet.recipe.d.ts +3 -0
  224. package/dist/types/components/snackbar/index.d.ts +2 -0
  225. package/dist/types/components/snackbar/snackbar.d.ts +36 -0
  226. package/dist/types/components/snackbar/snackbar.recipe.d.ts +5 -0
  227. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +28 -1
  228. package/dist/types/components/tabs/tabs.d.ts +11 -1
  229. package/dist/types/index.d.ts +7 -0
  230. package/dist/types/product/comments/comments.d.ts +9 -3
  231. package/dist/types/product/comments/comments.recipe.d.ts +12 -2
  232. package/dist/types/product/memberssettings/index.d.ts +1 -0
  233. package/dist/types/product/memberssettings/memberssettings.d.ts +85 -0
  234. package/dist/types/product/memberssettings/memberssettings.recipe.d.ts +3 -0
  235. package/dist/types/product/notificationssettings/index.d.ts +1 -0
  236. package/dist/types/product/notificationssettings/notificationssettings.d.ts +37 -0
  237. package/dist/types/product/notificationssettings/notificationssettings.recipe.d.ts +3 -0
  238. package/dist/types/product/recordpage/recordpage.d.ts +53 -2
  239. package/dist/types/product/workspacegeneralsettings/index.d.ts +1 -0
  240. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.d.ts +48 -0
  241. package/dist/types/product/workspacegeneralsettings/workspacegeneralsettings.recipe.d.ts +3 -0
  242. package/dist/types/tokens/contract.d.ts +4 -1
  243. package/dist/types/tokens/elevation.d.ts +8 -5
  244. package/dist/types/tokens/palette.d.ts +9 -1
  245. package/dist/types/tokens/scale.d.ts +11 -1
  246. package/dist/types/tokens/semantic.d.ts +2 -0
  247. package/dist/wheelpicker.css +4 -2
  248. package/dist/wheelpicker.layered.css +4 -2
  249. package/dist/workspacegeneralsettings.css +30 -0
  250. package/dist/workspacegeneralsettings.d.ts +7 -0
  251. package/dist/workspacegeneralsettings.layered.css +32 -0
  252. package/package.json +36 -1
package/dist/table.css CHANGED
@@ -1,38 +1,56 @@
1
1
  .crisp-table {
2
- display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps` (style/className on this element), and the header/footer below pin inside it exactly the way Attio's own grid does ("Both the header and
2
+ display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps`
3
+ (style/className on this element), and the header/footer below pin
4
+ inside it exactly the way Attio's own grid does ("Both the header and
3
5
  the summary row are sticky, on the scroll container rather than the
4
6
  cells" -- docs/study/attio-table.md). Unbounded, `overflow: auto`
5
7
  shows no vertical scrollbar and nothing sticks, so this is a no-op
6
8
  for every existing consumer that never set a height. */
7
9
  & .crisp-table-scroll { overflow: auto; }
8
10
  & table { width: 100%; border-collapse: separate; border-spacing: 0; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
9
- /* #465: 12px, not crisp's old 8px -- measured on a live header cell (padding: 0 12px) and independently on a body cell's text inset
11
+ /* #465: 12px, not crisp's old 8px -- measured on a live header cell
12
+ (padding: 0 12px) and independently on a body cell's text inset
10
13
  (getBoundingClientRect delta from the cell edge). Matches
11
14
  ColumnCalc's own already-correct 12px trigger inset. */
12
15
  & th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
13
16
  /* #554: sticky on the vertical axis, mirroring RecordsTable's own
14
17
  `.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
15
- and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins. `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
18
+ and below a sticky-column corner cell (DataTable's `th[data-sticky]`,
19
+ z-index 3), so the corner always wins.
20
+ `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
16
21
  column renders its BODY cell as a real `<th scope="row">` (#779, for
17
22
  a11y), and a bare `th` here matched that one too -- every property in
18
23
  this rule leaked onto it: `height: tableHeader` (40px) stretched the
19
24
  whole body row to 40px instead of 36 (#833, confirmed live on the
20
25
  showcase, every td in the row equalized to the one th); `color:
21
- color-mix(...63%...)` muted the primary column's own text below every sibling `<td>`'s full-opacity color (#835, re-measured live against
22
- Attio's own header labels -- including a genuinely computed one, "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no muting at all, so this drops the color-mix entirely rather than narrowing it); `position:sticky; top:0` tried to stick a BODY row to the scroll container's top; the extra `border-top` doubled that
23
- row's own grid line. `thead th` simply never matches `tbody th[scope=row]` at all, so none of this reaches it; the base `& th, & td` rule above (36px, one border-bottom, full opacity via `& table`'s own color) applies to it like every other cell. */
26
+ color-mix(...63%...)` muted the primary column's own text below every
27
+ sibling `<td>`'s full-opacity color (#835, re-measured live against
28
+ Attio's own header labels -- including a genuinely computed one,
29
+ "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no
30
+ muting at all, so this drops the color-mix entirely rather than
31
+ narrowing it); `position:sticky; top:0` tried to stick a BODY row
32
+ to the scroll container's top; the extra `border-top` doubled that
33
+ row's own grid line. `thead th` simply never matches
34
+ `tbody th[scope=row]` at all, so none of this reaches it; the base
35
+ `& th, & td` rule above (36px, one border-bottom, full opacity via
36
+ `& table`'s own color) applies to it like every other cell. */
24
37
  & thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
25
38
  & td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
26
- /* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the header rule above to `thead th` correctly stopped it leaking onto the primary column's body cell (a real `<th scope="row">` since
27
- #779), but that same leaked rule's `font-weight: var(--crisp-weight-medium)` was the ONLY thing overriding the browser's own UA stylesheet default
39
+ /* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the
40
+ header rule above to `thead th` correctly stopped it leaking onto
41
+ the primary column's body cell (a real `<th scope="row">` since
42
+ #779), but that same leaked rule's `font-weight: var(--crisp-weight-medium)`
43
+ was the ONLY thing overriding the browser's own UA stylesheet default
28
44
  for `<th>` (`font-weight: bold; text-align: center`) on that cell --
29
45
  once the leak stopped, a plain-text primary column fell through to
30
46
  bold+centred instead of matching its sibling `<td>`s (`400`/start,
31
- Attio's own plain-text primary cell). `text-align` was already safe (the base `& th, & td` rule's own `text-align: start` above is
47
+ Attio's own plain-text primary cell). `text-align` was already safe
48
+ (the base `& th, & td` rule's own `text-align: start` above is
32
49
  author-origin and always beats the UA stylesheet regardless of
33
50
  specificity) but is restated here explicitly, defensively -- cheap,
34
51
  and removes any doubt. `type: "entity"` primary columns are a
35
- separate case (Attio's own entity/record names are 500, not 400) -- see `.crisp-datatable-entity-name`'s own new explicit weight in
52
+ separate case (Attio's own entity/record names are 500, not 400) --
53
+ see `.crisp-datatable-entity-name`'s own new explicit weight in
36
54
  datatable.recipe.ts, which wins here by class specificity. */
37
55
  & tbody th { font-weight: var(--crisp-weight-regular); text-align: start; }
38
56
  & th:last-child, & td:last-child { border-inline-end: none; }
@@ -1,39 +1,57 @@
1
1
  @layer crisp-components {
2
2
  .crisp-table {
3
- display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps` (style/className on this element), and the header/footer below pin inside it exactly the way Attio's own grid does ("Both the header and
3
+ display: block; box-sizing: border-box; background: var(--crisp-bg-surface); /* #554: both axes -- a consumer bounds the height via `scrollProps`
4
+ (style/className on this element), and the header/footer below pin
5
+ inside it exactly the way Attio's own grid does ("Both the header and
4
6
  the summary row are sticky, on the scroll container rather than the
5
7
  cells" -- docs/study/attio-table.md). Unbounded, `overflow: auto`
6
8
  shows no vertical scrollbar and nothing sticks, so this is a no-op
7
9
  for every existing consumer that never set a height. */
8
10
  & .crisp-table-scroll { overflow: auto; }
9
11
  & table { width: 100%; border-collapse: separate; border-spacing: 0; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
10
- /* #465: 12px, not crisp's old 8px -- measured on a live header cell (padding: 0 12px) and independently on a body cell's text inset
12
+ /* #465: 12px, not crisp's old 8px -- measured on a live header cell
13
+ (padding: 0 12px) and independently on a body cell's text inset
11
14
  (getBoundingClientRect delta from the cell edge). Matches
12
15
  ColumnCalc's own already-correct 12px trigger inset. */
13
16
  & th, & td { position: relative; height: var(--crisp-size-tableRow); padding: 0 var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); border-inline-end: 1px solid var(--crisp-border-subtle); text-align: start; vertical-align: middle; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
14
17
  /* #554: sticky on the vertical axis, mirroring RecordsTable's own
15
18
  `.crisp-recordstable-th`. z-index 2 sits above a plain body cell (auto)
16
- and below a sticky-column corner cell (DataTable's `th[data-sticky]`, z-index 3), so the corner always wins. `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
19
+ and below a sticky-column corner cell (DataTable's `th[data-sticky]`,
20
+ z-index 3), so the corner always wins.
21
+ `thead th`, not a bare `th` (crisp#833/#835): DataTable's primary
17
22
  column renders its BODY cell as a real `<th scope="row">` (#779, for
18
23
  a11y), and a bare `th` here matched that one too -- every property in
19
24
  this rule leaked onto it: `height: tableHeader` (40px) stretched the
20
25
  whole body row to 40px instead of 36 (#833, confirmed live on the
21
26
  showcase, every td in the row equalized to the one th); `color:
22
- color-mix(...63%...)` muted the primary column's own text below every sibling `<td>`'s full-opacity color (#835, re-measured live against
23
- Attio's own header labels -- including a genuinely computed one, "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no muting at all, so this drops the color-mix entirely rather than narrowing it); `position:sticky; top:0` tried to stick a BODY row to the scroll container's top; the extra `border-top` doubled that
24
- row's own grid line. `thead th` simply never matches `tbody th[scope=row]` at all, so none of this reaches it; the base `& th, & td` rule above (36px, one border-bottom, full opacity via `& table`'s own color) applies to it like every other cell. */
27
+ color-mix(...63%...)` muted the primary column's own text below every
28
+ sibling `<td>`'s full-opacity color (#835, re-measured live against
29
+ Attio's own header labels -- including a genuinely computed one,
30
+ "Twitter follower count" -- all fully opaque `rgb(16,17,18)`, no
31
+ muting at all, so this drops the color-mix entirely rather than
32
+ narrowing it); `position:sticky; top:0` tried to stick a BODY row
33
+ to the scroll container's top; the extra `border-top` doubled that
34
+ row's own grid line. `thead th` simply never matches
35
+ `tbody th[scope=row]` at all, so none of this reaches it; the base
36
+ `& th, & td` rule above (36px, one border-bottom, full opacity via
37
+ `& table`'s own color) applies to it like every other cell. */
25
38
  & thead th { position: sticky; top: 0; z-index: 2; height: var(--crisp-size-tableHeader); background: var(--crisp-bg-surface); border-top: 1px solid var(--crisp-border-subtle); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-primary); user-select: none; }
26
39
  & td { color: var(--crisp-fg-primary); background: var(--crisp-bg-surface); }
27
- /* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the header rule above to `thead th` correctly stopped it leaking onto the primary column's body cell (a real `<th scope="row">` since
28
- #779), but that same leaked rule's `font-weight: var(--crisp-weight-medium)` was the ONLY thing overriding the browser's own UA stylesheet default
40
+ /* crisp#851 -- a REGRESSION from #833/#835/#848's own fix: scoping the
41
+ header rule above to `thead th` correctly stopped it leaking onto
42
+ the primary column's body cell (a real `<th scope="row">` since
43
+ #779), but that same leaked rule's `font-weight: var(--crisp-weight-medium)`
44
+ was the ONLY thing overriding the browser's own UA stylesheet default
29
45
  for `<th>` (`font-weight: bold; text-align: center`) on that cell --
30
46
  once the leak stopped, a plain-text primary column fell through to
31
47
  bold+centred instead of matching its sibling `<td>`s (`400`/start,
32
- Attio's own plain-text primary cell). `text-align` was already safe (the base `& th, & td` rule's own `text-align: start` above is
48
+ Attio's own plain-text primary cell). `text-align` was already safe
49
+ (the base `& th, & td` rule's own `text-align: start` above is
33
50
  author-origin and always beats the UA stylesheet regardless of
34
51
  specificity) but is restated here explicitly, defensively -- cheap,
35
52
  and removes any doubt. `type: "entity"` primary columns are a
36
- separate case (Attio's own entity/record names are 500, not 400) -- see `.crisp-datatable-entity-name`'s own new explicit weight in
53
+ separate case (Attio's own entity/record names are 500, not 400) --
54
+ see `.crisp-datatable-entity-name`'s own new explicit weight in
37
55
  datatable.recipe.ts, which wins here by class specificity. */
38
56
  & tbody th { font-weight: var(--crisp-weight-regular); text-align: start; }
39
57
  & th:last-child, & td:last-child { border-inline-end: none; }
@@ -7,12 +7,18 @@
7
7
  & .crisp-tabletoolbar-search svg { flex-shrink: 0; }
8
8
  & .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
9
9
  & .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
10
- /* crisp/#830: every trigger label here (Sort, Filter, View settings, Import/Export -- all compose this one shared .tool rule) read the "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
11
- (the button root itself inherits Attio's own 10px rem base and is a red herring, the same trap the original "10px font" layout-audit finding fell into): every label leaf is 14px/500/lh20, the "lg" text size. */
10
+ /* crisp/#830: every trigger label here (Sort, Filter, View settings,
11
+ Import/Export -- all compose this one shared .tool rule) read the
12
+ "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
13
+ (the button root itself inherits Attio's own 10px rem base and is a
14
+ red herring, the same trap the original "10px font" layout-audit
15
+ finding fell into): every label leaf is 14px/500/lh20, the "lg" text
16
+ size. */
12
17
  & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
13
18
  & .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
14
19
  & .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
15
- /* crisp/#772: re-measured live on Sort with an actual sort applied -- an active trigger's own fill is white (bgSurface), the same as the
20
+ /* crisp/#772: re-measured live on Sort with an actual sort applied --
21
+ an active trigger's own fill is white (bgSurface), the same as the
16
22
  base .tool rule above now already sets; this override existed to
17
23
  distinguish active from a base state that used to be transparent.
18
24
  Kept explicit (not just deleted) so a future change to the base
@@ -23,13 +29,23 @@
23
29
  /* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
24
30
  trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
25
31
  a dashed ::before (1px dashed, border-radius: inherit, absolutely
26
- positioned inset: 0) over a barely-there fill, confirmed on Attio's own empty Filter chip (its ::before border computes to exactly "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger drops the dashed pseudo and picks up the base tool's own solid ring
32
+ positioned inset: 0) over a barely-there fill, confirmed on Attio's
33
+ own empty Filter chip (its ::before border computes to exactly
34
+ "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger
35
+ drops the dashed pseudo and picks up the base tool's own solid ring
27
36
  instead (the --active modifier, unchanged) -- confirmed on Sort with
28
37
  an actual sort applied. color-mix (not the raw rgba Attio computes
29
38
  to) so both the border and the fill flip correctly in dark mode, the
30
39
  same reasoning --ghost above already uses. Only wired into
31
- TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. crisp/#844, correcting #831: the label colour was added here later, muting only the FILTER trigger (via a "--filter" modifier), on the assumption that was a Filter-specific tone distinct from Sort's.
32
- Re-measured live and that premise was wrong -- Sort's own resting label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5) as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
40
+ TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's
41
+ own Sort/Filter triggers share this same chrome function but are
42
+ deprecated, not touched here.
43
+ crisp/#844, correcting #831: the label colour was added here later,
44
+ muting only the FILTER trigger (via a "--filter" modifier), on the
45
+ assumption that was a Filter-specific tone distinct from Sort's.
46
+ Re-measured live and that premise was wrong -- Sort's own resting
47
+ label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5)
48
+ as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
33
49
  "Sort's colour" in an earlier pass is a different thing entirely: the
34
50
  "Sorted by" PREFIX word inside an ACTIVE sort chip, #788 -- a
35
51
  compound-label treatment that only exists once a sort is applied, not
@@ -116,17 +132,21 @@
116
132
  & .crisp-tabletoolbar-fchip-x:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
117
133
  & .crisp-tabletoolbar-spacer { flex: 1; }
118
134
  & .crisp-tabletoolbar-count { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
119
- & .crisp-tabletoolbar-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 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; transition: background-color .12s; }
120
- & .crisp-tabletoolbar-new:hover { background: var(--crisp-bg-brand-solid-pressed); }
121
-
135
+ /* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
136
+ the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
137
+ clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897).
138
+ Hover is a brightness filter on the new fill, not bgBrandSolidPressed
139
+ (that token stays tuned for the lighter accent's own consumers). */
140
+ & .crisp-tabletoolbar-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 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; transition: filter .12s; }
141
+ & .crisp-tabletoolbar-new:hover { filter: brightness(0.96); }
122
142
  & .crisp-tabletoolbar-fcond { display: inline-flex; align-items: center; height: var(--crisp-size-row); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); white-space: nowrap; }
123
143
  & .crisp-tabletoolbar-fcond-seg { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); font-family: inherit; font-size: inherit; color: inherit; cursor: pointer; }
124
144
  & .crisp-tabletoolbar-fcond-seg svg { flex-shrink: 0; }
125
- & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field,
126
- & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
145
+ & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field, & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
127
146
  & .crisp-tabletoolbar-fcond-seg--field { border-radius: var(--crisp-radius-md) 0 0 var(--crisp-radius-md); font-weight: var(--crisp-weight-medium); max-width: 200px; }
128
147
  & .crisp-tabletoolbar-fcond-seg--field svg { color: var(--crisp-fg-muted); }
129
- /* #592: a nested pick's field segment ("Team › Twitter follower count") — measured live: BOTH path segments the same colour (chip
148
+ /* #592: a nested pick's field segment ("Team › Twitter follower
149
+ count") — measured live: BOTH path segments the same colour (chip
130
150
  context only; the picker's own menu rows keep the parent muted, see
131
151
  tabletoolbar.chrome.ts), each independently truncated. Attio's own
132
152
  layout gives the leaf segment priority (it stays fully readable
@@ -152,8 +172,7 @@
152
172
  & .crisp-tabletoolbar-sort-field-picker { position: relative; display: inline-flex; flex: 1; min-width: 0; }
153
173
  & .crisp-tabletoolbar-sort-field-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); width: 100%; min-width: 0; margin: 0; padding: 0 var(--crisp-space-1-5) 0 var(--crisp-space-2); border: none; 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); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s ease, box-shadow .12s ease; }
154
174
  & .crisp-tabletoolbar-sort-field-trigger:hover { background: var(--crisp-bg-raised); }
155
- & .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"],
156
- & .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
175
+ & .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"], & .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
157
176
  & .crisp-tabletoolbar-sort-field-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; }
158
177
  & .crisp-tabletoolbar-sort-field-picker .crisp-tabletoolbar-menu { min-width: 200px; }
159
178
  & .crisp-tabletoolbar-menu--val { min-width: 134px; }
@@ -161,18 +180,10 @@
161
180
  & .crisp-tabletoolbar-datepop-presets { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-2); padding: 0 var(--crisp-space-1); }
162
181
  & .crisp-tabletoolbar-datepop-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; }
163
182
  & .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
164
-
165
183
  & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
166
-
167
184
  & .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
168
- & .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
169
- padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent);
170
- box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
171
-
172
- & .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
173
- padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent);
174
- box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft);
175
- font-variant-numeric: tabular-nums; }
185
+ & .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
186
+ & .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); font-variant-numeric: tabular-nums; }
176
187
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
177
188
  }
178
189
 
@@ -8,12 +8,18 @@
8
8
  & .crisp-tabletoolbar-search svg { flex-shrink: 0; }
9
9
  & .crisp-tabletoolbar-search input { border: none; outline: none; background: transparent; font-family: inherit; font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); width: 180px; }
10
10
  & .crisp-tabletoolbar-search input::placeholder { color: var(--crisp-fg-muted); }
11
- /* crisp/#830: every trigger label here (Sort, Filter, View settings, Import/Export -- all compose this one shared .tool rule) read the "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
12
- (the button root itself inherits Attio's own 10px rem base and is a red herring, the same trap the original "10px font" layout-audit finding fell into): every label leaf is 14px/500/lh20, the "lg" text size. */
11
+ /* crisp/#830: every trigger label here (Sort, Filter, View settings,
12
+ Import/Export -- all compose this one shared .tool rule) read the
13
+ "md" text size, 13px. Re-measured on Attio's own trigger LEAF node
14
+ (the button root itself inherits Attio's own 10px rem base and is a
15
+ red herring, the same trap the original "10px font" layout-audit
16
+ finding fell into): every label leaf is 14px/500/lh20, the "lg" text
17
+ size. */
13
18
  & .crisp-tabletoolbar-tool { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); margin: 0; padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
14
19
  & .crisp-tabletoolbar-tool:hover { background: var(--crisp-bg-raised); }
15
20
  & .crisp-tabletoolbar-tool svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
16
- /* crisp/#772: re-measured live on Sort with an actual sort applied -- an active trigger's own fill is white (bgSurface), the same as the
21
+ /* crisp/#772: re-measured live on Sort with an actual sort applied --
22
+ an active trigger's own fill is white (bgSurface), the same as the
17
23
  base .tool rule above now already sets; this override existed to
18
24
  distinguish active from a base state that used to be transparent.
19
25
  Kept explicit (not just deleted) so a future change to the base
@@ -24,13 +30,23 @@
24
30
  /* crisp/#772 follow-up, re-measured live 2026-09-25: an EMPTY Sort/Filter
25
31
  trigger (no sort/condition set) isn't a solid-ring chip at all -- it's
26
32
  a dashed ::before (1px dashed, border-radius: inherit, absolutely
27
- positioned inset: 0) over a barely-there fill, confirmed on Attio's own empty Filter chip (its ::before border computes to exactly "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger drops the dashed pseudo and picks up the base tool's own solid ring
33
+ positioned inset: 0) over a barely-there fill, confirmed on Attio's
34
+ own empty Filter chip (its ::before border computes to exactly
35
+ "1px dashed rgba(0, 0, 0, 0.06)"). Once a value IS set, the trigger
36
+ drops the dashed pseudo and picks up the base tool's own solid ring
28
37
  instead (the --active modifier, unchanged) -- confirmed on Sort with
29
38
  an actual sort applied. color-mix (not the raw rgba Attio computes
30
39
  to) so both the border and the fill flip correctly in dark mode, the
31
40
  same reasoning --ghost above already uses. Only wired into
32
- TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's own Sort/Filter triggers share this same chrome function but are deprecated, not touched here. crisp/#844, correcting #831: the label colour was added here later, muting only the FILTER trigger (via a "--filter" modifier), on the assumption that was a Filter-specific tone distinct from Sort's.
33
- Re-measured live and that premise was wrong -- Sort's own resting label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5) as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
41
+ TableToolbar itself (tabletoolbar.tsx) this pass -- RecordsTable's
42
+ own Sort/Filter triggers share this same chrome function but are
43
+ deprecated, not touched here.
44
+ crisp/#844, correcting #831: the label colour was added here later,
45
+ muting only the FILTER trigger (via a "--filter" modifier), on the
46
+ assumption that was a Filter-specific tone distinct from Sort's.
47
+ Re-measured live and that premise was wrong -- Sort's own resting
48
+ label ("Sort", no condition set) is the exact SAME muted rgba(0,0,0,.5)
49
+ as Filter's, not full-strength. (The rgba(0,0,0,.63) that looked like
34
50
  "Sort's colour" in an earlier pass is a different thing entirely: the
35
51
  "Sorted by" PREFIX word inside an ACTIVE sort chip, #788 -- a
36
52
  compound-label treatment that only exists once a sort is applied, not
@@ -117,17 +133,21 @@
117
133
  & .crisp-tabletoolbar-fchip-x:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); color: var(--crisp-fg-primary); }
118
134
  & .crisp-tabletoolbar-spacer { flex: 1; }
119
135
  & .crisp-tabletoolbar-count { font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
120
- & .crisp-tabletoolbar-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 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; transition: background-color .12s; }
121
- & .crisp-tabletoolbar-new:hover { background: var(--crisp-bg-brand-solid-pressed); }
122
-
136
+ /* your-moon/crisp#953: bgBrandContrast, not bgBrandSolid --
137
+ the accent (#0298d9) only clears 3.23:1 with white; the darker sibling
138
+ clears 4.5:1+, same fix already applied to Button/Badge/Avatar (#897).
139
+ Hover is a brightness filter on the new fill, not bgBrandSolidPressed
140
+ (that token stays tuned for the lighter accent's own consumers). */
141
+ & .crisp-tabletoolbar-new { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: var(--crisp-size-row); padding: 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; transition: filter .12s; }
142
+ & .crisp-tabletoolbar-new:hover { filter: brightness(0.96); }
123
143
  & .crisp-tabletoolbar-fcond { display: inline-flex; align-items: center; height: var(--crisp-size-row); font-size: var(--crisp-text-md); color: var(--crisp-fg-primary); white-space: nowrap; }
124
144
  & .crisp-tabletoolbar-fcond-seg { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 100%; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: var(--crisp-bg-surface-muted); box-shadow: inset 0 0 0 1px var(--crisp-border-divider); font-family: inherit; font-size: inherit; color: inherit; cursor: pointer; }
125
145
  & .crisp-tabletoolbar-fcond-seg svg { flex-shrink: 0; }
126
- & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field,
127
- & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
146
+ & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--field, & .crisp-tabletoolbar-fcond[data-complete] .crisp-tabletoolbar-fcond-seg--val { background: var(--crisp-bg-surface); }
128
147
  & .crisp-tabletoolbar-fcond-seg--field { border-radius: var(--crisp-radius-md) 0 0 var(--crisp-radius-md); font-weight: var(--crisp-weight-medium); max-width: 200px; }
129
148
  & .crisp-tabletoolbar-fcond-seg--field svg { color: var(--crisp-fg-muted); }
130
- /* #592: a nested pick's field segment ("Team › Twitter follower count") — measured live: BOTH path segments the same colour (chip
149
+ /* #592: a nested pick's field segment ("Team › Twitter follower
150
+ count") — measured live: BOTH path segments the same colour (chip
131
151
  context only; the picker's own menu rows keep the parent muted, see
132
152
  tabletoolbar.chrome.ts), each independently truncated. Attio's own
133
153
  layout gives the leaf segment priority (it stays fully readable
@@ -153,8 +173,7 @@
153
173
  & .crisp-tabletoolbar-sort-field-picker { position: relative; display: inline-flex; flex: 1; min-width: 0; }
154
174
  & .crisp-tabletoolbar-sort-field-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-menuRow); width: 100%; min-width: 0; margin: 0; padding: 0 var(--crisp-space-1-5) 0 var(--crisp-space-2); border: none; 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); font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); cursor: pointer; transition: background-color .12s ease, box-shadow .12s ease; }
155
175
  & .crisp-tabletoolbar-sort-field-trigger:hover { background: var(--crisp-bg-raised); }
156
- & .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"],
157
- & .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
176
+ & .crisp-tabletoolbar-sort-field-trigger[aria-expanded="true"], & .crisp-tabletoolbar-sort-field-trigger:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); background: var(--crisp-bg-surface); }
158
177
  & .crisp-tabletoolbar-sort-field-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; }
159
178
  & .crisp-tabletoolbar-sort-field-picker .crisp-tabletoolbar-menu { min-width: 200px; }
160
179
  & .crisp-tabletoolbar-menu--val { min-width: 134px; }
@@ -162,18 +181,10 @@
162
181
  & .crisp-tabletoolbar-datepop-presets { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-2); padding: 0 var(--crisp-space-1); }
163
182
  & .crisp-tabletoolbar-datepop-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; }
164
183
  & .crisp-tabletoolbar-datepop-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
165
-
166
184
  & .crisp-tabletoolbar-tool--raised { border: none; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; cursor: pointer; }
167
-
168
185
  & .crisp-tabletoolbar-sorted-prefix { color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
169
- & .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
170
- padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent);
171
- box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
172
-
173
- & .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box;
174
- padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent);
175
- box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft);
176
- font-variant-numeric: tabular-nums; }
186
+ & .crisp-tabletoolbar-sorted-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
187
+ & .crisp-tabletoolbar-tool-count { display: inline-flex; align-items: center; height: 16px; box-sizing: border-box; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); font-variant-numeric: tabular-nums; }
177
188
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
178
189
  }
179
190
 
package/dist/tabs.css CHANGED
@@ -2,17 +2,31 @@
2
2
  display: flex; flex-direction: column; min-height: 0; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
3
3
  & .crisp-tabs-list { position: relative; display: flex; align-items: center; gap: var(--crisp-space-1); box-sizing: content-box; height: var(--crisp-size-row); padding: 0 var(--crisp-space-3) var(--crisp-space-2); flex-shrink: 0; }
4
4
  & .crisp-tabs-list::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--crisp-border-subtle); }
5
+ /* crisp#908: an alternative to the "+N more" collapse above (crisp#863) --
6
+ a consumer opts into a single scrolling row instead (Naver/Kakao's own
7
+ pattern, docs/study/korean/), never both at once. No new visual value:
8
+ reuses the same list gap/tab geometry, only adds overflow-x + snap. */
9
+ & .crisp-tabs-list[data-overflow="scroll"] { overflow-x: auto; flex-wrap: nowrap; scroll-snap-type: x mandatory; scrollbar-width: none; }
10
+ & .crisp-tabs-list[data-overflow="scroll"]::-webkit-scrollbar { display: none; }
11
+ & .crisp-tabs-list[data-overflow="scroll"] .crisp-tabs-tab { flex-shrink: 0; scroll-snap-align: start; }
5
12
  & .crisp-tabs-leading { display: inline-flex; align-items: center; margin-inline-end: var(--crisp-space-1); }
6
- & .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; box-shadow: inset 0 0 0 1px transparent; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-muted); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease, box-shadow .12s ease; }
13
+ & .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-muted); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease; }
7
14
  & .crisp-tabs-tab svg { flex-shrink: 0; opacity: 0.85; }
8
15
  & .crisp-tabs-tab:hover:not([data-selected]) { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
9
- & .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary); background: var(--crisp-bg-subtle); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); }
16
+ & .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary); }
10
17
  & .crisp-tabs-tab:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
11
18
  & .crisp-tabs-tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 14px; height: 14px; padding: 0 var(--crisp-space-1); border-radius: 4px; background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: 10px; line-height: 14px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
12
19
  & .crisp-tabs-tab[data-selected] .crisp-tabs-tab-badge { color: var(--crisp-fg-primary); }
13
20
  & .crisp-tabs-indicator { position: absolute; bottom: 0; left: 0; z-index: 1; height: 1px; background: var(--crisp-fg-primary); border-radius: 2px 2px 0 0; transition: transform .2s cubic-bezier(.4,0,.2,1), width .2s cubic-bezier(.4,0,.2,1); pointer-events: none; }
14
- /* crisp#863: the "+N more" overflow trigger, measured live -- its computed style is identical to a plain .crisp-tabs-tab (same pill, same 6px icon/label gap the tab class already gives via space["1.5"]), and the dropdown it opens is crisp's own Menu/
15
- MenuItem chrome (already matches Attio's popover, nothing new to style there). Only the wrapper needs a rule: an overflowed tab (or the trigger itself, when nothing is hidden) is taken out of the flex row and out of the a11y tree without ever making its own offsetWidth unmeasurable the way display:none would -- that's what
21
+ /* crisp#863: the "+N more" overflow trigger, measured live -- its
22
+ computed style is identical to a plain .crisp-tabs-tab (same pill,
23
+ same 6px icon/label gap the tab class already gives via
24
+ space["1.5"]), and the dropdown it opens is crisp's own Menu/
25
+ MenuItem chrome (already matches Attio's popover, nothing new to
26
+ style there). Only the wrapper needs a rule: an overflowed tab (or
27
+ the trigger itself, when nothing is hidden) is taken out of the
28
+ flex row and out of the a11y tree without ever making its own
29
+ offsetWidth unmeasurable the way display:none would -- that's what
16
30
  lets the tabs.tsx effect recompute the cutoff from cached widths on
17
31
  every resize with no flash of an unclipped row. */
18
32
  & .crisp-tabs-more { display: inline-flex; }
@@ -3,17 +3,31 @@
3
3
  display: flex; flex-direction: column; min-height: 0; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
4
4
  & .crisp-tabs-list { position: relative; display: flex; align-items: center; gap: var(--crisp-space-1); box-sizing: content-box; height: var(--crisp-size-row); padding: 0 var(--crisp-space-3) var(--crisp-space-2); flex-shrink: 0; }
5
5
  & .crisp-tabs-list::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--crisp-border-subtle); }
6
+ /* crisp#908: an alternative to the "+N more" collapse above (crisp#863) --
7
+ a consumer opts into a single scrolling row instead (Naver/Kakao's own
8
+ pattern, docs/study/korean/), never both at once. No new visual value:
9
+ reuses the same list gap/tab geometry, only adds overflow-x + snap. */
10
+ & .crisp-tabs-list[data-overflow="scroll"] { overflow-x: auto; flex-wrap: nowrap; scroll-snap-type: x mandatory; scrollbar-width: none; }
11
+ & .crisp-tabs-list[data-overflow="scroll"]::-webkit-scrollbar { display: none; }
12
+ & .crisp-tabs-list[data-overflow="scroll"] .crisp-tabs-tab { flex-shrink: 0; scroll-snap-align: start; }
6
13
  & .crisp-tabs-leading { display: inline-flex; align-items: center; margin-inline-end: var(--crisp-space-1); }
7
- & .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; box-shadow: inset 0 0 0 1px transparent; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-muted); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease, box-shadow .12s ease; }
14
+ & .crisp-tabs-tab { position: relative; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: 28px; margin: 0; padding: 0 var(--crisp-space-2); border: none; background: none; border-radius: var(--crisp-radius-md); font-family: inherit; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); letter-spacing: -0.14px; color: var(--crisp-fg-muted); cursor: pointer; white-space: nowrap; transition: color .12s ease, background-color .12s ease; }
8
15
  & .crisp-tabs-tab svg { flex-shrink: 0; opacity: 0.85; }
9
16
  & .crisp-tabs-tab:hover:not([data-selected]) { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); color: var(--crisp-fg-primary); }
10
- & .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary); background: var(--crisp-bg-subtle); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); }
17
+ & .crisp-tabs-tab[data-selected] { color: var(--crisp-fg-primary); }
11
18
  & .crisp-tabs-tab:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
12
19
  & .crisp-tabs-tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 14px; height: 14px; padding: 0 var(--crisp-space-1); border-radius: 4px; background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); font-size: 10px; line-height: 14px; font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-neutral-soft); }
13
20
  & .crisp-tabs-tab[data-selected] .crisp-tabs-tab-badge { color: var(--crisp-fg-primary); }
14
21
  & .crisp-tabs-indicator { position: absolute; bottom: 0; left: 0; z-index: 1; height: 1px; background: var(--crisp-fg-primary); border-radius: 2px 2px 0 0; transition: transform .2s cubic-bezier(.4,0,.2,1), width .2s cubic-bezier(.4,0,.2,1); pointer-events: none; }
15
- /* crisp#863: the "+N more" overflow trigger, measured live -- its computed style is identical to a plain .crisp-tabs-tab (same pill, same 6px icon/label gap the tab class already gives via space["1.5"]), and the dropdown it opens is crisp's own Menu/
16
- MenuItem chrome (already matches Attio's popover, nothing new to style there). Only the wrapper needs a rule: an overflowed tab (or the trigger itself, when nothing is hidden) is taken out of the flex row and out of the a11y tree without ever making its own offsetWidth unmeasurable the way display:none would -- that's what
22
+ /* crisp#863: the "+N more" overflow trigger, measured live -- its
23
+ computed style is identical to a plain .crisp-tabs-tab (same pill,
24
+ same 6px icon/label gap the tab class already gives via
25
+ space["1.5"]), and the dropdown it opens is crisp's own Menu/
26
+ MenuItem chrome (already matches Attio's popover, nothing new to
27
+ style there). Only the wrapper needs a rule: an overflowed tab (or
28
+ the trigger itself, when nothing is hidden) is taken out of the
29
+ flex row and out of the a11y tree without ever making its own
30
+ offsetWidth unmeasurable the way display:none would -- that's what
17
31
  lets the tabs.tsx effect recompute the cutoff from cached widths on
18
32
  every resize with no flash of an unclipped row. */
19
33
  & .crisp-tabs-more { display: inline-flex; }
package/dist/textarea.css CHANGED
@@ -1,17 +1,13 @@
1
1
  .crisp-textarea {
2
2
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
3
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-field); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
3
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); border: 1px solid var(--crisp-border-default); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
4
4
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
5
5
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
6
6
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
7
7
  overlay that is present-but-transparent at rest, so focusing never
8
8
  shifts the box, animating only its colour. */
9
9
  & .crisp-textarea-wrap { position: relative; display: block; }
10
- & .crisp-textarea-wrap::after {
11
- content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md);
12
- border: 2px solid transparent; transition: border-color .1s ease;
13
- pointer-events: none;
14
- }
10
+ & .crisp-textarea-wrap::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md); border: 2px solid transparent; transition: border-color .1s ease; pointer-events: none; }
15
11
  & .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-stroke-field-focus); }
16
12
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
17
13
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
@@ -1,18 +1,14 @@
1
1
  @layer crisp-components {
2
2
  .crisp-textarea {
3
3
  position: relative; display: block; width: 100%; font-family: var(--crisp-font-sans);
4
- & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-field); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; transition: box-shadow .15s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
4
+ & .crisp-textarea-field { box-sizing: border-box; display: block; width: 100%; min-height: 80px; resize: vertical; margin: 0; padding: var(--crisp-space-2-5) 14px; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); border: 1px solid var(--crisp-border-default); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-primary); outline: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
5
5
  & .crisp-textarea-field::placeholder { color: var(--crisp-fg-muted); }
6
6
  & .crisp-textarea-field:disabled { opacity: 0.5; cursor: not-allowed; }
7
7
  /* seed-design's focus treatment, same as Input: a 2px ring on an ::after
8
8
  overlay that is present-but-transparent at rest, so focusing never
9
9
  shifts the box, animating only its colour. */
10
10
  & .crisp-textarea-wrap { position: relative; display: block; }
11
- & .crisp-textarea-wrap::after {
12
- content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md);
13
- border: 2px solid transparent; transition: border-color .1s ease;
14
- pointer-events: none;
15
- }
11
+ & .crisp-textarea-wrap::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-md); border: 2px solid transparent; transition: border-color .1s ease; pointer-events: none; }
16
12
  & .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-stroke-field-focus); }
17
13
  &[data-invalid] .crisp-textarea-wrap::after { border-color: var(--crisp-bg-danger); }
18
14
  &[data-invalid] .crisp-textarea-wrap:focus-within::after { border-color: var(--crisp-bg-danger); }
@@ -14,7 +14,8 @@
14
14
  & [data-swatch="light"] .crisp-themepicker-preview-bar:not(:nth-child(1)), & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #eeeff1; }
15
15
  & [data-swatch="light"] .crisp-themepicker-preview-main, & [data-swatch="system"] .crisp-themepicker-preview-main { background: #ffffff; }
16
16
  & [data-swatch="light"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar, & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #eeeff1; }
17
- /* Dark swatch colours -- always for "dark", and for "system" only when the OS itself reports dark. */
17
+ /* Dark swatch colours -- always for "dark", and for "system" only
18
+ when the OS itself reports dark. */
18
19
  & .crisp-themepicker-preview[data-swatch="dark"] { border: 1px solid #1c1d1f; background: #0e0f10; }
19
20
  & [data-swatch="dark"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
20
21
  & [data-swatch="dark"] .crisp-themepicker-preview-main { background: #0a0a0a; }
@@ -15,7 +15,8 @@
15
15
  & [data-swatch="light"] .crisp-themepicker-preview-bar:not(:nth-child(1)), & [data-swatch="system"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #eeeff1; }
16
16
  & [data-swatch="light"] .crisp-themepicker-preview-main, & [data-swatch="system"] .crisp-themepicker-preview-main { background: #ffffff; }
17
17
  & [data-swatch="light"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar, & [data-swatch="system"] .crisp-themepicker-preview-main .crisp-themepicker-preview-bar { background: #eeeff1; }
18
- /* Dark swatch colours -- always for "dark", and for "system" only when the OS itself reports dark. */
18
+ /* Dark swatch colours -- always for "dark", and for "system" only
19
+ when the OS itself reports dark. */
19
20
  & .crisp-themepicker-preview[data-swatch="dark"] { border: 1px solid #1c1d1f; background: #0e0f10; }
20
21
  & [data-swatch="dark"] .crisp-themepicker-preview-bar:not(:nth-child(1)) { background: #1c1d1f; }
21
22
  & [data-swatch="dark"] .crisp-themepicker-preview-main { background: #0a0a0a; }
package/dist/tokens.css CHANGED
@@ -45,7 +45,9 @@
45
45
  --crisp-ring-switch: #d9dade;
46
46
  --crisp-bg-tile-active: #ffffff;
47
47
  --crisp-shadow-tile-active: rgba(0,0,0,0.04);
48
- --crisp-bg-scrim: rgba(0,0,0,0.25);
48
+ --crisp-bg-scrim: rgba(0,0,0,0.45);
49
+ --crisp-bg-overlay-strong: #00000074;
50
+ --crisp-stroke-group-divider: #00000010;
49
51
  --crisp-fg-alert-description: rgba(0,0,0,0.63);
50
52
  --crisp-bg-overlay-frost: #ffffff;
51
53
  --crisp-shadow-overlay1: rgba(28,40,64,0.12);
@@ -117,6 +119,8 @@
117
119
  --crisp-bg-tile-active: #101112;
118
120
  --crisp-shadow-tile-active: rgba(0,0,0,0);
119
121
  --crisp-bg-scrim: rgba(0,0,0,0.55);
122
+ --crisp-bg-overlay-strong: #00000074;
123
+ --crisp-stroke-group-divider: #ffffff17;
120
124
  --crisp-fg-alert-description: rgba(255,255,255,0.6);
121
125
  --crisp-bg-overlay-frost: #1c1d1f;
122
126
  --crisp-shadow-overlay1: rgba(0,0,0,0.48);
@@ -182,13 +186,14 @@
182
186
  --crisp-space-2-5: 10px;
183
187
  --crisp-space-3-5: 14px;
184
188
  --crisp-radius-xs: 4px;
185
- --crisp-radius-chip: 7px;
189
+ --crisp-radius-chip: 999px;
186
190
  --crisp-radius-sm: 6px;
187
191
  --crisp-radius-md: 8px;
188
192
  --crisp-radius-lg: 9px;
189
193
  --crisp-radius-xl: 12px;
190
194
  --crisp-radius-2xl: 16px;
191
195
  --crisp-radius-3xl: 20px;
196
+ --crisp-radius-4xl: 24px;
192
197
  --crisp-radius-full: 999px;
193
198
  --crisp-size-icon: 16px;
194
199
  --crisp-size-chip: 22px;
@@ -212,4 +217,10 @@
212
217
  --crisp-weight-semibold: 600;
213
218
  --crisp-weight-bold: 700;
214
219
  --crisp-font-sans: "VK Sans Display", "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
220
+ --crisp-tracking-18: -0.36px;
221
+ --crisp-tracking-20: -0.4px;
222
+ --crisp-tracking-24: -0.48px;
223
+ --crisp-tracking-26: -0.52px;
224
+ --crisp-tracking-28: -0.56px;
225
+ --crisp-tracking-32: -0.64px;
215
226
  }