@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
@@ -8,13 +8,15 @@
8
8
  & .crisp-resizablepanel-panel[data-floating="false"] { border-radius: 0; box-shadow: none; }
9
9
  & .crisp-resizablepanel-panel[data-floating="false"][data-side="left"] { border-inline-end: 1px solid var(--crisp-border-subtle); }
10
10
  & .crisp-resizablepanel-panel[data-floating="false"][data-side="right"] { border-inline-start: 1px solid var(--crisp-border-subtle); }
11
- /* floating — position: fixed, 8px gutter, r10, the measured floating elevation. Rest is transform: none (Lesson 27); the off-canvas value is the @starting-style enter only. */
11
+ /* floating — position: fixed, 8px gutter, r10, the measured floating elevation.
12
+ Rest is transform: none (Lesson 27); the off-canvas value is the @starting-style enter only. */
12
13
  & .crisp-resizablepanel-panel[data-floating="true"] { position: fixed; top: var(--crisp-space-2); bottom: var(--crisp-space-2); border-inline-end: none; border-inline-start: none; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: none; transition: transform 0.14s, padding 0.14s; }
13
14
  & .crisp-resizablepanel-panel[data-floating="true"][data-side="left"] { padding: var(--crisp-space-2) 0 var(--crisp-space-2) var(--crisp-space-2); @starting-style { transform: translateX(calc(-100% - var(--crisp-space-2))); } }
14
15
  & .crisp-resizablepanel-panel[data-floating="true"][data-side="right"] { padding: var(--crisp-space-2) var(--crisp-space-2) var(--crisp-space-2) 0; @starting-style { transform: translateX(calc(100% + var(--crisp-space-2))); } }
15
16
  & .crisp-resizablepanel-inner { height: 100%; opacity: 1; }
16
17
  & .crisp-resizablepanel-panel[data-floating="true"] .crisp-resizablepanel-inner { opacity: 1; transition: opacity 0.14s; @starting-style { opacity: 0; } }
17
- /* handle — variant "panel" (default): a 10px hit target, its ::before the only visible divider (1px rest -> 2px on hover/drag, brand-solid). */
18
+ /* handle — variant "panel" (default): a 10px hit target, its ::before the
19
+ only visible divider (1px rest -> 2px on hover/drag, brand-solid). */
18
20
  & .crisp-resizablepanel-handle { position: absolute; top: 0; width: 10px; height: 100%; z-index: 2; cursor: col-resize; background: transparent; touch-action: none; }
19
21
  & .crisp-resizablepanel-handle[data-side="left"] { right: 0; }
20
22
  & .crisp-resizablepanel-handle[data-side="right"] { left: 0; }
@@ -22,9 +24,10 @@
22
24
  & .crisp-resizablepanel-handle[data-side="left"]::before { right: 0; }
23
25
  & .crisp-resizablepanel-handle[data-side="right"]::before { left: 0; }
24
26
  & .crisp-resizablepanel-handle:hover::before, & .crisp-resizablepanel-handle[data-dragging="true"]::before { width: 2px; background: var(--crisp-bg-brand-solid); }
25
- /* handle — variant "column": a wider 7px hit target straddling a 1px divider (table column edges), with a real 3px inner bar whose opacity comes in on a 100ms DELAY — distinct from the panel variant's instant
26
- ::before swap. */
27
- /* .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column (both classes) to
27
+ /* handle — variant "column": a wider 7px hit target straddling a 1px
28
+ divider (table column edges), with a real 3px inner bar whose opacity
29
+ comes in on a 100ms DELAY — distinct from the panel variant's instant
30
+ ::before swap. */ /* .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column (both classes) to
28
31
  out-specificity the base [data-side] left/right rules above, which
29
32
  otherwise tie-break by source order alone and would win. */
30
33
  & .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column { display: flex; align-items: center; justify-content: center; width: 7px; left: -3px; right: -3px; z-index: 1; cursor: col-resize; }
@@ -9,13 +9,15 @@
9
9
  & .crisp-resizablepanel-panel[data-floating="false"] { border-radius: 0; box-shadow: none; }
10
10
  & .crisp-resizablepanel-panel[data-floating="false"][data-side="left"] { border-inline-end: 1px solid var(--crisp-border-subtle); }
11
11
  & .crisp-resizablepanel-panel[data-floating="false"][data-side="right"] { border-inline-start: 1px solid var(--crisp-border-subtle); }
12
- /* floating — position: fixed, 8px gutter, r10, the measured floating elevation. Rest is transform: none (Lesson 27); the off-canvas value is the @starting-style enter only. */
12
+ /* floating — position: fixed, 8px gutter, r10, the measured floating elevation.
13
+ Rest is transform: none (Lesson 27); the off-canvas value is the @starting-style enter only. */
13
14
  & .crisp-resizablepanel-panel[data-floating="true"] { position: fixed; top: var(--crisp-space-2); bottom: var(--crisp-space-2); border-inline-end: none; border-inline-start: none; border-radius: 10px; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: none; transition: transform 0.14s, padding 0.14s; }
14
15
  & .crisp-resizablepanel-panel[data-floating="true"][data-side="left"] { padding: var(--crisp-space-2) 0 var(--crisp-space-2) var(--crisp-space-2); @starting-style { transform: translateX(calc(-100% - var(--crisp-space-2))); } }
15
16
  & .crisp-resizablepanel-panel[data-floating="true"][data-side="right"] { padding: var(--crisp-space-2) var(--crisp-space-2) var(--crisp-space-2) 0; @starting-style { transform: translateX(calc(100% + var(--crisp-space-2))); } }
16
17
  & .crisp-resizablepanel-inner { height: 100%; opacity: 1; }
17
18
  & .crisp-resizablepanel-panel[data-floating="true"] .crisp-resizablepanel-inner { opacity: 1; transition: opacity 0.14s; @starting-style { opacity: 0; } }
18
- /* handle — variant "panel" (default): a 10px hit target, its ::before the only visible divider (1px rest -> 2px on hover/drag, brand-solid). */
19
+ /* handle — variant "panel" (default): a 10px hit target, its ::before the
20
+ only visible divider (1px rest -> 2px on hover/drag, brand-solid). */
19
21
  & .crisp-resizablepanel-handle { position: absolute; top: 0; width: 10px; height: 100%; z-index: 2; cursor: col-resize; background: transparent; touch-action: none; }
20
22
  & .crisp-resizablepanel-handle[data-side="left"] { right: 0; }
21
23
  & .crisp-resizablepanel-handle[data-side="right"] { left: 0; }
@@ -23,9 +25,10 @@
23
25
  & .crisp-resizablepanel-handle[data-side="left"]::before { right: 0; }
24
26
  & .crisp-resizablepanel-handle[data-side="right"]::before { left: 0; }
