@kerfjs/ui 5.0.0-beta.105 → 5.0.0-beta.107

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 (227) hide show
  1. package/README.md +2 -1
  2. package/ai/application-ui-diagnostic-ids-v1.json +1 -0
  3. package/ai/application-ui-profile.defaults.json +6 -1
  4. package/ai/component-catalog.json +160 -27
  5. package/ai/component-composition-rules.json +20 -2
  6. package/ai/component-composition.d.ts +11 -0
  7. package/ai/component-composition.json +118 -19
  8. package/ai/component-composition.schema.json +32 -0
  9. package/ai/components/README.md +3 -2
  10. package/ai/components/button.md +4 -1
  11. package/ai/components/checkbox-group.md +89 -0
  12. package/ai/components/checkbox.md +3 -2
  13. package/ai/components/color-picker.md +10 -7
  14. package/ai/components/disclosure.md +6 -1
  15. package/ai/components/foundation.md +1 -1
  16. package/ai/components/list-detail-dialog.md +1 -1
  17. package/ai/components/message-composer.md +2 -1
  18. package/ai/components/radio-group.md +4 -3
  19. package/ai/components/split-button.md +5 -2
  20. package/ai/components/surface-scaffold.md +2 -1
  21. package/ai/components/switch.md +1 -1
  22. package/ai/components/text.md +2 -0
  23. package/ai/components/wa-checkbox-group.md +5 -5
  24. package/ai/components/workbench-dialog.md +1 -1
  25. package/ai/public-api-signatures-v1.md +198 -26
  26. package/ai/skill.md +73 -62
  27. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  28. package/dist/browser/checkbox-group.js +5 -0
  29. package/dist/button.d.ts +15 -2
  30. package/dist/button.js +1 -1
  31. package/dist/catalog.js +9 -8
  32. package/dist/catalog.js.map +1 -1
  33. package/dist/checkbox-group.d.ts +70 -0
  34. package/dist/checkbox-group.js +7 -0
  35. package/dist/checkbox-group.js.map +1 -0
  36. package/dist/{chunk-SQ2Q3OQI.js → chunk-2LM3PYHA.js} +2 -2
  37. package/dist/{chunk-SQ2Q3OQI.js.map → chunk-2LM3PYHA.js.map} +1 -1
  38. package/dist/{chunk-HYORKKYP.js → chunk-3VZ6SFD4.js} +1 -1
  39. package/dist/chunk-3VZ6SFD4.js.map +1 -0
  40. package/dist/{chunk-EKBMUXFV.js → chunk-3Z7N2NAZ.js} +141 -54
  41. package/dist/chunk-3Z7N2NAZ.js.map +1 -0
  42. package/dist/{chunk-FKKJHGN5.js → chunk-AZ3WT77F.js} +2 -2
  43. package/dist/{chunk-FKKJHGN5.js.map → chunk-AZ3WT77F.js.map} +1 -1
  44. package/dist/{chunk-FG6U7KQQ.js → chunk-DNWWF6UN.js} +2 -2
  45. package/dist/{chunk-FG6U7KQQ.js.map → chunk-DNWWF6UN.js.map} +1 -1
  46. package/dist/{chunk-C3RLKKFQ.js → chunk-EYDXFOSH.js} +13 -8
  47. package/dist/chunk-EYDXFOSH.js.map +1 -0
  48. package/dist/{chunk-TAHR457X.js → chunk-G4DRH4A5.js} +3 -1
  49. package/dist/chunk-G4DRH4A5.js.map +1 -0
  50. package/dist/{chunk-PE2KPZDW.js → chunk-HDXUHLTQ.js} +7 -2
  51. package/dist/chunk-HDXUHLTQ.js.map +1 -0
  52. package/dist/chunk-HU5IHXCI.js +73 -0
  53. package/dist/chunk-HU5IHXCI.js.map +1 -0
  54. package/dist/{chunk-DF2YKGIX.js → chunk-JCCN3U6X.js} +2 -2
  55. package/dist/{chunk-DF2YKGIX.js.map → chunk-JCCN3U6X.js.map} +1 -1
  56. package/dist/{chunk-GCAK23PU.js → chunk-MVKHSAKE.js} +2 -2
  57. package/dist/{chunk-GCAK23PU.js.map → chunk-MVKHSAKE.js.map} +1 -1
  58. package/dist/{chunk-DDSCVEO5.js → chunk-NLMEDZRM.js} +5 -5
  59. package/dist/{chunk-DDSCVEO5.js.map → chunk-NLMEDZRM.js.map} +1 -1
  60. package/dist/{chunk-ECFCAKWE.js → chunk-NR6O74ST.js} +5 -1
  61. package/dist/chunk-NR6O74ST.js.map +1 -0
  62. package/dist/{chunk-7W3GKMN4.js → chunk-OQP3PFKQ.js} +7 -4
  63. package/dist/chunk-OQP3PFKQ.js.map +1 -0
  64. package/dist/{chunk-WJKHLOP5.js → chunk-TI2GV36S.js} +8 -2
  65. package/dist/chunk-TI2GV36S.js.map +1 -0
  66. package/dist/{chunk-UTCAOOXU.js → chunk-TXRKCGT3.js} +8 -2
  67. package/dist/chunk-TXRKCGT3.js.map +1 -0
  68. package/dist/{chunk-ACUKTVS3.js → chunk-XWNXGFX3.js} +52 -42
  69. package/dist/chunk-XWNXGFX3.js.map +1 -0
  70. package/dist/{chunk-ZXZAECHZ.js → chunk-Z4DS77U2.js} +2 -2
  71. package/dist/{chunk-ZXZAECHZ.js.map → chunk-Z4DS77U2.js.map} +1 -1
  72. package/dist/collapsible-panel.js +2 -2
  73. package/dist/color-picker.d.ts +30 -5
  74. package/dist/color-picker.js +1 -1
  75. package/dist/disclosure.d.ts +13 -4
  76. package/dist/disclosure.js +1 -1
  77. package/dist/disclosure.js.map +1 -1
  78. package/dist/help-tags-register.js +1 -1
  79. package/dist/index.d.ts +2 -1
  80. package/dist/index.js +20 -19
  81. package/dist/list-action-row.js +1 -1
  82. package/dist/list-detail-dialog.d.ts +7 -1
  83. package/dist/list-detail-dialog.js +6 -4
  84. package/dist/list-detail-dialog.js.map +1 -1
  85. package/dist/list-header.d.ts +8 -1
  86. package/dist/list-header.js +1 -1
  87. package/dist/nav-stack.js +1 -1
  88. package/dist/popup-menu-register.js +2 -2
  89. package/dist/popup-menu.d.ts +15 -5
  90. package/dist/popup-menu.js +1 -1
  91. package/dist/select-register.js +3 -3
  92. package/dist/split-button.d.ts +14 -2
  93. package/dist/split-button.js +1 -1
  94. package/dist/split-view.js +1 -1
  95. package/dist/styles/anchored-surface.css +3 -0
  96. package/dist/styles/button.css +29 -0
  97. package/dist/styles/catalog/components/catalog-example.css +55 -18
  98. package/dist/styles/checkbox-group.css +63 -0
  99. package/dist/styles/checkbox.css +7 -6
  100. package/dist/styles/color-picker.css +69 -34
  101. package/dist/styles/components/actions/button/button.css +29 -0
  102. package/dist/styles/components/actions/split-button/split-button.css +51 -5
  103. package/dist/styles/components/collections/framed-list/framed-list.css +4 -0
  104. package/dist/styles/components/collections/list/list.css +6 -0
  105. package/dist/styles/components/collections/list-header/list-header.css +7 -0
  106. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +3 -0
  107. package/dist/styles/components/forms/checkbox/checkbox.css +7 -6
  108. package/dist/styles/components/forms/checkbox-group/checkbox-group.css +63 -0
  109. package/dist/styles/components/forms/color-picker/color-picker.css +69 -34
  110. package/dist/styles/components/forms/radio-group/radio-group.css +7 -5
  111. package/dist/styles/components/forms/select/select.css +6 -2
  112. package/dist/styles/components/forms/switch/switch.css +3 -3
  113. package/dist/styles/components/layout/pane/pane.css +9 -0
  114. package/dist/styles/components/layout/workbench/workbench.css +4 -0
  115. package/dist/styles/components/navigation/nav-stack/nav-stack.css +64 -1
  116. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +1 -0
  117. package/dist/styles/components/surfaces/content-item/content-item.css +30 -0
  118. package/dist/styles/components/surfaces/disclosure/disclosure.css +38 -0
  119. package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +3 -0
  120. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +6 -0
  121. package/dist/styles/components/typography/text/text.css +10 -0
  122. package/dist/styles/content-item.css +30 -0
  123. package/dist/styles/disclosure.css +38 -0
  124. package/dist/styles/foundation.css +21 -0
  125. package/dist/styles/framed-list.css +4 -0
  126. package/dist/styles/list-header.css +7 -0
  127. package/dist/styles/list.css +6 -0
  128. package/dist/styles/nav-stack.css +64 -1
  129. package/dist/styles/pane.css +9 -0
  130. package/dist/styles/radio-group.css +7 -5
  131. package/dist/styles/select.css +6 -2
  132. package/dist/styles/split-button.css +51 -5
  133. package/dist/styles/styles.css +1 -0
  134. package/dist/styles/sunken-panel.css +3 -0
  135. package/dist/styles/surface-scaffold.css +6 -0
  136. package/dist/styles/switch.css +3 -3
  137. package/dist/styles/tab-navigator.css +1 -0
  138. package/dist/styles/text.css +10 -0
  139. package/dist/styles/webawesome.css +45 -9
  140. package/dist/styles/workbench.css +4 -0
  141. package/dist/surface-scaffold.d.ts +7 -1
  142. package/dist/surface-scaffold.js +1 -1
  143. package/dist/wire-color-fields.js +2 -2
  144. package/dist/wire-color-pickers.d.ts +4 -3
  145. package/dist/wire-color-pickers.js +1 -1
  146. package/dist/wire-comboboxes.js +1 -1
  147. package/dist/workbench-dialog.d.ts +11 -2
  148. package/dist/workbench-dialog.js +5 -2
  149. package/dist/workbench-dialog.js.map +1 -1
  150. package/dist/workbench.js +1 -1
  151. package/docs/accessibility.md +40 -1
  152. package/docs/anchored-surface.md +6 -1
  153. package/docs/catalog.md +26 -1
  154. package/docs/color-picker.md +39 -8
  155. package/docs/component-contract.md +33 -2
  156. package/docs/component-selection.md +20 -9
  157. package/docs/design/templates/button/full-width-dark.svg +1 -0
  158. package/docs/design/templates/button/full-width.svg +1 -0
  159. package/docs/design/templates/button-dark.svg +1 -1
  160. package/docs/design/templates/button.svg +1 -1
  161. package/docs/design/templates/checkbox/error-dark.svg +1 -1
  162. package/docs/design/templates/checkbox/error.svg +1 -1
  163. package/docs/design/templates/checkbox/states-dark.svg +1 -1
  164. package/docs/design/templates/checkbox/states.svg +1 -1
  165. package/docs/design/templates/checkbox-dark.svg +1 -1
  166. package/docs/design/templates/checkbox-group/horizontal-dark.svg +1 -0
  167. package/docs/design/templates/checkbox-group/horizontal.svg +1 -0
  168. package/docs/design/templates/checkbox-group/vertical-dark.svg +1 -0
  169. package/docs/design/templates/checkbox-group/vertical.svg +1 -0
  170. package/docs/design/templates/checkbox-group-dark.svg +1 -0
  171. package/docs/design/templates/checkbox-group.svg +1 -0
  172. package/docs/design/templates/checkbox.svg +1 -1
  173. package/docs/design/templates/color-picker/gray-dark.svg +1 -1
  174. package/docs/design/templates/color-picker/gray.svg +1 -1
  175. package/docs/design/templates/color-picker/hsb-dark.svg +1 -0
  176. package/docs/design/templates/color-picker/hsb.svg +1 -0
  177. package/docs/design/templates/color-picker/rgb-dark.svg +1 -1
  178. package/docs/design/templates/color-picker/rgb.svg +1 -1
  179. package/docs/design/templates/color-picker-dark.svg +1 -1
  180. package/docs/design/templates/color-picker.svg +1 -1
  181. package/docs/design/templates/disclosure/embedded-dark.svg +1 -0
  182. package/docs/design/templates/disclosure/embedded.svg +1 -0
  183. package/docs/design/templates/disclosure-dark.svg +1 -1
  184. package/docs/design/templates/disclosure.svg +1 -1
  185. package/docs/design/templates/radio-group/horizontal-dark.svg +1 -1
  186. package/docs/design/templates/radio-group/horizontal.svg +1 -1
  187. package/docs/design/templates/radio-group/vertical-dark.svg +1 -1
  188. package/docs/design/templates/radio-group/vertical.svg +1 -1
  189. package/docs/design/templates/radio-group-dark.svg +1 -1
  190. package/docs/design/templates/radio-group.svg +1 -1
  191. package/docs/design/templates/split-button/full-width-dark.svg +1 -0
  192. package/docs/design/templates/split-button/full-width.svg +1 -0
  193. package/docs/design/templates/split-button/pill-dark.svg +1 -0
  194. package/docs/design/templates/split-button/pill.svg +1 -0
  195. package/docs/design/templates/split-button/states-dark.svg +1 -0
  196. package/docs/design/templates/split-button/states.svg +1 -0
  197. package/docs/design/templates/split-button/tones-dark.svg +1 -0
  198. package/docs/design/templates/split-button/tones.svg +1 -0
  199. package/docs/design/templates/split-button-dark.svg +1 -0
  200. package/docs/design/templates/split-button.svg +1 -0
  201. package/docs/design/templates/switch/states-dark.svg +1 -1
  202. package/docs/design/templates/switch/states.svg +1 -1
  203. package/docs/design/templates/switch-dark.svg +1 -1
  204. package/docs/design/templates/switch.svg +1 -1
  205. package/docs/design/templates.md +10 -3
  206. package/docs/disclosure.md +34 -0
  207. package/docs/list-detail-dialog.md +4 -0
  208. package/docs/nav-stack.md +6 -2
  209. package/docs/surface-scaffold.md +6 -2
  210. package/docs/ui-doctor.md +16 -4
  211. package/docs/webawesome-migration.md +1 -1
  212. package/docs/webawesome-theme.md +48 -16
  213. package/docs/workbench-dialog.md +4 -1
  214. package/docs/writing.md +3 -3
  215. package/doctor/copy-capitalization-checks.mjs +10 -7
  216. package/llms.txt +50 -20
  217. package/package.json +7 -1
  218. package/dist/chunk-7W3GKMN4.js.map +0 -1
  219. package/dist/chunk-ACUKTVS3.js.map +0 -1
  220. package/dist/chunk-C3RLKKFQ.js.map +0 -1
  221. package/dist/chunk-ECFCAKWE.js.map +0 -1
  222. package/dist/chunk-EKBMUXFV.js.map +0 -1
  223. package/dist/chunk-HYORKKYP.js.map +0 -1
  224. package/dist/chunk-PE2KPZDW.js.map +0 -1
  225. package/dist/chunk-TAHR457X.js.map +0 -1
  226. package/dist/chunk-UTCAOOXU.js.map +0 -1
  227. package/dist/chunk-WJKHLOP5.js.map +0 -1
