@kerfjs/ui 5.0.0-beta.52 → 5.0.0-beta.53

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 (137) hide show
  1. package/ai/component-catalog-v2.d.ts +3 -0
  2. package/ai/component-catalog-v2.json +3 -1
  3. package/ai/component-catalog-v2.schema.json +7 -0
  4. package/ai/component-catalog.json +3 -1
  5. package/ai/public-api-signatures-v1.md +12 -8
  6. package/ai/skill.md +15 -15
  7. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  8. package/dist/app-tab.js +1 -1
  9. package/dist/browser/segmented-control.js +0 -1
  10. package/dist/catalog.js +4 -4
  11. package/dist/{chunk-7XJO4D6A.js → chunk-3NBL3OUQ.js} +2 -2
  12. package/dist/{chunk-7XJO4D6A.js.map → chunk-3NBL3OUQ.js.map} +1 -1
  13. package/dist/{chunk-2S7OWAEV.js → chunk-44IG7PFV.js} +3 -3
  14. package/dist/{chunk-2S7OWAEV.js.map → chunk-44IG7PFV.js.map} +1 -1
  15. package/dist/{chunk-DNCOFEUL.js → chunk-5I22LMCV.js} +2 -2
  16. package/dist/{chunk-DNCOFEUL.js.map → chunk-5I22LMCV.js.map} +1 -1
  17. package/dist/{chunk-KAQUUTZR.js → chunk-ATHXW6RP.js} +2 -2
  18. package/dist/{chunk-KAQUUTZR.js.map → chunk-ATHXW6RP.js.map} +1 -1
  19. package/dist/{chunk-JGFZ42ZF.js → chunk-BJJKFVWW.js} +14 -5
  20. package/dist/chunk-BJJKFVWW.js.map +1 -0
  21. package/dist/{chunk-T7C2VZUB.js → chunk-C2FAYFDE.js} +2 -2
  22. package/dist/{chunk-T7C2VZUB.js.map → chunk-C2FAYFDE.js.map} +1 -1
  23. package/dist/{chunk-IR53BQUJ.js → chunk-CCMKJWLX.js} +3 -3
  24. package/dist/{chunk-IR53BQUJ.js.map → chunk-CCMKJWLX.js.map} +1 -1
  25. package/dist/{chunk-SV22UIW4.js → chunk-DQA5FMOX.js} +2 -2
  26. package/dist/{chunk-SV22UIW4.js.map → chunk-DQA5FMOX.js.map} +1 -1
  27. package/dist/{chunk-LIOXPQ7N.js → chunk-GUIHMIT2.js} +12 -10
  28. package/dist/chunk-GUIHMIT2.js.map +1 -0
  29. package/dist/{chunk-3S7OUHUN.js → chunk-KPNTVB7A.js} +9 -4
  30. package/dist/chunk-KPNTVB7A.js.map +1 -0
  31. package/dist/{chunk-OSCL5TKR.js → chunk-RNZAKSME.js} +11 -8
  32. package/dist/chunk-RNZAKSME.js.map +1 -0
  33. package/dist/{chunk-ABAXNUXU.js → chunk-T22EM4ET.js} +7 -5
  34. package/dist/chunk-T22EM4ET.js.map +1 -0
  35. package/dist/{chunk-YZV2PTY4.js → chunk-TZ5IHWB2.js} +3 -3
  36. package/dist/{chunk-YZV2PTY4.js.map → chunk-TZ5IHWB2.js.map} +1 -1
  37. package/dist/{chunk-2CE22Q2K.js → chunk-WZ2GLEY4.js} +2 -1
  38. package/dist/chunk-WZ2GLEY4.js.map +1 -0
  39. package/dist/{chunk-M6GLI6A6.js → chunk-X5QSICJ3.js} +5 -5
  40. package/dist/chunk-X5QSICJ3.js.map +1 -0
  41. package/dist/{chunk-4XE2CDYB.js → chunk-ZMBU522F.js} +2 -2
  42. package/dist/{chunk-4XE2CDYB.js.map → chunk-ZMBU522F.js.map} +1 -1
  43. package/dist/css-values.d.ts +1 -1
  44. package/dist/css-values.js +1 -1
  45. package/dist/grid.js +1 -1
  46. package/dist/index.js +15 -15
  47. package/dist/list-action-row.d.ts +2 -1
  48. package/dist/list-action-row.js +1 -1
  49. package/dist/list-header.d.ts +1 -0
  50. package/dist/list-header.js +1 -1
  51. package/dist/list-item.d.ts +5 -3
  52. package/dist/list-item.js +1 -1
  53. package/dist/list.js +1 -1
  54. package/dist/nav-stack.js +1 -1
  55. package/dist/row.js +1 -1
  56. package/dist/segmented-control.d.ts +1 -1
  57. package/dist/segmented-control.js +1 -3
  58. package/dist/select.js +1 -1
  59. package/dist/skeleton.js +1 -1
  60. package/dist/spacer.js +1 -1
  61. package/dist/split-view.js +1 -1
  62. package/dist/state-banner.d.ts +1 -1
  63. package/dist/state-banner.js +1 -1
  64. package/dist/styles/badge.css +17 -6
  65. package/dist/styles/collapsible-panel.css +1 -1
  66. package/dist/styles/foundation.css +82 -26
  67. package/dist/styles/list-action-row.css +29 -8
  68. package/dist/styles/list-header.css +19 -7
  69. package/dist/styles/list-item.css +11 -3
  70. package/dist/styles/resizable-region.css +1 -1
  71. package/dist/styles/segmented-control.css +21 -1
  72. package/dist/styles/select.css +24 -13
  73. package/dist/styles/skeleton.css +33 -2
  74. package/dist/styles/state-banner.css +48 -12
  75. package/dist/styles/webawesome.css +47 -20
  76. package/dist/styles/workbench.css +1 -1
  77. package/dist/toolbar-text.js +1 -1
  78. package/dist/value-table.js +1 -1
  79. package/docs/component-contract.md +76 -4
  80. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  81. package/docs/design/templates/empty-state-dark.svg +1 -1
  82. package/docs/design/templates/list/stack-dark.svg +1 -1
  83. package/docs/design/templates/list/stack.svg +1 -1
  84. package/docs/design/templates/list-action-row/selected.svg +1 -1
  85. package/docs/design/templates/list-action-row.svg +1 -1
  86. package/docs/design/templates/list-dark.svg +1 -1
  87. package/docs/design/templates/list-header/action-dark.svg +1 -1
  88. package/docs/design/templates/list-header/action.svg +1 -1
  89. package/docs/design/templates/list-header/count-dark.svg +1 -1
  90. package/docs/design/templates/list-header/count.svg +1 -1
  91. package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
  92. package/docs/design/templates/list-header/inline-action.svg +1 -1
  93. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
  94. package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
  95. package/docs/design/templates/list-header-dark.svg +1 -1
  96. package/docs/design/templates/list-header.svg +1 -1
  97. package/docs/design/templates/list-item/selected.svg +1 -1
  98. package/docs/design/templates/list-item.svg +1 -1
  99. package/docs/design/templates/list.svg +1 -1
  100. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  101. package/docs/design/templates/segmented-control/equal.svg +1 -1
  102. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
  103. package/docs/design/templates/segmented-control/pill-small.svg +1 -1
  104. package/docs/design/templates/segmented-control-dark.svg +1 -1
  105. package/docs/design/templates/segmented-control.svg +1 -1
  106. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  107. package/docs/design/templates/state-banner/danger.svg +1 -1
  108. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  109. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  110. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  111. package/docs/design/templates/state-banner/info.svg +1 -1
  112. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  113. package/docs/design/templates/state-banner/success.svg +1 -1
  114. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  115. package/docs/design/templates/state-banner/warning.svg +1 -1
  116. package/docs/design/templates/state-banner-dark.svg +1 -1
  117. package/docs/design/templates/state-banner.svg +1 -1
  118. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  119. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  120. package/docs/design/templates/tab-bar-dark.svg +1 -1
  121. package/docs/design/templates/tab-bar.svg +1 -1
  122. package/docs/design/templates/token-search-field/tokens.svg +1 -1
  123. package/docs/design/templates/token-search-field.svg +1 -1
  124. package/docs/design/templates.md +11 -1
  125. package/docs/device-class.md +2 -1
  126. package/docs/ux-demo.md +1 -1
  127. package/docs/webawesome-theme.md +9 -2
  128. package/llms.txt +7 -3
  129. package/package.json +1 -1
  130. package/ux-demo/recipes/loading-inspector.tsx +3 -2
  131. package/dist/chunk-2CE22Q2K.js.map +0 -1
  132. package/dist/chunk-3S7OUHUN.js.map +0 -1
  133. package/dist/chunk-ABAXNUXU.js.map +0 -1
  134. package/dist/chunk-JGFZ42ZF.js.map +0 -1
  135. package/dist/chunk-LIOXPQ7N.js.map +0 -1
  136. package/dist/chunk-M6GLI6A6.js.map +0 -1
  137. package/dist/chunk-OSCL5TKR.js.map +0 -1