25
27
  & .crisp-resizablepanel-handle:hover::before, & .crisp-resizablepanel-handle[data-dragging="true"]::before { width: 2px; background: var(--crisp-bg-brand-solid); }
26
- /* handle — variant "column": a wider 7px hit target straddling a 1px divider (table column edges), with a real 3px inner bar whose opacity comes in on a 100ms DELAY — distinct from the panel variant's instant
27
- ::before swap. */
28
- /* .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column (both classes) to
28
+ /* handle — variant "column": a wider 7px hit target straddling a 1px
29
+ divider (table column edges), with a real 3px inner bar whose opacity
30
+ comes in on a 100ms DELAY — distinct from the panel variant's instant
31
+ ::before swap. */ /* .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column (both classes) to
29
32
  out-specificity the base [data-side] left/right rules above, which
30
33
  otherwise tie-break by source order alone and would win. */
31
34
  & .crisp-resizablepanel-handle.crisp-resizablepanel-handle--column { display: flex; align-items: center; justify-content: center; width: 7px; left: -3px; right: -3px; z-index: 1; cursor: col-resize; }
package/dist/richtext.css CHANGED
@@ -9,13 +9,28 @@
9
9
  & .crisp-rte-body h1 { font-size: var(--crisp-text-xl); line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.3px; margin-top: var(--crisp-space-4); }
10
10
  & .crisp-rte-body h2 { font-size: 17px; line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; margin-top: var(--crisp-space-3); }
11
11
  & .crisp-rte-body h3 { font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-semibold); margin-top: var(--crisp-space-2-5); }
12
- /* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped ul, ol { list-style: none }
13
- , specificity 0,0,1) was winning every list marker outright -- this rule set padding but never declared list-style-type, so there was no higher-specificity value (this selector is 0,1,1) to beat the reset with. Split into two single-selector rules, each declaring its own marker type, rather than the old single comma-joined rule ( .crisp-rte-body ul, & .crisp-rte-body ol ) the issue flagged as malformed. #611: padding-inline-start re-measured live once CRUD on the measurement workspace was allowed (a "zz-parity" note with a bulleted list, a nested bulleted list, and a numbered list) -- Attio's own <ul>/<ol> measures 36px (getComputedStyle,
12
+ /* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped
13
+ ul, ol { list-style: none }, specificity 0,0,1) was winning every
14
+ list marker outright -- this rule set padding but never declared
15
+ list-style-type, so there was no higher-specificity value (this
16
+ selector is 0,1,1) to beat the reset with. Split into two
17
+ single-selector rules, each declaring its own marker type, rather
18
+ than the old single comma-joined rule ( .crisp-rte-body ul, &
19
+ .crisp-rte-body ol ) the issue flagged as malformed.
20
+ #611: padding-inline-start re-measured live once CRUD on the
21
+ measurement workspace was allowed (a "zz-parity" note with a
22
+ bulleted list, a nested bulleted list, and a numbered list) --
23
+ Attio's own <ul>/<ol> measures 36px (getComputedStyle,
14
24
  ~36.1353px), not the 20px placeholder #575 shipped with no real
15
- content to check against. 36px isn't in tokens/scale.ts (steps stop at 24px, jump to 32px) and is a single component-intrinsic value, so it stays a raw px per AUTHORING.md's golden rule 4b
25
+ content to check against. 36px isn't in tokens/scale.ts (steps
26
+ stop at 24px, jump to 32px) and is a single component-intrinsic
27
+ value, so it stays a raw px per AUTHORING.md's golden rule 4b
16
28
  rather than being rounded to an existing token or added to the
17
29
  shared scale. Marker colour (currentColor via the already-measured
18
- fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) == #101112 exactly) and the ~4px li-to-li gap (the existing li margin-top rule below) were re-checked at the same time and already matched -- only the padding was wrong. Attio doesn't vary
30
+ fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) ==
31
+ #101112 exactly) and the ~4px li-to-li gap (the existing li
32
+ margin-top rule below) were re-checked at the same time and
33
+ already matched -- only the padding was wrong. Attio doesn't vary
19
34
  marker type for a nested list either (nested <ul> is disc too,
20
35
  not circle), which this already doesn't attempt. */
21
36
  & .crisp-rte-body ul { list-style-type: disc; padding-inline-start: 36px; }
@@ -26,10 +41,13 @@
26
41
  & .crisp-rte-body a { color: var(--crisp-bg-brand-solid); text-decoration: underline; text-underline-offset: 2px; }
27
42
  & .crisp-rte-body strong { font-weight: var(--crisp-weight-semibold); }
28
43
  & .crisp-rte-body img { display: block; max-width: 100%; border-radius: var(--crisp-radius-md); }
29
- /* Not measured against Attio (#428) — nothing in a read-only pass over app.attio.com had a live @mention rendered to read computed styles from, and typing one to create one is off-limits there. Reused verbatim from the one measured "brand" tag/chip this repo already has (RecordsTable/MultiSelect's [data-tone="brand"]) rather than
44
+ /* Not measured against Attio (#428) — nothing in a read-only pass over
45
+ app.attio.com had a live @mention rendered to read computed styles
46
+ from, and typing one to create one is off-limits there. Reused
47
+ verbatim from the one measured "brand" tag/chip this repo already
48
+ has (RecordsTable/MultiSelect's [data-tone="brand"]) rather than
30
49
  inventing a new color or shape. */
31
50
  & .crisp-rte-mention { display: inline; border-radius: var(--crisp-radius-chip); padding: 0 var(--crisp-space-1); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); font-weight: var(--crisp-weight-medium); cursor: default; }
32
-
33
51
  & .crisp-rte-toolbar { position: fixed; z-index: 70; display: inline-flex; align-items: center; gap: 2px; padding: 2px; border-radius: 10px; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, -100%); opacity: 1; transition: opacity 0.1s ease; }
34
52
  & .crisp-rte-toolbar { @starting-style { opacity: 0; } }
35
53
  & .crisp-rte-tool { display: inline-flex; align-items: center; justify-content: center; gap: var(--crisp-space-1); min-width: 30px; height: 28px; padding: 0 7px; margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: background-color .1s; }
@@ -37,13 +55,11 @@
37
55
  & .crisp-rte-tool:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
38
56
  & .crisp-rte-tool[data-active], & .crisp-rte-tool[aria-expanded="true"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 12%, transparent); color: var(--crisp-bg-brand-solid); }
39
57
  & .crisp-rte-tool-sep { width: 1px; height: 16px; margin: 0 2px; background: var(--crisp-border-subtle); }
40
-
41
58
  & .crisp-rte-swatchpanel { position: fixed; z-index: 71; display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--crisp-space-1); width: 168px; padding: var(--crisp-space-1-5); border-radius: var(--crisp-radius-lg); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, var(--crisp-space-1-5)); opacity: 1; transition: opacity 0.1s ease; }