@@ -1,8 +1,10 @@
1
- /* ColorPicker: a saturation and brightness area, hue and opacity sliders, a
2
- color-model menu with its tools, channel fields, a hex and opacity row,
3
- then preset and sample swatches. The surface's custom properties
4
- (--_kui-color-picker-h/s/v/a and the opaque color) place the thumbs and
5
- paint the tracks; the wiring updates them while a person drags. */
1
+ /* ColorPicker: a saturation and brightness area, a slider per channel of the
2
+ color model plus an opacity slider, a color-model menu with its tools,
3
+ channel fields, a hex and opacity row, then preset and sample swatches.
4
+ The surface's custom properties (--_kui-color-picker-h/s/v/a and the
5
+ opaque color) place the area thumb and paint the opacity slider; each
6
+ channel slider carries its own track gradient and thumb color inline. The
7
+ wiring updates both while a person drags. */
6
8
  .kui-color-picker {
7
9
  display: grid;
8
10
  width: 100%;
@@ -18,7 +20,18 @@
18
20
  font-size: var(--kui-font-m, 1rem);
19
21
  }
20
22
 
23
+ /* The area and every slider track carry an inner edge halfway to the text
24
+ color, so an area or track as dark (or as light) as the surface behind it
25
+ keeps a visible boundary in either scheme. Every thumb draws a two-tone
26
+ ring, white inside a dark outline, so it keeps a 3:1 boundary over light
27
+ and dark colors alike. */
21
28
  .kui-color-picker__surface {
29
+ --_kui-color-picker-track-edge: color-mix(
30
+ in srgb,
31
+ var(--kui-color-text) 50%,
32
+ transparent
33
+ );
34
+ --_kui-color-picker-thumb-outline: rgb(0 0 0 / 0.6);
22
35
  --_kui-color-picker-checker: repeating-conic-gradient(
23
36
  var(--kui-color-neutral-fill-normal) 0% 25%,
24
37
  var(--kui-color-surface) 0% 50%
@@ -38,6 +51,7 @@
38
51
  background:
39
52
  linear-gradient(to top, #000, transparent),
40
53
  linear-gradient(to right, #fff, hsl(var(--_kui-color-picker-h) 100% 50%));
54
+ box-shadow: inset 0 0 0 1px var(--_kui-color-picker-track-edge);
41
55
  cursor: crosshair;
42
56
  touch-action: none;
43
57
  }
@@ -58,17 +72,28 @@
58
72
  border-radius: 50%;
59
73
  background: var(--_kui-color-picker-color);
60
74
  box-shadow:
61
- 0 0 0 1px rgb(0 0 0 / 0.3),
75
+ 0 0 0 1px var(--_kui-color-picker-thumb-outline),
62
76
  var(--kui-shadow-s);
63
77
  pointer-events: none;
64
78
  translate: -50% -50%;
65
79
  }
66
80
 
67
- /* The hue and opacity sliders: native ranges drawn as 12px tracks with a
68
- round thumb that shows the color at that point. */
69
- .kui-color-picker__hue,
81
+ /* The channel and opacity sliders, one group: native ranges drawn as 12px
82
+ tracks with a round thumb that shows the color at that point. A channel
83
+ slider's inline style carries its track (the colors its channel produces
84
+ while the others hold, or the full rainbow for hue) and its thumb color.
85
+ Every track runs in the writing direction, as the native range does, and
86
+ carries the surface's inner edge. */
87
+ .kui-color-picker__sliders {
88
+ display: grid;
89
+ min-width: 0;
90
+ gap: var(--kui-space-xs, 0.5rem);
91
+ }
92
+
93
+ .kui-color-picker__slider,
70
94
  .kui-color-picker__opacity {
71
95
  --_kui-color-picker-thumb: 1.25rem;
96
+ --_kui-color-picker-track-direction: to right;
72
97
 
73
98
  display: block;
74
99
  width: 100%;
@@ -81,23 +106,22 @@
81
106
  appearance: none;
82
107
  }
83
108
 
84
- .kui-color-picker__hue {
85
- --_kui-color-picker-track: linear-gradient(
86
- to right,
87
- #f00,
88
- #ff0,
89
- #0f0,
90
- #0ff,
91
- #00f,
92
- #f0f,
93
- #f00
94
- );
95
- --_kui-color-picker-thumb-color: hsl(var(--_kui-color-picker-h) 100% 50%);
109
+ .kui-color-picker__slider[hidden] {
110
+ display: none;
111
+ }
112
+
113
+ .kui-color-picker__slider:dir(rtl),
114
+ .kui-color-picker__opacity:dir(rtl) {
115
+ --_kui-color-picker-track-direction: to left;
96
116
  }
97
117
 
98
118
  .kui-color-picker__opacity {
99
119
  --_kui-color-picker-track:
100
- linear-gradient(to right, transparent, var(--_kui-color-picker-color)),
120
+ linear-gradient(
121
+ var(--_kui-color-picker-track-direction),
122
+ transparent,
123
+ var(--_kui-color-picker-color)
124
+ ),
101
125
  var(--_kui-color-picker-checker);
102
126
  --_kui-color-picker-thumb-color: color-mix(
103
127
  in srgb,
@@ -106,23 +130,23 @@
106
130
  );
107
131
  }
108
132
 
109
- .kui-color-picker__hue::-webkit-slider-runnable-track,
133
+ .kui-color-picker__slider::-webkit-slider-runnable-track,
110
134
  .kui-color-picker__opacity::-webkit-slider-runnable-track {
111
135
  height: 0.75rem;
112
136
  border-radius: var(--kui-radius-pill);
113
137
  background: var(--_kui-color-picker-track);
114
- box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
138
+ box-shadow: inset 0 0 0 1px var(--_kui-color-picker-track-edge);
115
139
  }
116
140
 
117
- .kui-color-picker__hue::-moz-range-track,
141
+ .kui-color-picker__slider::-moz-range-track,
118
142
  .kui-color-picker__opacity::-moz-range-track {
119
143
  height: 0.75rem;
120
144
  border-radius: var(--kui-radius-pill);
121
145
  background: var(--_kui-color-picker-track);
122
- box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.1);
146
+ box-shadow: inset 0 0 0 1px var(--_kui-color-picker-track-edge);
123
147
  }
124
148
 
125
- .kui-color-picker__hue::-webkit-slider-thumb,
149
+ .kui-color-picker__slider::-webkit-slider-thumb,
126
150
  .kui-color-picker__opacity::-webkit-slider-thumb {
127
151
  width: var(--_kui-color-picker-thumb);
128
152
  height: var(--_kui-color-picker-thumb);
@@ -132,12 +156,12 @@
132
156
  border-radius: 50%;
133
157
  background: var(--_kui-color-picker-thumb-color);
134
158
  box-shadow:
135
- 0 0 0 1px rgb(0 0 0 / 0.2),
159
+ 0 0 0 1px var(--_kui-color-picker-thumb-outline),
136
160
  var(--kui-shadow-s);
137
161
  appearance: none;
138
162
  }
139
163
 
140
- .kui-color-picker__hue::-moz-range-thumb,
164
+ .kui-color-picker__slider::-moz-range-thumb,
141
165
  .kui-color-picker__opacity::-moz-range-thumb {
142
166
  width: var(--_kui-color-picker-thumb);
143
167
  height: var(--_kui-color-picker-thumb);
@@ -146,22 +170,22 @@
146
170
  border-radius: 50%;
147
171
  background: var(--_kui-color-picker-thumb-color);
148
172
  box-shadow:
149
- 0 0 0 1px rgb(0 0 0 / 0.2),
173
+ 0 0 0 1px var(--_kui-color-picker-thumb-outline),
150
174
  var(--kui-shadow-s);
151
175
  }
152
176
 
153
- .kui-color-picker__hue:focus-visible,
177
+ .kui-color-picker__slider:focus-visible,
154
178
  .kui-color-picker__opacity:focus-visible {
155
179
  outline: none;
156
180
  }
157
181
 
158
- .kui-color-picker__hue:focus-visible::-webkit-slider-thumb,
182
+ .kui-color-picker__slider:focus-visible::-webkit-slider-thumb,
159
183
  .kui-color-picker__opacity:focus-visible::-webkit-slider-thumb {
160
184
  outline: var(--kui-focus-ring);
161
185
  outline-offset: 1px;
162
186
  }
163
187
 
164
- .kui-color-picker__hue:focus-visible::-moz-range-thumb,
188
+ .kui-color-picker__slider:focus-visible::-moz-range-thumb,
165
189
  .kui-color-picker__opacity:focus-visible::-moz-range-thumb {
166
190
  outline: var(--kui-focus-ring);
167
191
  outline-offset: 1px;
@@ -317,10 +341,21 @@
317
341
  cursor: not-allowed;
318
342
  }
319
343
 
344
+ /* Increased contrast draws the area and track edge in the full text color. */
345
+ @media (prefers-contrast: more) {
346
+ .kui-color-picker__surface {
347
+ --_kui-color-picker-track-edge: var(--kui-color-text);
348
+ }
349
+ }
350
+
320
351
  @media (forced-colors: active) {
352
+ .kui-color-picker__surface {
353
+ --_kui-color-picker-track-edge: CanvasText;
354
+ }
355
+
321
356
  .kui-color-picker__area,
322
357
  .kui-color-picker__area-thumb,
323
- .kui-color-picker__hue,
358
+ .kui-color-picker__slider,
324
359
  .kui-color-picker__opacity {
325
360
  forced-color-adjust: none;
326
361
  }
@@ -75,6 +75,18 @@
75
75
  flex-shrink: 0;
76
76
  padding: 0;
77
77
  }
78
+ /* fill: the button spans its parent's available inline width, as a filled
79
+ SplitButton does. The label stays centered and ellipsizes once it no longer
80
+ fits; an icon-only button that fills spans too. */
81
+ .kui-button[data-fill="true"] {
82
+ display: flex;
83
+ width: 100%;
84
+ min-width: 0;
85
+ }
86
+ .kui-button[data-fill="true"] > .kui-button__label {
87
+ overflow: hidden;
88
+ text-overflow: ellipsis;
89
+ }
78
90
  /* A pill: fully round ends (a circle when icon-only). */
79
91
  .kui-button[data-shape="pill"] {
80
92
  border-radius: var(--kui-layout-pill-radius, calc(1px + 1.3125rem));
@@ -197,6 +209,23 @@
197
209
  outline: var(--kui-focus-ring);
198
210
  outline-offset: 1px;
199
211
  }
212
+ /* focusRingInset: inside an ancestor that clips overflow, the ring moves
213
+ inside the box. On a loud fill the ring can share the fill's hue (brand),
214
+ so a surface-colored line runs inside it: the ring then meets the surface
215
+ on both edges, as the outside ring does, whatever the fill. The line is an
216
+ inset shadow from the padding edge (inside the 1px border) to 3px past the
217
+ ring, wide enough to stay solid at a fractional position; a pressed
218
+ toggle's inset ring lies under the focus ring meanwhile. The line paints
219
+ the surface the button sits on: the surface context's opaque color with
220
+ its translucent tint (a sunken or quiet fill) layered over it
221
+ (foundation.css), so it reads as a cut through the fill, not a halo. */
222
+ .kui-button[data-focus-ring-inset="true"]:focus-visible {
223
+ outline-offset: -3px;
224
+ box-shadow:
225
+ inset 0 0 0 5px var(--kui-color-surface-current-tint, transparent),
226
+ inset 0 0 0 5px var(--kui-color-surface-current-region, transparent),
227
+ inset 0 0 0 5px var(--kui-color-surface-current, var(--kui-color-surface));
228
+ }
200
229
  .kui-button:is(:disabled, [aria-disabled="true"]) {
201
230
  cursor: not-allowed;
202
231
  opacity: 0.5;
@@ -1,20 +1,32 @@
1
1
  /* One loud semantic fill split into a primary half and a narrow options
2
2
  trigger, with a hairline divider in the foreground color. Both halves are
3
- native buttons on the shared fill; each brightens on its own hover. */
3
+ native buttons on the shared fill; each brightens on its own hover. The
4
+ outer corners take the shared control radius, or full round ends as a
5
+ pill; the divider seam between the halves stays square. */
4
6
  .kui-split-button {
5
7
  --_kui-split-button-fill: var(--kui-color-brand-fill-loud);
6
8
  --_kui-split-button-on: var(--kui-color-brand-on-loud);
9
+ --_kui-split-button-radius: var(
10
+ --kui-layout-rounded-radius,
11
+ calc(1px + 0.6875rem)
12
+ );
7
13
  display: inline-grid;
8
14
  min-width: 0;
9
15
  min-height: 2.75rem;
10
- overflow: hidden;
11
- border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
16
+ border-radius: var(--_kui-split-button-radius);
12
17
  color: var(--_kui-split-button-on);
13
18
  background: var(--_kui-split-button-fill);
14
19
  grid-template-columns: minmax(0, auto) 2.5rem;
15
20
  font-weight: var(--kui-font-weight-semibold);
16
21
  }
17
22
 
23
+ .kui-split-button[data-shape="pill"] {
24
+ --_kui-split-button-radius: var(
25
+ --kui-layout-pill-radius,
26
+ calc(1px + 1.3125rem)
27
+ );
28
+ }
29
+
18
30
  .kui-split-button[data-tone="neutral"] {
19
31
  --_kui-split-button-fill: var(--kui-color-neutral-fill-loud);
20
32
  --_kui-split-button-on: var(--kui-color-neutral-on-loud);
@@ -50,6 +62,7 @@
50
62
  padding-inline: var(--kui-space-s);
51
63
  border: 0;
52
64
  border-radius: 0;
65
+ appearance: none;
53
66
  color: inherit;
54
67
  background: transparent;
55
68
  cursor: pointer;
@@ -69,11 +82,44 @@
69
82
  background: color-mix(in srgb, currentColor 12%, transparent);
70
83
  }
71
84
 
72
- /* The group clips outer outlines at its rounded corners, so the ring sits
73
- inside each half. */
85
+ /* Each half rounds its outer corners with the group, so its hover fill and
86
+ focus ring follow the rounded or pill end. The group does not clip, so
87
+ these radii are what keep a half's fill inside the group's corners. */
88
+ .kui-split-button > .kui-split-button__primary {
89
+ border-start-start-radius: var(--_kui-split-button-radius);
90
+ border-end-start-radius: var(--_kui-split-button-radius);
91
+ }
92
+
93
+ .kui-split-button > .kui-split-button__options {
94
+ border-start-end-radius: var(--_kui-split-button-radius);
95
+ border-end-end-radius: var(--_kui-split-button-radius);
96
+ }
97
+
98
+ /* The ring sits outside the focused half, offset like Button's, so it is
99
+ drawn against the surrounding surface rather than the loud fill, whose
100
+ brand color can match the ring's own (an inset ring vanished there). The
101
+ segment along the divider overlaps the neighboring half, painted above it. */
102
+ .kui-split-button > button:focus {
103
+ outline: none;
104
+ }
105
+
74
106
  .kui-split-button > button:focus-visible {
75
107
  outline: var(--kui-focus-ring);
108
+ outline-offset: 1px;
109
+ }
110
+
111
+ /* focusRingInset: inside an ancestor that clips overflow, each half's ring
112
+ moves inside its box. The loud fill can share the ring's hue (brand), so a
113
+ surface-colored line runs inside the ring: the ring then meets the surface
114
+ on both edges, as the outside ring does, on every tone. The line runs 3px
115
+ past the ring, wide enough to stay solid at a fractional position. It
116
+ paints the surface context, as Button's does (foundation.css). */
117
+ .kui-split-button[data-focus-ring-inset="true"] > button:focus-visible {
76
118
  outline-offset: -3px;
119
+ box-shadow:
120
+ inset 0 0 0 6px var(--kui-color-surface-current-tint, transparent),
121
+ inset 0 0 0 6px var(--kui-color-surface-current-region, transparent),
122
+ inset 0 0 0 6px var(--kui-color-surface-current, var(--kui-color-surface));
77
123
  }
78
124
 
79
125
  .kui-split-button > button:disabled {
@@ -11,10 +11,14 @@
11
11
  border: 1px solid var(--kui-framed-list-border);
12
12
  border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
13
13
  background: var(--kui-color-surface-lowered);
14
+ --kui-color-surface-current-tint: var(--kui-color-surface-lowered);
14
15
  list-style: none;
15
16
  }
16
17
 
17
18
  .kui-framed-list[data-surface="base"] {
19
+ --kui-color-surface-current: var(--kui-color-surface);
20
+ --kui-color-surface-current-region: transparent;
21
+ --kui-color-surface-current-tint: transparent;
18
22
  background: var(--kui-color-surface);
19
23
  }
20
24
 
@@ -273,10 +273,16 @@
273
273
 
274
274
  /* `surface`: a solid background behind the stack and its insets. */
275
275
  .kui-list[data-surface="base"] {
276
+ --kui-color-surface-current: var(--kui-color-surface);
277
+ --kui-color-surface-current-region: transparent;
278
+ --kui-color-surface-current-tint: transparent;
276
279
  background: var(--kui-color-surface);
277
280
  }
278
281
 
279
282
  .kui-list[data-surface="raised"] {
283
+ --kui-color-surface-current: var(--kui-color-surface-raised);
284
+ --kui-color-surface-current-region: transparent;
285
+ --kui-color-surface-current-tint: transparent;
280
286
  background: var(--kui-color-surface-raised);
281
287
  }
282
288
 
@@ -29,6 +29,13 @@
29
29
  padding-block: var(--kui-list-header-title-padding-block, 0.25rem);
30
30
  }
31
31
 
32
+ /* Wrapped label lines keep the compact header's 4px block inset off the
33
+ header edges; a one-line label still centers in the unchanged minimum
34
+ height. */
35
+ .kui-list-header[data-wrap="true"] .kui-list-header__title {
36
+ padding-block: var(--kui-list-header-title-padding-block, 0.25rem);
37
+ }
38
+
32
39
  .kui-list-header[data-divider="before"],
33
40
  .kui-list-header[data-divider="both"] {
34
41
  border-block-start: 1px solid
@@ -20,6 +20,9 @@
20
20
  border: 1px solid var(--kui-color-neutral-border-normal);
21
21
  border-radius: var(--kui-anchored-surface-radius, var(--kui-radius-m));
22
22
  color: var(--kui-color-text, inherit);
23
+ --kui-color-surface-current: var(--kui-color-surface-raised);
24
+ --kui-color-surface-current-region: transparent;
25
+ --kui-color-surface-current-tint: transparent;
23
26
  background: var(--kui-color-surface-raised);
24
27
  box-shadow: var(--kui-shadow-l);
25
28
  font: inherit;
@@ -1,6 +1,7 @@
1
- /* Checkbox: a drawn box beside its label, with hint and error text on the
2
- label's column. The native input sits invisibly over the box, so pointer,
3
- keyboard, touch exploration, and forms all reach the real control. */
1
+ /* Checkbox: a drawn box beside its label, with hint and error text directly
2
+ under the label on its column, as a grouped choice hint sits. The native
3
+ input sits invisibly over the box, so pointer, keyboard, touch
4
+ exploration, and forms all reach the real control. */
4
5
  .kui-checkbox {
5
6
  --_kui-checkbox-box: 1.25rem;
6
7
  --_kui-checkbox-gap: 0.5rem;
@@ -91,7 +92,6 @@
91
92
  .kui-checkbox__hint,
92
93
  .kui-checkbox__error {
93
94
  display: block;
94
- margin-block-start: 0.4375rem;
95
95
  padding-inline-start: calc(
96
96
  var(--_kui-checkbox-box) + var(--_kui-checkbox-gap)
97
97
  );
@@ -106,8 +106,9 @@
106
106
  .kui-checkbox__error {
107
107
  color: var(--kui-color-danger-on-quiet);
108
108
  }
109
- .kui-checkbox__hint + .kui-checkbox__error {
110
- margin-block-start: 0;
109
+ /* Inside a CheckboxGroup an invalid group marks every box. */
110
+ .kui-checkbox-group[data-invalid] .kui-checkbox__box {
111
+ border-color: var(--kui-color-danger-border-loud);
111
112
  }
112
113
  @media (forced-colors: active) {
113
114
  .kui-checkbox__box {
@@ -0,0 +1,63 @@
1
+ /* CheckboxGroup: the group label, the choices (each a Kerf Checkbox, which
2
+ draws its own box, label, and hint), and hint and error text below. It is
3
+ laid out exactly like a RadioGroup: each box sits on the group's
4
+ inline-start edge and stacked choices sit 8px apart, the 28px pitch
5
+ checkboxes and radios share. */
6
+ .kui-checkbox-group {
7
+ display: flex;
8
+ min-width: 0;
9
+ flex-direction: column;
10
+ margin: 0;
11
+ padding: 0;
12
+ border: none;
13
+ font-size: var(--kui-font-m, 1rem);
14
+ font-weight: 400;
15
+ line-height: 1.2;
16
+ }
17
+ .kui-checkbox-group[data-size="compact"] {
18
+ font-size: var(--kui-font-s, 0.875rem);
19
+ }
20
+ /* The label matches every Kerf form control's label (RadioGroup's too). */
21
+ .kui-checkbox-group__label {
22
+ display: block;
23
+ float: none;
24
+ margin-block-end: 0.375rem;
25
+ padding: 0;
26
+ padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
27
+ color: var(--kui-color-neutral-on-quiet);
28
+ font-size: var(--kui-font-xs);
29
+ font-weight: 650;
30
+ letter-spacing: 0.04em;
31
+ line-height: 1.2;
32
+ text-transform: uppercase;
33
+ }
34
+ .kui-checkbox-group__choices {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: var(--kui-space-xs);
38
+ }
39
+ .kui-checkbox-group[data-orientation="horizontal"]
40
+ .kui-checkbox-group__choices {
41
+ flex-direction: row;
42
+ flex-wrap: wrap;
43
+ column-gap: 1.5rem;
44
+ }
45
+ .kui-checkbox-group__hint,
46
+ .kui-checkbox-group__error {
47
+ display: block;
48
+ margin-block-start: 0.4375rem;
49
+ padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
50
+ color: var(--kui-color-text-quiet);
51
+ font-size: var(--kui-font-s, 0.875rem);
52
+ line-height: 1.6;
53
+ }
54
+ .kui-checkbox-group[data-size="compact"]
55
+ :is(.kui-checkbox-group__hint, .kui-checkbox-group__error) {
56
+ font-size: var(--kui-font-xs, 0.75rem);
57
+ }
58
+ .kui-checkbox-group__error {
59
+ color: var(--kui-color-danger-on-quiet);
60
+ }
61
+ .kui-checkbox-group__hint + .kui-checkbox-group__error {
62
+ margin-block-start: 0;
63
+ }