@@ -148,8 +148,28 @@
148
148
  outline-offset: 1px;
149
149
  }
150
150
 
151
- .kui-segmented-control__item:disabled {
151
+ /* A placeholder is disabled to stay inert, but it is loading, not unavailable:
152
+ its choices keep the live tone. SegmentedControl renders no skeleton (its
153
+ choices are known; only the selection is unknown), so it does not load
154
+ skeleton.css and neutralizes disabled chrome itself, including Web Awesome's
155
+ native button:disabled. A choice the author disabled (the data-kui-disabled
156
+ marker) keeps the live disabled tone; only the `not-allowed` cursor is
157
+ reserved for the live control. */
158
+ .kui-segmented-control[data-placeholder="true"] .kui-segmented-control__item {
159
+ cursor: default;
160
+ }
161
+
162
+ .kui-segmented-control[data-placeholder="true"]
163
+ .kui-segmented-control__item:not([data-kui-disabled="true"]) {
164
+ opacity: 1;
165
+ }
166
+
167
+ .kui-segmented-control__item[data-kui-disabled="true"] {
152
168
  opacity: 0.45;
169
+ }
170
+
171
+ .kui-segmented-control:not([data-placeholder="true"])
172
+ .kui-segmented-control__item:disabled {
153
173
  cursor: not-allowed;
154
174
  }
155
175
 
@@ -116,7 +116,7 @@
116
116
  .kui-select wa-option {
117
117
  --wa-form-control-activated-color: var(--kui-color-brand-fill-normal);
118
118
  /* Current option text sits on the activated brand fill; use the darker on-fill
119
- accent so it clears WCAG AA (brand-on-quiet was 3.77:1 over that fill). */
119
+ accent so it clears WCAG AA (brand-on-quiet is 4.26:1 over that fill). */
120
120
  --current-text-color: var(--kui-color-brand-on-fill);
121
121
  }
122
122
  .kui-select wa-option::part(start) {
@@ -189,11 +189,17 @@
189
189
  width: 100%;
190
190
  }
191
191
  .kui-select__placeholder-label {
192
+ /* The live field's top label (see webawesome.css): a ListHeader-style label,
193
+ inset by the field's border + inline padding so it lines up with the value. */
192
194
  display: block;
193
- margin-block-end: 0.25rem;
194
- color: var(--kui-color-text);
195
- font-size: var(--kui-font-s);
196
- line-height: 1.4;
195
+ margin-block-end: 0.375rem;
196
+ padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
197
+ color: var(--kui-color-neutral-on-quiet);
198
+ font-size: var(--kui-font-xs);
199
+ font-weight: 650;
200
+ letter-spacing: 0.04em;
201
+ line-height: 1.2;
202
+ text-transform: uppercase;
197
203
  }
198
204
  .kui-select__placeholder-box {
199
205
  display: flex;
@@ -219,23 +225,28 @@
219
225
  max-width: 100%;
220
226
  }
221
227
  .kui-select__placeholder-hint {
228
+ /* The live wa-select hint part: small body text at Web Awesome's form-control
229
+ hint metrics (1.6 line height, 7px below the box), inset like the value. */
222
230
  display: block;
223
- margin-block-start: 0.25rem;
231
+ margin-block-start: 0.4375rem;
224
232
  padding-inline: calc(1px + var(--kui-layout-item-padding, 0.5rem));
225
233
  color: var(--kui-color-text-quiet);
226
- font-size: var(--kui-font-xs);
227
- line-height: 1.4;
234
+ font-size: var(--kui-font-s);
235
+ line-height: 1.6;
228
236
  }
229
237
  .kui-select__placeholder-chevron {
230
- display: inline-flex;
231
- width: 1rem;
238
+ /* The live control's expand-icon box and scale, with the same glyph. */
239
+ display: grid;
240
+ width: 1.25rem;
232
241
  height: 1rem;
233
242
  flex: none;
234
- color: var(--kui-color-text-quiet);
235
- transform: scale(var(--kui-disclosure-icon-scale, 0.85));
243
+ place-items: center;
244
+ color: var(--kui-color-neutral-on-quiet);
245
+ transform: scale(var(--kui-disclosure-icon-scale, 0.5));
236
246
  }
237
247
  .kui-select__placeholder-chevron svg {
238
248
  display: block;
239
- width: 100%;
249
+ width: auto;
240
250
  height: 100%;
251
+ fill: currentColor;
241
252
  }
@@ -7,8 +7,13 @@
7
7
  height: 1em;
8
8
  border-radius: var(--kui-skeleton-radius);
9
9
  /* Deliberately unanimated: a flat, subtle fill that reads as "not yet loaded"
10
- without drawing the eye or implying progress. */
11
- background: color-mix(in srgb, var(--kui-color-text) 12%, transparent);
10
+ without drawing the eye or implying progress. A host with its own solid
11
+ fill (a solid Badge) supplies `--_kui-skeleton-fill` derived from its
12
+ foreground, since a text-color tint vanishes on a saturated fill. */
13
+ background: var(
14
+ --_kui-skeleton-fill,
15
+ color-mix(in srgb, var(--kui-color-text) 12%, transparent)
16
+ );
12
17
  vertical-align: middle;
13
18
  }