42
59
  & .crisp-rte-swatchpanel { @starting-style { opacity: 0; } }
43
60
  & .crisp-rte-swatch { width: 28px; height: 28px; padding: 0; margin: 0; border: none; border-radius: 50%; background: none; font-family: inherit; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); cursor: pointer; }
44
61
  & .crisp-rte-swatch--none { background: var(--crisp-bg-surface); position: relative; }
45
62
  & .crisp-rte-swatch--none::after { content: ""; position: absolute; inset: 6px; border-top: 1.5px solid color-mix(in srgb, var(--crisp-fg-primary) 40%, transparent); transform: rotate(-45deg); }
46
-
47
63
  & .crisp-rte-blockmenu { position: fixed; z-index: 71; box-sizing: border-box; width: 356px; padding: 0; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transition: opacity 0.1s ease; }
48
64
  & .crisp-rte-blockmenu { @starting-style { opacity: 0; } }
49
65
  & .crisp-rte-blockmenu-search { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-2-5) var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
@@ -10,13 +10,28 @@
10
10
  & .crisp-rte-body h1 { font-size: var(--crisp-text-xl); line-height: 28px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.3px; margin-top: var(--crisp-space-4); }
11
11
  & .crisp-rte-body h2 { font-size: 17px; line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; margin-top: var(--crisp-space-3); }
12
12
  & .crisp-rte-body h3 { font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-semibold); margin-top: var(--crisp-space-2-5); }
13
- /* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped ul, ol { list-style: none }
14
- , specificity 0,0,1) was winning every list marker outright -- this rule set padding but never declared list-style-type, so there was no higher-specificity value (this selector is 0,1,1) to beat the reset with. Split into two single-selector rules, each declaring its own marker type, rather than the old single comma-joined rule ( .crisp-rte-body ul, & .crisp-rte-body ol ) the issue flagged as malformed. #611: padding-inline-start re-measured live once CRUD on the measurement workspace was allowed (a "zz-parity" note with a bulleted list, a nested bulleted list, and a numbered list) -- Attio's own <ul>/<ol> measures 36px (getComputedStyle,
13
+ /* #575: a consumer's CSS reset (e.g. Tailwind preflight's un-scoped
14
+ ul, ol { list-style: none }, specificity 0,0,1) was winning every
15
+ list marker outright -- this rule set padding but never declared
16
+ list-style-type, so there was no higher-specificity value (this
17
+ selector is 0,1,1) to beat the reset with. Split into two
18
+ single-selector rules, each declaring its own marker type, rather
19
+ than the old single comma-joined rule ( .crisp-rte-body ul, &
20
+ .crisp-rte-body ol ) the issue flagged as malformed.
21
+ #611: padding-inline-start re-measured live once CRUD on the
22
+ measurement workspace was allowed (a "zz-parity" note with a
23
+ bulleted list, a nested bulleted list, and a numbered list) --
24
+ Attio's own <ul>/<ol> measures 36px (getComputedStyle,
15
25
  ~36.1353px), not the 20px placeholder #575 shipped with no real
16
- content to check against. 36px isn't in tokens/scale.ts (steps stop at 24px, jump to 32px) and is a single component-intrinsic value, so it stays a raw px per AUTHORING.md's golden rule 4b
26
+ content to check against. 36px isn't in tokens/scale.ts (steps
27
+ stop at 24px, jump to 32px) and is a single component-intrinsic
28
+ value, so it stays a raw px per AUTHORING.md's golden rule 4b
17
29
  rather than being rounded to an existing token or added to the
18
30
  shared scale. Marker colour (currentColor via the already-measured
19
- fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) == #101112 exactly) and the ~4px li-to-li gap (the existing li margin-top rule below) were re-checked at the same time and already matched -- only the padding was wrong. Attio doesn't vary
31
+ fgPrimary, confirmed to equal Attio's measured rgb(16,17,18) ==
32
+ #101112 exactly) and the ~4px li-to-li gap (the existing li
33
+ margin-top rule below) were re-checked at the same time and
34
+ already matched -- only the padding was wrong. Attio doesn't vary
20
35
  marker type for a nested list either (nested <ul> is disc too,
21
36
  not circle), which this already doesn't attempt. */
22
37
  & .crisp-rte-body ul { list-style-type: disc; padding-inline-start: 36px; }
@@ -27,10 +42,13 @@
27
42
  & .crisp-rte-body a { color: var(--crisp-bg-brand-solid); text-decoration: underline; text-underline-offset: 2px; }
28
43
  & .crisp-rte-body strong { font-weight: var(--crisp-weight-semibold); }
29
44
  & .crisp-rte-body img { display: block; max-width: 100%; border-radius: var(--crisp-radius-md); }
30
- /* Not measured against Attio (#428) — nothing in a read-only pass over app.attio.com had a live @mention rendered to read computed styles from, and typing one to create one is off-limits there. Reused verbatim from the one measured "brand" tag/chip this repo already has (RecordsTable/MultiSelect's [data-tone="brand"]) rather than
45
+ /* Not measured against Attio (#428) — nothing in a read-only pass over
46
+ app.attio.com had a live @mention rendered to read computed styles
47
+ from, and typing one to create one is off-limits there. Reused
48
+ verbatim from the one measured "brand" tag/chip this repo already
49
+ has (RecordsTable/MultiSelect's [data-tone="brand"]) rather than
31
50
  inventing a new color or shape. */
32
51
  & .crisp-rte-mention { display: inline; border-radius: var(--crisp-radius-chip); padding: 0 var(--crisp-space-1); background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); font-weight: var(--crisp-weight-medium); cursor: default; }
33
-
34
52
  & .crisp-rte-toolbar { position: fixed; z-index: 70; display: inline-flex; align-items: center; gap: 2px; padding: 2px; border-radius: 10px; background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, -100%); opacity: 1; transition: opacity 0.1s ease; }
35
53
  & .crisp-rte-toolbar { @starting-style { opacity: 0; } }
36
54
  & .crisp-rte-tool { display: inline-flex; align-items: center; justify-content: center; gap: var(--crisp-space-1); min-width: 30px; height: 28px; padding: 0 7px; margin: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); cursor: pointer; transition: background-color .1s; }
@@ -38,13 +56,11 @@
38
56
  & .crisp-rte-tool:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: var(--crisp-fg-primary); }
39
57
  & .crisp-rte-tool[data-active], & .crisp-rte-tool[aria-expanded="true"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 12%, transparent); color: var(--crisp-bg-brand-solid); }
40
58
  & .crisp-rte-tool-sep { width: 1px; height: 16px; margin: 0 2px; background: var(--crisp-border-subtle); }
41
-
42
59
  & .crisp-rte-swatchpanel { position: fixed; z-index: 71; display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--crisp-space-1); width: 168px; padding: var(--crisp-space-1-5); border-radius: var(--crisp-radius-lg); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); transform: translate(-50%, var(--crisp-space-1-5)); opacity: 1; transition: opacity 0.1s ease; }
43
60
  & .crisp-rte-swatchpanel { @starting-style { opacity: 0; } }
44
61
  & .crisp-rte-swatch { width: 28px; height: 28px; padding: 0; margin: 0; border: none; border-radius: 50%; background: none; font-family: inherit; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 10%, transparent); cursor: pointer; }
45
62
  & .crisp-rte-swatch--none { background: var(--crisp-bg-surface); position: relative; }
46
63
  & .crisp-rte-swatch--none::after { content: ""; position: absolute; inset: 6px; border-top: 1.5px solid color-mix(in srgb, var(--crisp-fg-primary) 40%, transparent); transform: rotate(-45deg); }
47
-
48
64
  & .crisp-rte-blockmenu { position: fixed; z-index: 71; box-sizing: border-box; width: 356px; padding: 0; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); opacity: 1; transition: opacity 0.1s ease; }
49
65
  & .crisp-rte-blockmenu { @starting-style { opacity: 0; } }
50
66
  & .crisp-rte-blockmenu-search { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-2-5) var(--crisp-space-3); border-bottom: 1px solid var(--crisp-border-subtle); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); }
@@ -74,9 +74,16 @@
74
74
 
75
75
  .crisp-savedviews {
76
76
  position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* crisp/#772 follow-up, re-measured live 2026-09-25 in the trigger's
77
- actual position (Attio's real view bar, next to View settings -- fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255) exact) with elevation.field's 3-layer shadow, the same raised
77
+ actual position (Attio's real view bar, next to View settings --
78
+ fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255)
79
+ exact) with elevation.field's 3-layer shadow, the same raised
78
80
  chrome View settings and Import/Export both carry
79
- (tabletoolbar.recipe.ts's own --raised, not reused here directly since this is a separate recipe/component, but the identical measured values). Supersedes the original #555 measurement (rgb(246,247,247), reused as bgRaised -- a flat grey fill with no shadow at all), which was wrong: this trigger was never re-checked once it moved into its real view-bar position. */
81
+ (tabletoolbar.recipe.ts's own --raised, not reused here directly
82
+ since this is a separate recipe/component, but the identical measured
83
+ values). Supersedes the original #555 measurement (rgb(246,247,247),
84
+ reused as bgRaised -- a flat grey fill with no shadow at all), which
85
+ was wrong: this trigger was never re-checked once it moved into its
86
+ real view-bar position. */
80
87
  & .crisp-savedviews-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: var(--crisp-space-1) var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-md); 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; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); cursor: pointer; white-space: nowrap; transition: background-color .12s ease; }
81
88
  & .crisp-savedviews-trigger:hover, & .crisp-savedviews-trigger[data-open] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
82
89
  & .crisp-savedviews-trigger-icon { flex-shrink: 0; display: inline-flex; width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
@@ -75,9 +75,16 @@
75
75
 
76
76
  .crisp-savedviews {
77
77
  position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; /* crisp/#772 follow-up, re-measured live 2026-09-25 in the trigger's
78
- actual position (Attio's real view bar, next to View settings -- fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255) exact) with elevation.field's 3-layer shadow, the same raised
78
+ actual position (Attio's real view bar, next to View settings --
79
+ fixed there in #766/#768/#778): white (bgSurface, rgb(255,255,255)
80
+ exact) with elevation.field's 3-layer shadow, the same raised
79
81
  chrome View settings and Import/Export both carry
80
- (tabletoolbar.recipe.ts's own --raised, not reused here directly since this is a separate recipe/component, but the identical measured values). Supersedes the original #555 measurement (rgb(246,247,247), reused as bgRaised -- a flat grey fill with no shadow at all), which was wrong: this trigger was never re-checked once it moved into its real view-bar position. */
82
+ (tabletoolbar.recipe.ts's own --raised, not reused here directly
83
+ since this is a separate recipe/component, but the identical measured
84
+ values). Supersedes the original #555 measurement (rgb(246,247,247),
85
+ reused as bgRaised -- a flat grey fill with no shadow at all), which
86
+ was wrong: this trigger was never re-checked once it moved into its
87
+ real view-bar position. */
81
88
  & .crisp-savedviews-trigger { box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); height: var(--crisp-size-row); margin: 0; padding: var(--crisp-space-1) var(--crisp-space-1-5); border: none; border-radius: var(--crisp-radius-md); 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; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); cursor: pointer; white-space: nowrap; transition: background-color .12s ease; }
82
89
  & .crisp-savedviews-trigger:hover, & .crisp-savedviews-trigger[data-open] { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, var(--crisp-bg-surface)); }
83
90
  & .crisp-savedviews-trigger-icon { flex-shrink: 0; display: inline-flex; width: var(--crisp-size-icon); height: var(--crisp-size-icon); }
package/dist/select.css CHANGED
@@ -27,6 +27,20 @@
27
27
  .crisp-select-search svg { flex-shrink: 0; }
28
28
  .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
29
29
  .crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
30
+ /* select.yaml's own divider slot (marginX x4, height 1px, colour
31
+ stroke.neutral-muted -- described upstream as "the line marking a
32
+ boundary between semantic units: between sections, between content
33
+ and an action area, between a header and a body" -- exactly the
34
+ search-field/option-list boundary crisp#904's review flagged as
35
+ reading too tight). Not the general-purpose separator #867 declined
36
+ to build (nothing groups options with one) -- scoped to this one
37
+ specific header/body seam, which now exists because searchable
38
+ does. Sits as an ordinary flex child, so the listbox's own 8px gap
39
+ still applies on both sides of it -- total visual seam is
40
+ gap+1px+gap (17px), deliberately more than the 8px between two
41
+ plain option rows, so it reads as a section break, not a wider list
42
+ gap. */
43
+ .crisp-select-divider { flex-shrink: 0; height: 1px; margin-inline: var(--crisp-space-4); background: var(--crisp-stroke-select-divider); }
30
44
  .crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
31
45
  /* select.yaml's groupLabel -- font-size/line-height/weight are the same
32
46
  across sizes, only paddingY differs (medium 8px, large 10px). */