14
19
 
@@ -27,6 +32,32 @@
27
32
  height: 0.8em;
28
33
  }
29
34
 
35
+ /* Placeholder mode. A component's `placeholder` keeps its controls `disabled` so
36
+ they stay inert and out of the keyboard order, but a placeholder is loading,
37
+ not unavailable: it must look exactly like the live component except for its
38
+ skeleton values. Neutralize generic disabled chrome, including Web Awesome's
39
+ layered native `button:disabled { opacity: 0.5; cursor: not-allowed }`.
40
+ Opacity carries zero specificity so a component's own opacity rules (a
41
+ hover-revealed control that is invisible until interaction) still win;
42
+ components exclude placeholders from their own disabled tone. The cursor is
43
+ the non-interactive default, never `not-allowed`.
44
+
45
+ A control the author disabled carries `data-kui-disabled="true"` (set from
46
+ the component's own disabled prop, independent of placeholder). It is
47
+ unavailable once loaded, so its placeholder keeps the live disabled tone:
48
+ the reset skips it, and components key their disabled tone on the marker. */
49
+ :where(
50
+ [data-placeholder="true"]:disabled:not([data-kui-disabled="true"]),
51
+ [data-placeholder="true"] :disabled:not([data-kui-disabled="true"])
52
+ ) {
53
+ opacity: 1;
54
+ }
55
+
56
+ [data-placeholder="true"]:disabled,
57
+ [data-placeholder="true"] :disabled {
58
+ cursor: default;
59
+ }
60
+
30
61
  @media (forced-colors: active) {
31
62
  .kui-skeleton {
32
63
  background: GrayText;
@@ -41,6 +41,15 @@
41
41
  align-items: center;
42
42
  gap: var(--kui-layout-item-gap, 0.5rem);
43
43
  }
44
+ /* The detail is secondary through its smaller, regular-weight type, not a
45
+ dimmed color: an opacity cut toned details below WCAG AA over their fills.
46
+ Only the neutral tone has a quieter text color that still clears AA. */
47
+ .kui-state-banner[data-tone="neutral"] {
48
+ --_kui-state-banner-detail: var(
49
+ --kui-state-banner-detail,
50
+ var(--kui-color-neutral-on-quiet)
51
+ );
52
+ }
44
53
  .kui-state-banner[data-tone="info"] {
45
54
  --_kui-state-banner-background: var(
46
55
  --kui-state-banner-background,
@@ -123,7 +132,7 @@
123
132
  );
124
133
  --_kui-state-banner-foreground: var(
125
134
  --kui-state-banner-foreground,
126
- var(--kui-state-banner-danger-foreground, var(--kui-color-danger-on-quiet))
135
+ var(--kui-state-banner-danger-foreground, var(--kui-color-danger-on-fill))
127
136
  );
128
137
  }
129
138
  .kui-state-banner__icon {
@@ -134,21 +143,50 @@
134
143
  width: 1rem;
135
144
  height: 1rem;
136
145
  }
146
+ /* The copy is inline flow, not flex: a wrapping title lays out as text, so the
147
+ badge follows the title's last word instead of the right edge of a
148
+ flex-shrunk title box, and the detail stays beside them only while it fits
149
+ whole. Otherwise it moves to its own line and truncates at the full copy
150
+ width. Flex shrank the title and detail together, which left a gap before
151
+ the badge and cut the detail early. Each item's trailing margin is the item
152
+ gap, so no margin lands at the start of a wrapped line. */
137
153
  .kui-state-banner__copy {
138
- display: flex;
139
154
  min-width: 0;
140
- align-items: baseline;
141
- gap: var(--kui-layout-item-gap, 0.5rem);
155
+ /* The title's size, so a wrapped title's lines keep the title's own line
156
+ height instead of the larger inherited strut. */
157
+ font-size: var(--kui-font-xs);
142
158
  }
143
159
  .kui-state-banner__copy strong {
160
+ margin-inline-end: var(--kui-layout-item-gap, 0.5rem);
144
161
  font-size: var(--kui-font-xs);
145
162
  }
163
+ /* The badge is taller than the title's line. Negative block margins keep it
164
+ out of the line-height calculation, so a wrapped title's lines stay evenly
165
+ spaced whichever line the badge lands on. */
166
+ .kui-state-banner__badge {
167
+ margin-block: -0.5em;
168
+ margin-inline-end: var(--kui-layout-item-gap, 0.5rem);
169
+ vertical-align: baseline;
170
+ }
171
+ /* A placeholder badge holds a skeleton instead of text. With no text, the
172
+ skeleton's baseline would be synthesized from its bottom edge, sitting the
173
+ badge higher than the live one by a font-dependent amount. A zero-width
174
+ character gives it a text baseline in the badge's own font and line
175
+ height, exactly where the live badge's text baseline falls on every
176
+ platform. */
177
+ .kui-state-banner[data-placeholder="true"]
178
+ .kui-state-banner__badge
179
+ > *::before {
180
+ content: "\200b";
181
+ }
146
182
  .kui-state-banner__detail {
147
- overflow: hidden;
183
+ display: inline-block;
184
+ max-width: 100%;
185
+ overflow: clip;
148
186
  color: var(--_kui-state-banner-detail);
149
187
  font-size: var(--kui-font-2xs);
150
- opacity: 0.78;
151
188
  text-overflow: ellipsis;
189
+ vertical-align: baseline;
152
190
  white-space: nowrap;
153
191
  }
154
192
  .kui-state-banner__action {
@@ -174,12 +212,10 @@
174
212
  outline-offset: 2px;
175
213
  }
176
214
  @media (max-width: 36rem) {
177
- .kui-state-banner__copy {
178
- display: grid;
179
- grid-template-columns: auto 1fr;
180
- gap: 0.05rem;
181
- }
215
+ /* The detail drops below the title. The title row keeps the wide layout's
216
+ relationship: a content-sized badge one item gap after the title, on the
217
+ title's baseline. */
182
218
  .kui-state-banner__detail {
183
- grid-column: 1 / -1;
219
+ display: block;
184
220
  }
185
221
  }
@@ -42,9 +42,18 @@
42
42
  var(--wa-color-neutral-fill-normal) 25%,
43
43
  transparent
44
44
  );