@@ -56,21 +70,27 @@
56
70
  .crisp-select {
57
71
  position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
58
72
  & .crisp-select-trigger { box-sizing: border-box; display: inline-flex; align-items: center; width: 100%; min-width: 0; margin: 0; border: 1px solid var(--crisp-stroke-select-trigger); background: transparent; cursor: pointer; font-family: inherit; color: var(--crisp-fg-select-neutral); transition: background-color .15s cubic-bezier(.35,0,.35,1), border-color .1s cubic-bezier(.35,0,.35,1), border-width .1s cubic-bezier(.35,0,.35,1); }
59
- /* seed defines no hover state for this trigger -- only pressed, invalid, disabled and readonly. The scale-down is scoped to the CONTENT (seed's scaleScope: content), not the button itself, so the border
60
- never moves. */
61
- /* Only the value scales, not the chevron: the chevron's own transform is its open/close rotation, and a scale would fight it for one shared CSS property when both are true at once (pressing while open). */
73
+ /* seed defines no hover state for this trigger -- only pressed, invalid,
74
+ disabled and readonly. The scale-down is scoped to the CONTENT
75
+ (seed's scaleScope: content), not the button itself, so the border
76
+ never moves. */ /* Only the value scales, not the chevron: the chevron's own transform is
77
+ its open/close rotation, and a scale would fight it for one shared
78
+ CSS property when both are true at once (pressing while open). */
62
79
  & .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) { background: var(--crisp-bg-select-pressed); }
63
80
  & .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) .crisp-select-value { transform: scale(0.98); }
64
81
  & .crisp-select-trigger:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
65
82
  & .crisp-select-trigger:disabled { background: var(--crisp-bg-select-disabled); cursor: not-allowed; }
66
83
  & .crisp-select-trigger:disabled .crisp-select-value, & .crisp-select-trigger:disabled .crisp-select-placeholder, & .crisp-select-trigger:disabled .crisp-select-chevron { color: var(--crisp-fg-disabled); }
67
- /* readonly: same fill as disabled, but the value/placeholder text stays normal ink -- it reads as "answered and locked", not "answered and
84
+ /* readonly: same fill as disabled, but the value/placeholder text stays
85
+ normal ink -- it reads as "answered and locked", not "answered and
68
86
  greyed out" (select-trigger.yaml's readonly state only overrides
69
87
  root.color; value/placeholder keep their enabled colours). */
70
88
  & .crisp-select-trigger[aria-readonly="true"] { background: var(--crisp-bg-select-disabled); cursor: default; }
71
89
  & .crisp-select-value { flex: 1; min-width: 0; display: inline-flex; align-items: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; transition: transform .15s cubic-bezier(0,0,.15,1); }
72
90
  & .crisp-select-placeholder { color: var(--crisp-fg-select-placeholder); }
73
- /* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing" curve. Overridden to 150ms on open (openRotateDuration) below -- same curve both ways, only the duration differs. */
91
+ /* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing"
92
+ curve. Overridden to 150ms on open (openRotateDuration) below --
93
+ same curve both ways, only the duration differs. */
74
94
  & .crisp-select-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
75
95
  & .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); transition-duration: .15s; }
76
96
  }
@@ -28,6 +28,20 @@
28
28
  .crisp-select-search svg { flex-shrink: 0; }
29
29
  .crisp-select-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; color: var(--crisp-fg-select-neutral); }
30
30
  .crisp-select-search input::placeholder { color: var(--crisp-fg-select-placeholder); }
31
+ /* select.yaml's own divider slot (marginX x4, height 1px, colour
32
+ stroke.neutral-muted -- described upstream as "the line marking a
33
+ boundary between semantic units: between sections, between content
34
+ and an action area, between a header and a body" -- exactly the
35
+ search-field/option-list boundary crisp#904's review flagged as
36
+ reading too tight). Not the general-purpose separator #867 declined
37
+ to build (nothing groups options with one) -- scoped to this one
38
+ specific header/body seam, which now exists because searchable
39
+ does. Sits as an ordinary flex child, so the listbox's own 8px gap
40
+ still applies on both sides of it -- total visual seam is
41
+ gap+1px+gap (17px), deliberately more than the 8px between two
42
+ plain option rows, so it reads as a section break, not a wider list
43
+ gap. */
44
+ .crisp-select-divider { flex-shrink: 0; height: 1px; margin-inline: var(--crisp-space-4); background: var(--crisp-stroke-select-divider); }
31
45
  .crisp-select-empty { padding: var(--crisp-space-3) var(--crisp-space-4); text-align: center; font-size: var(--crisp-text-md); color: var(--crisp-fg-neutral-subtle); }
32
46
  /* select.yaml's groupLabel -- font-size/line-height/weight are the same
33
47
  across sizes, only paddingY differs (medium 8px, large 10px). */
@@ -57,21 +71,27 @@
57
71
  .crisp-select {
58
72
  position: relative; display: inline-flex; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
59
73
  & .crisp-select-trigger { box-sizing: border-box; display: inline-flex; align-items: center; width: 100%; min-width: 0; margin: 0; border: 1px solid var(--crisp-stroke-select-trigger); background: transparent; cursor: pointer; font-family: inherit; color: var(--crisp-fg-select-neutral); transition: background-color .15s cubic-bezier(.35,0,.35,1), border-color .1s cubic-bezier(.35,0,.35,1), border-width .1s cubic-bezier(.35,0,.35,1); }
60
- /* seed defines no hover state for this trigger -- only pressed, invalid, disabled and readonly. The scale-down is scoped to the CONTENT (seed's scaleScope: content), not the button itself, so the border
61
- never moves. */
62
- /* Only the value scales, not the chevron: the chevron's own transform is its open/close rotation, and a scale would fight it for one shared CSS property when both are true at once (pressing while open). */
74
+ /* seed defines no hover state for this trigger -- only pressed, invalid,
75
+ disabled and readonly. The scale-down is scoped to the CONTENT
76
+ (seed's scaleScope: content), not the button itself, so the border
77
+ never moves. */ /* Only the value scales, not the chevron: the chevron's own transform is
78
+ its open/close rotation, and a scale would fight it for one shared
79
+ CSS property when both are true at once (pressing while open). */
63
80
  & .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) { background: var(--crisp-bg-select-pressed); }
64
81
  & .crisp-select-trigger:active:not(:disabled):not([aria-readonly="true"]) .crisp-select-value { transform: scale(0.98); }
65
82
  & .crisp-select-trigger:focus-visible { outline: 2px solid var(--crisp-stroke-focus-ring); outline-offset: -2px; }
66
83
  & .crisp-select-trigger:disabled { background: var(--crisp-bg-select-disabled); cursor: not-allowed; }
67
84
  & .crisp-select-trigger:disabled .crisp-select-value, & .crisp-select-trigger:disabled .crisp-select-placeholder, & .crisp-select-trigger:disabled .crisp-select-chevron { color: var(--crisp-fg-disabled); }