45
+ /* Kept although kerf overrides --wa-shadow-s/-m/-l below: Web Awesome's
46
+ theme stylesheets build their shadows from this token, so an app that
47
+ layers one of them keeps kerf's scheme-aware shadow color. */
45
48
  --wa-color-shadow: light-dark(rgb(0 0 0 / 0.14), rgb(0 0 0 / 0.5));
46
49
  --wa-color-focus: light-dark(#007aff, #64d2ff);
47
- --wa-color-brand-fill-loud: light-dark(#0088ff, #64d2ff);
50
+ /* Kerf-owned loud fills and on-loud text: every on-loud/fill-loud pair
51
+ clears WCAG AA (4.5:1) in both schemes. Light brand and danger keep
52
+ white text on a slightly deeper fill of the same hue (#0088ff ->
53
+ #0075db, #ff383c -> #eb0005); success keeps its bright green with dark
54
+ text, as warning already does; dark brand and danger keep their fills
55
+ with dark text. src/foundation.css mirrors these as fallbacks. */
56
+ --wa-color-brand-fill-loud: light-dark(#0075db, #64d2ff);
48
57
  --wa-color-brand-fill-quiet: color-mix(
49
58
  in srgb,
50
59
  var(--wa-color-brand-fill-loud) 8%,
@@ -66,7 +75,10 @@
66
75
  var(--wa-color-surface-default)
67
76
  );
68
77
  --wa-color-brand-border-loud: var(--wa-color-brand-fill-loud);
69
- --wa-color-brand-on-quiet: light-dark(#1e6ef4, #8acbff);
78
+ /* Kerf-owned light on-quiet values: darkened from Hot Sheet 2's hues so
79
+ they clear AA on the lowered page background (#f2f2f7) as well as on
80
+ the surface; src/foundation.css mirrors them as fallbacks. */
81
+ --wa-color-brand-on-quiet: light-dark(#0c62f3, #8acbff);
70
82
  --wa-color-brand-on-normal: var(--wa-color-brand-on-quiet);
71
83
  --wa-color-brand-on-loud: light-dark(#fff, #111113);
72
84
 
@@ -106,9 +118,9 @@
106
118
  var(--wa-color-success-fill-loud) 78%,
107
119
  var(--wa-color-neutral-on-normal)
108
120
  );
109
- --wa-color-success-on-quiet: light-dark(#008932, #63e685);
121
+ --wa-color-success-on-quiet: light-dark(#007f2e, #63e685);
110
122
  --wa-color-success-on-normal: light-dark(#006d28, #8cea9f);
111
- --wa-color-success-on-loud: #fff;
123
+ --wa-color-success-on-loud: #1d1d1f;
112
124
 
113
125
  --wa-color-warning-fill-loud: #ffcc00;
114
126
  --wa-color-warning-fill-quiet: color-mix(
@@ -136,11 +148,11 @@
136
148
  var(--wa-color-warning-fill-loud) 78%,
137
149
  var(--wa-color-neutral-on-normal)
138
150
  );
139
- --wa-color-warning-on-quiet: light-dark(#a16a00, #ffd84a);
151
+ --wa-color-warning-on-quiet: light-dark(#966200, #ffd84a);
140
152
  --wa-color-warning-on-normal: light-dark(#5f3f00, #ffe27a);
141
153
  --wa-color-warning-on-loud: #1d1d1f;
142
154
 
143
- --wa-color-danger-fill-loud: #ff383c;
155
+ --wa-color-danger-fill-loud: light-dark(#eb0005, #ff383c);
144
156
  --wa-color-danger-fill-quiet: color-mix(
145
157
  in srgb,
146
158
  var(--wa-color-danger-fill-loud) 7%,
@@ -168,7 +180,7 @@
168
180
  );
169
181
  --wa-color-danger-on-quiet: light-dark(#c20b20, #ff696c);
170
182
  --wa-color-danger-on-normal: light-dark(#8e0717, #ff8a8c);
171
- --wa-color-danger-on-loud: #fff;
183
+ --wa-color-danger-on-loud: light-dark(#fff, #111113);
172
184
 
173
185
  /* Geometry stays aligned with the compact Kerf primitives. */
174
186
  --wa-border-radius-pill: 999px;
@@ -217,9 +229,16 @@
217
229
  --kui-wa-surface-margin: var(--kui-layout-inline-margin, 0.5rem);
218
230
  --kui-wa-container-inset: var(--kui-space-m, 1rem);
219
231
  --kui-disclosure-icon-scale: 0.5;
220
- --wa-shadow-s: 0 1px 3px rgb(0 0 0 / 0.14);
221
- --wa-shadow-m: 0 0.35rem 1rem rgb(0 0 0 / 0.11);
222
- --wa-shadow-l: 0 0.75rem 2rem rgb(0 0 0 / 0.09);
232
+ /* Elevation follows the scheme like --wa-color-shadow does: the light
233
+ alphas stay Hot Sheet 2's soft values, while dark raises them so a
234
+ raised surface still separates from a near-black page (a 9% black
235
+ shadow is invisible there). src/foundation.css mirrors these as
236
+ fallbacks. */
237
+ --wa-shadow-s: 0 1px 3px light-dark(rgb(0 0 0 / 0.14), rgb(0 0 0 / 0.5));
238
+ --wa-shadow-m: 0 0.35rem 1rem
239
+ light-dark(rgb(0 0 0 / 0.11), rgb(0 0 0 / 0.4));
240
+ --wa-shadow-l: 0 0.75rem 2rem
241
+ light-dark(rgb(0 0 0 / 0.09), rgb(0 0 0 / 0.32));
223
242
  }
224
243
 
225
244
  :where(:root),
@@ -255,18 +274,26 @@
255
274
  ) !important;
256
275
  }
257
276
 
258
- /* The fixed brand/success/danger loud fills need a dark foreground in both
259
- color schemes at badge text size. Neutral and warning already select an
260
- AA-safe on-loud token, so preserve their variant-specific treatment. */
261
- wa-badge[appearance="accent"]:is(
262
- :not([variant]),
263
- [variant="brand"],
264
- [variant="success"],
265
- [variant="danger"]
266
- ) {
277
+ /* Every variant's on-loud token clears AA on its loud fill in both color
278
+ schemes, so accent badges use it by default (a fixed dark foreground here
279
+ would fail on the deeper light brand and danger fills). Brand, success,
280
+ and danger keep a reviewed-override hook. */
281
+ wa-badge[appearance="accent"]:is(:not([variant]), [variant="brand"]) {
267
282
  --wa-color-on-loud: var(
268
283
  --kui-wa-badge-accent-foreground,
269
- #1d1d1f
284
+ var(--wa-color-brand-on-loud)
285
+ ) !important;
286
+ }
287
+ wa-badge[appearance="accent"][variant="success"] {
288
+ --wa-color-on-loud: var(
289
+ --kui-wa-badge-accent-foreground,
290
+ var(--wa-color-success-on-loud)
291
+ ) !important;
292
+ }
293
+ wa-badge[appearance="accent"][variant="danger"] {
294
+ --wa-color-on-loud: var(
295
+ --kui-wa-badge-accent-foreground,
296
+ var(--wa-color-danger-on-loud)
270
297
  ) !important;
271
298
  }
272
299
 
@@ -259,7 +259,7 @@
259
259
  z-index: var(--kui-workbench-overlay-z, 41);
260
260
  max-width: var(--kui-workbench-overlay-max-width, 85vw);
261
261
  max-height: var(--kui-workbench-overlay-max-height, 85vh);
262
- box-shadow: var(--kui-shadow-l, 0 8px 32px rgb(0 0 0 / 24%));
262
+ box-shadow: var(--kui-shadow-l);
263
263
  }
264
264
 
265
265
  .kui-workbench__rail[data-presentation="overlay"] {
@@ -1,4 +1,4 @@
1
- export { ToolbarText } from './chunk-YZV2PTY4.js';
1
+ export { ToolbarText } from './chunk-TZ5IHWB2.js';
2
2
 
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- export { ValueTable, ValueTableRow } from './chunk-2S7OWAEV.js';
1
+ export { ValueTable, ValueTableRow } from './chunk-44IG7PFV.js';
2
2
 
3
3
 
4
4
 
@@ -26,7 +26,10 @@ delivery contract. Every v1 entry projects once, in order, under the stable
26
26
  qualified key `package:id`. Each v2 entry explicitly covers parents/contexts,
27
27
  named zones and cardinality, optional explicit JSX prop bindings, child concepts, state ownership, required wiring,
28
28
  responsive ownership, layout and geometry, accessibility obligations, public
29
- CSS boundaries, diagnostics, and provenance.
29
+ CSS boundaries, diagnostics, and provenance. A wrapper entry may add
30
+ `rendersAs`: the cataloged roots it renders (any one of them, or nothing), so
31
+ composition checks treat its elements as each root rather than as an unknown
32
+ child.
30
33
 
31
34
  An entry's optional `cssValueProps` makes CSS-adjacent prop grammar equally
32
35
  machine-evaluable. Each path records the property grammar, finite shorthands,
@@ -245,6 +248,9 @@ and metadata labels. Configure its semantic `tone`, `appearance`, `shape`, and
245
248
  `size`; do not recreate or override badge anatomy in an application or consuming
246
249
  component. Use `label` when visible content is abbreviated and `ariaHidden` only
247
250
  when a surrounding component already includes the same value in its accessible name.
251
+ Every tone's text and solid fill use that tone's `--kui-color-{tone}-on-fill`
252
+ token (`neutral` uses the text colors), the foreground tuned to clear WCAG AA
253
+ (4.5:1) on the tone's fills in light and dark mode.
248
254
 
249
255
  `ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
250
256
  default while retaining the row's 44px minimum interactive target. Multiline
@@ -275,7 +281,14 @@ the logical end while the visible glyph defaults to 18px through
275
281
  `StateBanner` exposes instance-level `--kui-state-banner-background`,
276
282
  `--kui-state-banner-border`, `--kui-state-banner-foreground`,
277
283
  `--kui-state-banner-detail` and action background variables. Its optional
278
- badge composes `Badge` beside the title and follows the banner tone by default. Its five built-in
284
+ badge composes `Badge` beside the title and follows the banner tone by default. The
285
+ title, badge, and detail flow as inline text: a wrapping title keeps the badge one item
286
+ gap after its last word, and a detail that does not fit whole beside them moves to its
287
+ own line and truncates at the full copy width (below 576px it always takes its own
288
+ line). The title and detail both use the tone's `--kui-color-{tone}-on-fill`
289
+ foreground (`info` uses `brand`) at full strength, clearing WCAG AA over the tone's fill in light and dark
290
+ mode; the detail reads as secondary through its smaller, regular-weight type, and
291
+ only the neutral tone quiets it, to `--kui-color-neutral-on-quiet`. Its five built-in
279
292
  tones can be rethemed globally with
280
293
  `--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
281
294
  segmented-control, app-tab, and tab-bar colors likewise use their public
@@ -449,7 +462,8 @@ A value-bearing component's `placeholder` prop is a first-class loading mode: th
449
462
  component renders its own real chrome (labels, icon and action affordances,
450
463
  container geometry) while replacing each **value** slot with a subtle, deliberately
451
464
  unanimated `Skeleton` block and disabling its own interactive controls
452
- (`aria-busy`, dropped `data-action`, disabled buttons). Sizes and shapes stay
465
+ (`aria-busy`, dropped `data-action`, disabled buttons). Only unknown values become
466
+ skeletons; nothing else may change. Sizes, shapes, typography, color, and opacity stay
453
467
  identical to the populated component, so a parent composes a faithful loading view —
454
468
  an inspector, a detail pane — from placeholder children without hand-rebuilding
455
469
  markup. The application still owns the loading lifecycle (when to pass `placeholder`)
@@ -460,6 +474,46 @@ line of its own and centers in its slot. It is a
460
474
  placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
461
475
  animate the skeleton.
462
476
 
477
+ A placeholder is loading, not unavailable, so it keeps the `disabled` attribute (its
478
+ controls stay inert and out of the keyboard order) but never shows disabled chrome.
479
+ `skeleton.css`, which every component that renders a skeleton loads, neutralizes generic
480
+ disabled styling under `[data-placeholder="true"]` — including Web Awesome's native
481
+ `button:disabled { opacity: 0.5; cursor: not-allowed }` when `webawesome.css` is
482
+ loaded — to full opacity and the non-interactive `default` cursor. That opacity reset
483
+ carries zero specificity, so a component's own opacity (a control hidden until
484
+ interaction) still wins, and each component excludes placeholders from its own
485
+ disabled tone and hover feedback — including hover reveals: a `ListActionRow` with
486
+ `trailingActionVisibility="interaction"` keeps its trailing action hidden when its
487
+ placeholder is hovered, as the resting live row does. The cursor is the one intentional difference from the
488
+ live state: a placeholder is not clickable, so it never advertises a pointer.
489
+
490
+ A control the author disabled is different: it will be unavailable once loaded, so its
491
+ placeholder keeps the live disabled tone. Each such control carries the component-owned
492
+ `data-kui-disabled="true"` marker whenever its own disabled prop is set, independent of
493
+ `placeholder` — `ListItem` and `ListActionRow` `disabled`, `trailingActionDisabled`,
494
+ a `SegmentedControl` choice's `disabled`, and `ListHeader` `actionDisabled` (on the
495
+ action or disclosure toggle). The placeholder reset skips the marker and components key
496
+ their disabled tone on it, so only the `placeholder`-only `disabled` attribute is
497
+ neutralized. That tone is each component's own, never Web Awesome's native
498
+ `button:disabled`, so an author-disabled control is dimmed with or without
499
+ `webawesome.css`. The marker is reserved: the extension-attribute channels
500
+ (`rootAttributes`, `trailingActionAttributes`, `triggerAttributes`) cannot set it. A
501
+ disabled placeholder still shows the `default` cursor, never `not-allowed`.
502
+ Chrome a component draws itself from a known prop stays live, even inside a slot that
503
+ also holds values. `ListItem`'s trailing slot has three inputs: the `busy` spinner is
504
+ component-owned chrome and stays live, while `status` text and author-supplied
505
+ `trailing` content are values and each become a skeleton (the component cannot tell an
506
+ author's chevron from a count, so all `trailing` content is treated as a value).
507
+ `ListActionRow`'s status line follows the same split: its `busy` spinner stays live and
508
+ only the `status` text becomes a skeleton.
509
+ `SegmentedControl` is the one placeholder without a skeleton: its choices are known
510
+ chrome and only the selection is unknown, so it renders every choice's live label or
511
+ icon at its live geometry, selects none, and neutralizes its own disabled chrome.
512
+ `tests/browser/placeholder-fixture.spec.ts` enforces the rule: it renders every
513
+ placeholder component live and as a placeholder from identical props and diffs each
514
+ element's geometry and computed chrome, excluding only the value slots, and checks that
515
+ every author-disabled control is dimmed in both renders.
516
+
463
517
  Package source styles express root-scaled geometry with `remify(<px>)`; the
464
518
  build converts it against the 16px authoring baseline and exposes only ordinary
465
519
  `rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
@@ -475,7 +529,25 @@ Kerf JSX declaration boundary for every catalog-supported `wa-*` tag.
475
529
  Consumers register only the individual Web Awesome modules they render and can
476
530
  override `--wa-*` values after the theme import. The shared `--wa-*` values feed
477
531
  both Web Awesome controls and Kerf's `--kui-*` foundation aliases, preventing a
478
- second application palette.
532
+ second application palette. Without the theme, every foundation color token,
533
+ every elevation token (`--kui-shadow-*`), and the focus-ring color fall back to
534
+ the same value the theme assigns, including its `light-dark()` pair, so
535
+ surfaces (including the dark `surface-raised`), links (`text-link` is the brand
536
+ on-quiet text color, not the brand fill), tone text, fills, and raised-surface
537
+ shadows keep their light and dark appearance and contrast either way. The
538
+ theme's elevation shadows are scheme-aware: light keeps the soft Hot Sheet 2
539
+ alphas, and dark raises them (`--wa-shadow-s` 14% to 50% black, `-m` 11% to
540
+ 40%, `-l` 9% to 32%) so a raised surface still separates from a near-black
541
+ page.
542
+ Kerf owns the light `brand`, `success`, and `warning` `on-quiet` values in that
543
+ theme layer: each keeps its hue but is dark enough to clear WCAG AA (4.5:1) on
544
+ the lowered page background (`--kui-color-surface-lowered`, `#f2f2f7`), not
545
+ only on the white surface, so toned text reads on every background a page
546
+ paints. It likewise owns every tone's loud pair: each `on-loud` text color
547
+ clears AA on its `fill-loud` in both schemes. Light brand and danger keep white
548
+ text on a slightly deeper fill of the same hue (`#0075db`, `#eb0005`); success
549
+ keeps its bright green with dark text, as warning does; the dark-mode brand and
550
+ danger fills keep their color with dark text.
479
551
 
480
552
  `Select` owns its custom-element reconciliation seam. It gives each slotted
481
553
  option icon a stable key and leaves the upgraded Web Awesome-owned slot subtree
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 220" width="460" height="220"><defs><clipPath id="cp0"><rect x="214" y="53" width="32" height="32"/></clipPath><clipPath id="ct2"><rect x="157.7" y="101" width="144.7" height="23"/></clipPath><clipPath id="ct3"><rect x="73.7" y="132" width="312.7" height="20.3"/></clipPath><clipPath id="ct4"><rect x="178.6" y="168.3" width="102.8" height="32"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="212" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgic1"><rect x="214" y="53" width="32" height="32"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(214 53)scale(1.33333)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="157.67" y="120" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No open tickets</text><text x="73.67" y="147" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">When someone files a ticket it will show up here.</text><rect x="178.6" y="168.3" width="102.8" height="32" rx="16" fill="rgb(28,28,30)"/><rect x="179.5" y="168.5" width="101" height="31" rx="15.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="191.63" y="190.3" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">New ticket</text></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 220" width="460" height="220"><defs><clipPath id="cp0"><rect x="214" y="53" width="32" height="32"/></clipPath><clipPath id="ct2"><rect x="157.7" y="101" width="144.7" height="23"/></clipPath><clipPath id="ct3"><rect x="73.7" y="132" width="312.7" height="20.3"/></clipPath><clipPath id="ct4"><rect x="178.6" y="168.3" width="102.8" height="32"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="212" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgic1"><rect x="214" y="53" width="32" height="32"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(214 53)scale(1.33333)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="157.67" y="120" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No open tickets</text><text x="73.67" y="147" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">When someone files a ticket it will show up here.</text><rect x="178.6" y="168.3" width="102.8" height="32" rx="16" fill="rgb(44,44,46)"/><rect x="179.5" y="168.5" width="101" height="31" rx="15.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="191.63" y="190.3" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">New ticket</text></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 492 502" width="492" height="502"><defs><clipPath id="cp0"><rect x="16" y="38" width="460" height="220"/></clipPath><clipPath id="cp1"><rect x="16" y="296" width="460" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="460" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="460" height="220" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="274" width="460" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="296" width="460" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="492" height="502" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Icon, title, detail, and action</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="460" height="220"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="214" y="53" width="32" height="32"/></clipPath><clipPath id="svgimg4ct2"><rect x="157.7" y="101" width="144.7" height="23"/></clipPath><clipPath id="svgimg4ct3"><rect x="73.7" y="132" width="312.7" height="20.3"/></clipPath><clipPath id="svgimg4ct4"><rect x="178.6" y="168.3" width="102.8" height="32"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="212" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic1"><rect x="214" y="53" width="32" height="32"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(214 53)scale(1.33333)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="157.67" y="120" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No open tickets</text><text x="73.67" y="147" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">When someone files a ticket it will show up here.</text><rect x="178.6" y="168.3" width="102.8" height="32" rx="16" fill="rgb(28,28,30)"/><rect x="179.5" y="168.5" width="101" height="31" rx="15.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="191.63" y="190.3" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">New ticket</text></g></g></g></g><text x="16" y="286" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">No results for a filter</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="296" width="460" height="190"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 296)"><defs><clipPath id="svgimg7cp0"><rect x="214" y="66" width="32" height="32.3"/></clipPath><clipPath id="svgimg7ct2"><rect x="174.4" y="114.3" width="111.2" height="23"/></clipPath><clipPath id="svgimg7ct3"><rect x="115.7" y="145.3" width="228.6" height="20.3"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="191" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg7svgic1"><rect x="214" y="66.3" width="32" height="32"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(214 66.344)scale(1.33333)"><path d="M10 20a1 1 0 0 0 .6.9l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .5-1.3l7.2-8A1 1 0 0 0 21 3H3a1 1 0 0 0-.7 1.7l7.2 8A2 2 0 0 1 10 14Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="174.42" y="133.34" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No matches</text><text x="115.72" y="160.34" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">No tickets match the current filters.</text></g></g></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 492 502" width="492" height="502"><defs><clipPath id="cp0"><rect x="16" y="38" width="460" height="220"/></clipPath><clipPath id="cp1"><rect x="16" y="296" width="460" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="460" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="460" height="220" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="274" width="460" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="296" width="460" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="492" height="502" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Icon, title, detail, and action</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="460" height="220"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="214" y="53" width="32" height="32"/></clipPath><clipPath id="svgimg4ct2"><rect x="157.7" y="101" width="144.7" height="23"/></clipPath><clipPath id="svgimg4ct3"><rect x="73.7" y="132" width="312.7" height="20.3"/></clipPath><clipPath id="svgimg4ct4"><rect x="178.6" y="168.3" width="102.8" height="32"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="212" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic1"><rect x="214" y="53" width="32" height="32"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(214 53)scale(1.33333)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="157.67" y="120" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No open tickets</text><text x="73.67" y="147" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">When someone files a ticket it will show up here.</text><rect x="178.6" y="168.3" width="102.8" height="32" rx="16" fill="rgb(44,44,46)"/><rect x="179.5" y="168.5" width="101" height="31" rx="15.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="191.63" y="190.3" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">New ticket</text></g></g></g></g><text x="16" y="286" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">No results for a filter</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="296" width="460" height="190"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 296)"><defs><clipPath id="svgimg7cp0"><rect x="214" y="66" width="32" height="32.3"/></clipPath><clipPath id="svgimg7ct2"><rect x="174.4" y="114.3" width="111.2" height="23"/></clipPath><clipPath id="svgimg7ct3"><rect x="115.7" y="145.3" width="228.6" height="20.3"/></clipPath></defs><rect x="28.5" y="20.5" width="403" height="191" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg7svgic1"><rect x="214" y="66.3" width="32" height="32"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(214 66.344)scale(1.33333)"><path d="M10 20a1 1 0 0 0 .6.9l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .5-1.3l7.2-8A1 1 0 0 0 21 3H3a1 1 0 0 0-.7 1.7l7.2 8A2 2 0 0 1 10 14Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="1.5px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="174.42" y="133.34" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="20" font-weight="650" fill="rgb(245,245,247)">No matches</text><text x="115.72" y="160.34" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="14" fill="rgb(174,174,178)">No tickets match the current filters.</text></g></g></g></g></svg>
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="118.8" y="33" width="9.3" height="18"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><text x="118.81" y="48" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(174,174,178)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="26.5" width="97.8" height="31"/></clipPath><clipPath id="ct1"><rect x="29" y="26.5" width="97.8" height="31"/></clipPath><clipPath id="ct2"><rect x="134.8" y="32" width="20.3" height="20"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="37" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><rect x="134.8" y="32" width="20.3" height="20" rx="10" fill="rgb(17,17,19)"/><rect x="135.5" y="32.5" width="19" height="19" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="141.41" y="46.5" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="11" font-weight="650" fill="rgb(174,174,178)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, &quot;-apple-system&quot;, sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></svg>