68
- /* readonly: same fill as disabled, but the value/placeholder text stays normal ink -- it reads as "answered and locked", not "answered and
85
+ /* readonly: same fill as disabled, but the value/placeholder text stays
86
+ normal ink -- it reads as "answered and locked", not "answered and
69
87
  greyed out" (select-trigger.yaml's readonly state only overrides
70
88
  root.color; value/placeholder keep their enabled colours). */
71
89
  & .crisp-select-trigger[aria-readonly="true"] { background: var(--crisp-bg-select-disabled); cursor: default; }
72
90
  & .crisp-select-value { flex: 1; min-width: 0; display: inline-flex; align-items: center; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: start; transition: transform .15s cubic-bezier(0,0,.15,1); }
73
91
  & .crisp-select-placeholder { color: var(--crisp-fg-select-placeholder); }
74
- /* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing" curve. Overridden to 150ms on open (openRotateDuration) below -- same curve both ways, only the duration differs. */
92
+ /* closeRotateDuration/closeRotateTimingFunction: 100ms, seed's "easing"
93
+ curve. Overridden to 150ms on open (openRotateDuration) below --
94
+ same curve both ways, only the duration differs. */
75
95
  & .crisp-select-chevron { flex-shrink: 0; color: var(--crisp-fg-neutral-muted); transition: transform .1s cubic-bezier(.35,0,.35,1); }
76
96
  & .crisp-select-trigger[data-open] .crisp-select-chevron { transform: rotate(180deg); transition-duration: .15s; }
77
97
  }
@@ -5,14 +5,14 @@
5
5
  & .crisp-settingsshell-back svg { color: var(--crisp-fg-muted); }
6
6
  & .crisp-settingsshell-back:hover svg { color: var(--crisp-fg-primary); }
7
7
  & .crisp-settingsshell-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 32px; margin-bottom: var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-muted); }
8
- /* The field box owns the ring, so focus has to move it -- the inner input kills its own outline. Measured live: a focused field's
8
+ /* The field box owns the ring, so focus has to move it -- the inner
9
+ input kills its own outline. Measured live: a focused field's
9
10
  input carries box-shadow: none while its wrapper carries
10
11
  inset 0 0 0 1px #266df0. */
11
12
  & .crisp-settingsshell-search:focus-within { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
12
13
  & .crisp-settingsshell-search svg { flex-shrink: 0; }
13
14
  & .crisp-settingsshell-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
14
15
  & .crisp-settingsshell-search input::placeholder { color: var(--crisp-fg-muted); }
15
-
16
16
  & .crisp-settingsshell-groups { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--crisp-space-2-5); }
17
17
  & .crisp-settingsshell-group { display: flex; flex-direction: column; gap: 1px; }
18
18
  & .crisp-settingsshell-group-label { padding: var(--crisp-space-1) var(--crisp-space-2); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -23,7 +23,6 @@
23
23
  & .crisp-settingsshell-item[data-active] { background: var(--crisp-bg-raised); font-weight: var(--crisp-weight-medium); }
24
24
  & .crisp-settingsshell-item[data-active] svg { color: var(--crisp-fg-primary); }
25
25
  & .crisp-settingsshell-empty { padding: var(--crisp-space-3) var(--crisp-space-2); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
26
-
27
26
  & .crisp-settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--crisp-space-6) var(--crisp-space-8); }
28
27
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
29
28
  }
@@ -6,14 +6,14 @@
6
6
  & .crisp-settingsshell-back svg { color: var(--crisp-fg-muted); }
7
7
  & .crisp-settingsshell-back:hover svg { color: var(--crisp-fg-primary); }
8
8
  & .crisp-settingsshell-search { display: flex; align-items: center; gap: var(--crisp-space-2); height: 32px; margin-bottom: var(--crisp-space-2); padding: 0 var(--crisp-space-2-5); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-default); color: var(--crisp-fg-muted); }
9
- /* The field box owns the ring, so focus has to move it -- the inner input kills its own outline. Measured live: a focused field's
9
+ /* The field box owns the ring, so focus has to move it -- the inner
10
+ input kills its own outline. Measured live: a focused field's
10
11
  input carries box-shadow: none while its wrapper carries
11
12
  inset 0 0 0 1px #266df0. */
12
13
  & .crisp-settingsshell-search:focus-within { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
13
14
  & .crisp-settingsshell-search svg { flex-shrink: 0; }
14
15
  & .crisp-settingsshell-search input { flex: 1; min-width: 0; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
15
16
  & .crisp-settingsshell-search input::placeholder { color: var(--crisp-fg-muted); }
16
-
17
17
  & .crisp-settingsshell-groups { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: var(--crisp-space-2-5); }
18
18
  & .crisp-settingsshell-group { display: flex; flex-direction: column; gap: 1px; }
19
19
  & .crisp-settingsshell-group-label { padding: var(--crisp-space-1) var(--crisp-space-2); font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -24,7 +24,6 @@
24
24
  & .crisp-settingsshell-item[data-active] { background: var(--crisp-bg-raised); font-weight: var(--crisp-weight-medium); }
25
25
  & .crisp-settingsshell-item[data-active] svg { color: var(--crisp-fg-primary); }
26
26
  & .crisp-settingsshell-empty { padding: var(--crisp-space-3) var(--crisp-space-2); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
27
-
28
27
  & .crisp-settingsshell-content { flex: 1; min-width: 0; min-height: 0; overflow-y: auto; padding: var(--crisp-space-6) var(--crisp-space-8); }
29
28
  [dir="rtl"] & [data-rtl-flip] { transform: scaleX(-1); }
30
29
  }
package/dist/slider.css CHANGED
@@ -1,40 +1,19 @@
1
1
  .crisp-slider {
2
- display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a thumb's name — read, never drawn */
3
- & .crisp-slider-thumblabel {
4
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
5
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
6
- }
2
+ display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a
3
+ thumb's name — read, never drawn */
4
+ & .crisp-slider-thumblabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
7
5
  & .crisp-slider-control { position: relative; height: 26px; display: flex; align-items: center; }
8
-
9
- & .crisp-slider-track {
10
- position: relative; flex-grow: 1; height: var(--crisp-space-1);
11
- border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak);
12
- overflow: hidden;
13
- }
14
-
6
+ & .crisp-slider-track { position: relative; flex-grow: 1; height: var(--crisp-space-1); border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak); overflow: hidden; }
15
7
  & .crisp-slider-range { position: absolute; height: 100%; background: var(--crisp-bg-brand-solid); }
16
8
  & .crisp-slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
17
9
  & .crisp-slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
18
-
19
- & .crisp-slider-thumb {
20
- position: absolute; top: 50%;
21
- width: var(--crisp-space-5); height: var(--crisp-space-5);
22
- transform: translate(-50%, -50%);
23
- border: none; background: none; padding: 0;
24
- }
10
+ & .crisp-slider-thumb { position: absolute; top: 50%; width: var(--crisp-space-5); height: var(--crisp-space-5); transform: translate(-50%, -50%); border: none; background: none; padding: 0; }
25
11
  & .crisp-slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
26
12
  & .crisp-slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
27
- & .crisp-slider-thumb::after {
28
- content: ""; position: absolute; inset: 0;
29
- border-radius: var(--crisp-radius-full); background: #fff; 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);
30
- outline: 2px solid transparent; outline-offset: 2px;
31
- transition: transform .2s ease, outline-color .2s ease;
32
- cursor: grab;
33
- }
13
+ & .crisp-slider-thumb::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-full); background: #fff; 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); outline: 2px solid transparent; outline-offset: 2px; transition: transform .2s ease, outline-color .2s ease; cursor: grab; }
34
14
  & .crisp-slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
35
15
  & .crisp-slider-thumb:focus { outline: none; }
36
16
  & .crisp-slider-thumb:focus-visible::after { outline-color: var(--crisp-stroke-focus-ring); }
37
-
38
17
  &[data-disabled] { cursor: not-allowed; }
39
18
  &[data-disabled] .crisp-slider-range { background: var(--crisp-fg-disabled); }
40
19
  &[data-disabled] .crisp-slider-thumb::after { cursor: not-allowed; }
@@ -1,41 +1,20 @@
1
1
  @layer crisp-components {
2
2
  .crisp-slider {
3
- display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a thumb's name — read, never drawn */
4
- & .crisp-slider-thumblabel {
5
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
6
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
7
- }
3
+ display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a
4
+ thumb's name — read, never drawn */
5
+ & .crisp-slider-thumblabel { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
8
6
  & .crisp-slider-control { position: relative; height: 26px; display: flex; align-items: center; }
9
-
10
- & .crisp-slider-track {
11
- position: relative; flex-grow: 1; height: var(--crisp-space-1);
12
- border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak);
13
- overflow: hidden;
14
- }
15
-
7
+ & .crisp-slider-track { position: relative; flex-grow: 1; height: var(--crisp-space-1); border-radius: var(--crisp-radius-full); background: var(--crisp-bg-neutral-weak); overflow: hidden; }
16
8
  & .crisp-slider-range { position: absolute; height: 100%; background: var(--crisp-bg-brand-solid); }
17
9
  & .crisp-slider-range[data-dir="ltr"] { left: var(--range-start); right: var(--range-end); }
18
10
  & .crisp-slider-range[data-dir="rtl"] { right: var(--range-start); left: var(--range-end); }
19
-
20
- & .crisp-slider-thumb {
21
- position: absolute; top: 50%;
22
- width: var(--crisp-space-5); height: var(--crisp-space-5);
23
- transform: translate(-50%, -50%);
24
- border: none; background: none; padding: 0;
25
- }
11
+ & .crisp-slider-thumb { position: absolute; top: 50%; width: var(--crisp-space-5); height: var(--crisp-space-5); transform: translate(-50%, -50%); border: none; background: none; padding: 0; }
26
12
  & .crisp-slider-thumb[data-dir="ltr"] { left: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
27
13
  & .crisp-slider-thumb[data-dir="rtl"] { right: calc(var(--thumb-position) * 1% + var(--thumb-offset)); }
28
- & .crisp-slider-thumb::after {
29
- content: ""; position: absolute; inset: 0;
30
- border-radius: var(--crisp-radius-full); background: #fff; 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);
31
- outline: 2px solid transparent; outline-offset: 2px;
32
- transition: transform .2s ease, outline-color .2s ease;
33
- cursor: grab;
34
- }
14
+ & .crisp-slider-thumb::after { content: ""; position: absolute; inset: 0; border-radius: var(--crisp-radius-full); background: #fff; 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); outline: 2px solid transparent; outline-offset: 2px; transition: transform .2s ease, outline-color .2s ease; cursor: grab; }
35
15
  & .crisp-slider-thumb[data-thumb-dragging]::after { transform: scale(1.2); cursor: grabbing; }
36
16
  & .crisp-slider-thumb:focus { outline: none; }
37
17
  & .crisp-slider-thumb:focus-visible::after { outline-color: var(--crisp-stroke-focus-ring); }
38
-
39
18
  &[data-disabled] { cursor: not-allowed; }
40
19
  &[data-disabled] .crisp-slider-range { background: var(--crisp-fg-disabled); }
41
20
  &[data-disabled] .crisp-slider-thumb::after { cursor: not-allowed; }
@@ -0,0 +1,24 @@
1
+ .crisp-snackbar {
2
+ & .crisp-snackbar-region { position: fixed; z-index: 80; inset-inline: 0; bottom: 0; display: flex; justify-content: center; padding: var(--crisp-space-2); /* snackbar.yaml:95-96 region.paddingX/paddingY = $dimension.x2 (8px) */ pointer-events: none; }
3
+ & .crisp-snackbar { pointer-events: auto; box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2-5); /* snackbar.yaml:116 content.gap = $dimension.x2_5 (10px), reused as the icon+message-to-action gap */ min-height: 44px; max-width: 464px; /* snackbar.yaml:102-103 */ width: max-content; padding: var(--crisp-space-2-5); /* snackbar.yaml:104-105 root.paddingX/paddingY = $dimension.x2_5 (10px) */ border-radius: var(--crisp-radius-md); /* snackbar.yaml:101 root.cornerRadius = $radius.r2 (8px) */ background: var(--crisp-bg-neutral-inverted); /* snackbar.yaml:100 root.color = $color.bg.neutral-inverted */ font-family: var(--crisp-font-sans); opacity: 1; transform: scale(1); transition: opacity 150ms cubic-bezier(0,0,.15,1), transform 150ms cubic-bezier(0,0,.15,1); /* snackbar.yaml:108-109 enterDuration/enterTimingFunction = $duration.d3 (150ms) / $timing-function.enter */ @starting-style { opacity: 0; transform: scale(0.8); } /* snackbar.yaml:106-107 enterOpacity/enterScale */ }
4
+ & .crisp-snackbar-content { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
5
+ /* snackbar.yaml:124 prefixIcon.paddingRight = $dimension.x0_5 (2px), used as the icon-to-message gap */
6
+ & .crisp-snackbar-icon { flex-shrink: 0; display: inline-flex; }
7
+ & .crisp-snackbar[data-variant="positive"] .crisp-snackbar-icon { color: var(--crisp-bg-success); }
8
+ /* snackbar.yaml:138-139 variant=positive prefixIcon.color = $color.fg.positive */
9
+ & .crisp-snackbar[data-variant="critical"] .crisp-snackbar-icon { color: var(--crisp-bg-danger); }
10
+ /* snackbar.yaml:142-143 variant=critical prefixIcon.color = $color.fg.critical */
11
+ & .crisp-snackbar-message { flex: 1 1 auto; min-width: 0; color: var(--crisp-fg-on-neutral-inverted); font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-regular); }
12
+ /* snackbar.yaml:117-121: message.color = $color.fg.neutral-inverted, fontSize/lineHeight = $font-size.t4/$line-height.t4 (14px/19px), fontWeight = regular */
13
+ & .crisp-snackbar-action { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 var(--crisp-space-2); margin: -12px calc(-1 * var(--crisp-space-2)); /* snackbar.yaml:126-127 targetPaddingX/targetMinHeight = $dimension.x2 (8px, doubled here as horizontal padding)/44px -- a larger invisible tap target than the pill's own 44px content row, via negative margin so it doesn't grow the pill visually */ border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-on-neutral-inverted); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-bold); /* fontSize/lineHeight = t4/line-height.t4; fontWeight = bold (snackbar.yaml:129-131); colour deviation documented above */ cursor: pointer; transition: transform 150ms cubic-bezier(0,0,.15,1); }
14
+ & .crisp-snackbar-action:active { transform: scale(0.98); }
15
+ /* snackbar.yaml:133-134 pressed.actionButton.scaleScope = self */
16
+ }
17
+
18
+ @media (prefers-reduced-motion: reduce) {
19
+ .crisp-snackbar, .crisp-snackbar * {
20
+ animation-duration: 0.01ms !important;
21
+ animation-iteration-count: 1 !important;
22
+ transition-duration: 0.01ms !important;
23
+ }
24
+ }
@@ -0,0 +1,7 @@
1
+ import type { RecipeFn } from "../core/types";
2
+
3
+ export interface SnackbarVariants {
4
+
5
+ }
6
+
7
+ export declare const snackbarRecipe: RecipeFn<{ }>;
@@ -0,0 +1,26 @@
1
+ @layer crisp-components {
2
+ .crisp-snackbar {
3
+ & .crisp-snackbar-region { position: fixed; z-index: 80; inset-inline: 0; bottom: 0; display: flex; justify-content: center; padding: var(--crisp-space-2); /* snackbar.yaml:95-96 region.paddingX/paddingY = $dimension.x2 (8px) */ pointer-events: none; }
4
+ & .crisp-snackbar { pointer-events: auto; box-sizing: border-box; display: flex; align-items: center; gap: var(--crisp-space-2-5); /* snackbar.yaml:116 content.gap = $dimension.x2_5 (10px), reused as the icon+message-to-action gap */ min-height: 44px; max-width: 464px; /* snackbar.yaml:102-103 */ width: max-content; padding: var(--crisp-space-2-5); /* snackbar.yaml:104-105 root.paddingX/paddingY = $dimension.x2_5 (10px) */ border-radius: var(--crisp-radius-md); /* snackbar.yaml:101 root.cornerRadius = $radius.r2 (8px) */ background: var(--crisp-bg-neutral-inverted); /* snackbar.yaml:100 root.color = $color.bg.neutral-inverted */ font-family: var(--crisp-font-sans); opacity: 1; transform: scale(1); transition: opacity 150ms cubic-bezier(0,0,.15,1), transform 150ms cubic-bezier(0,0,.15,1); /* snackbar.yaml:108-109 enterDuration/enterTimingFunction = $duration.d3 (150ms) / $timing-function.enter */ @starting-style { opacity: 0; transform: scale(0.8); } /* snackbar.yaml:106-107 enterOpacity/enterScale */ }
5
+ & .crisp-snackbar-content { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--crisp-space-0-5); }
6
+ /* snackbar.yaml:124 prefixIcon.paddingRight = $dimension.x0_5 (2px), used as the icon-to-message gap */
7
+ & .crisp-snackbar-icon { flex-shrink: 0; display: inline-flex; }
8
+ & .crisp-snackbar[data-variant="positive"] .crisp-snackbar-icon { color: var(--crisp-bg-success); }
9
+ /* snackbar.yaml:138-139 variant=positive prefixIcon.color = $color.fg.positive */
10
+ & .crisp-snackbar[data-variant="critical"] .crisp-snackbar-icon { color: var(--crisp-bg-danger); }
11
+ /* snackbar.yaml:142-143 variant=critical prefixIcon.color = $color.fg.critical */
12
+ & .crisp-snackbar-message { flex: 1 1 auto; min-width: 0; color: var(--crisp-fg-on-neutral-inverted); font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-regular); }
13
+ /* snackbar.yaml:117-121: message.color = $color.fg.neutral-inverted, fontSize/lineHeight = $font-size.t4/$line-height.t4 (14px/19px), fontWeight = regular */
14
+ & .crisp-snackbar-action { flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 var(--crisp-space-2); margin: -12px calc(-1 * var(--crisp-space-2)); /* snackbar.yaml:126-127 targetPaddingX/targetMinHeight = $dimension.x2 (8px, doubled here as horizontal padding)/44px -- a larger invisible tap target than the pill's own 44px content row, via negative margin so it doesn't grow the pill visually */ border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-on-neutral-inverted); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 19px; font-weight: var(--crisp-weight-bold); /* fontSize/lineHeight = t4/line-height.t4; fontWeight = bold (snackbar.yaml:129-131); colour deviation documented above */ cursor: pointer; transition: transform 150ms cubic-bezier(0,0,.15,1); }
15
+ & .crisp-snackbar-action:active { transform: scale(0.98); }
16
+ /* snackbar.yaml:133-134 pressed.actionButton.scaleScope = self */
17
+ }
18
+
19
+ @media (prefers-reduced-motion: reduce) {
20
+ .crisp-snackbar, .crisp-snackbar * {
21
+ animation-duration: 0.01ms !important;
22
+ animation-iteration-count: 1 !important;
23
+ transition-duration: 0.01ms !important;
24
+ }
25
+ }
26
+ }
package/dist/statcard.css CHANGED
@@ -7,7 +7,9 @@
7
7
  /* caption's own status colour, opt-in via data-tone: not a new measured
8
8
  value — the same fg*Soft tokens Badge's tone already uses (and Badge's
9
9
  own doc comment records why: a dedicated soft-text token, not the
10
- tone's accent colour, is the one that clears AA). No "ok" reading on Badge itself; fgSuccessSoft is Badge's own "success" tone's text colour, reused here under the name a caption's own good-news state
10
+ tone's accent colour, is the one that clears AA). No "ok" reading on
11
+ Badge itself; fgSuccessSoft is Badge's own "success" tone's text
12
+ colour, reused here under the name a caption's own good-news state
11
13
  reads as. */
12
14
  & .crisp-statcard-caption[data-tone="ok"] { color: var(--crisp-fg-success-soft); }
13
15
  & .crisp-statcard-caption[data-tone="warning"] { color: var(--crisp-fg-warning-soft); }