@kerfjs/ui 5.0.0-beta.15 → 5.0.0-beta.17
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.
- package/README.md +3 -2
- package/ai/component-catalog.json +2 -1
- package/ai/public-api-signatures-v1.md +30 -3
- package/ai/skill.md +2 -2
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/catalog.d.ts +2 -0
- package/dist/catalog.js +6 -2
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-LCOBDOCC.js → chunk-6NLRBSVX.js} +32 -3
- package/dist/chunk-6NLRBSVX.js.map +1 -0
- package/dist/chunk-AHQI52QO.js +11 -0
- package/dist/chunk-AHQI52QO.js.map +1 -0
- package/dist/{chunk-BLK3UEEI.js → chunk-WRTAQ7BZ.js} +2 -2
- package/dist/{chunk-BLK3UEEI.js.map → chunk-WRTAQ7BZ.js.map} +1 -1
- package/dist/chunk-WXMGNX2Y.js +38 -0
- package/dist/chunk-WXMGNX2Y.js.map +1 -0
- package/dist/{chunk-XE5ZLPCC.js → chunk-ZQQ6P4SV.js} +2 -2
- package/dist/{chunk-XE5ZLPCC.js.map → chunk-ZQQ6P4SV.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/list-inset-text.d.ts +10 -1
- package/dist/list-inset-text.js +1 -1
- package/dist/nav-stack.js +1 -1
- package/dist/panel-header.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/styles/catalog.css +22 -1
- package/dist/styles/list-inset-text.css +9 -0
- package/dist/styles/toolbar-text.css +54 -2
- package/dist/styles/webawesome.css +131 -0
- package/dist/toolbar-text.d.ts +17 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/docs/catalog.md +4 -3
- package/docs/component-selection.md +6 -3
- package/docs/ux-demo.md +2 -2
- package/docs/webawesome-theme.md +65 -0
- package/llms.txt +16 -1
- package/package.json +1 -1
- package/dist/chunk-LCOBDOCC.js.map +0 -1
- package/dist/chunk-RUNWEPR4.js +0 -10
- package/dist/chunk-RUNWEPR4.js.map +0 -1
- package/dist/chunk-XE4OX6AZ.js +0 -10
- package/dist/chunk-XE4OX6AZ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
export { wireResizableRegions } from './chunk-AQNKJRFH.js';
|
|
2
2
|
export { reorderTabs, wireTabBars } from './chunk-XXMOARTH.js';
|
|
3
|
-
export { wireTokenSearchFields } from './chunk-
|
|
3
|
+
export { wireTokenSearchFields } from './chunk-6NLRBSVX.js';
|
|
4
4
|
export { TabBar } from './chunk-AVZHJN6C.js';
|
|
5
5
|
export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-7LDCTU7D.js';
|
|
6
6
|
export { ValueTable, ValueTableRow } from './chunk-37T3VNIZ.js';
|
|
7
|
-
export { PanelHeader } from './chunk-
|
|
7
|
+
export { PanelHeader } from './chunk-ZQQ6P4SV.js';
|
|
8
8
|
export { SegmentedControl } from './chunk-YGN7OMLT.js';
|
|
9
9
|
export { Select } from './chunk-CH4SQ6H5.js';
|
|
10
10
|
export { ResizableRegion, clampRegionSize, resizeRegionFromPointer } from './chunk-M5JRI6MN.js';
|
|
11
11
|
export { StateBanner } from './chunk-I7INRJO4.js';
|
|
12
12
|
export { ListActionRow } from './chunk-7JB7VPRI.js';
|
|
13
13
|
export { ListInsetControl } from './chunk-VPCTCUED.js';
|
|
14
|
-
export { ListInsetText } from './chunk-
|
|
15
|
-
export { ToolbarText } from './chunk-
|
|
14
|
+
export { ListInsetText } from './chunk-AHQI52QO.js';
|
|
15
|
+
export { ToolbarText } from './chunk-WXMGNX2Y.js';
|
|
16
16
|
export { AppTab } from './chunk-2Z5TWHKQ.js';
|
|
17
17
|
export { ToolbarControlGroup } from './chunk-RNPGFQ33.js';
|
|
18
18
|
export { Toolbar } from './chunk-DAFFDO33.js';
|
|
@@ -3,6 +3,13 @@ import { SafeHtml } from 'kerfjs';
|
|
|
3
3
|
interface ListInsetTextProps {
|
|
4
4
|
/** Text (or inline content) that carries no margin, border, or padding of its own. */
|
|
5
5
|
children: SafeHtml | SafeHtml[] | string;
|
|
6
|
+
/**
|
|
7
|
+
* Keep only the horizontal geometry (inline margin, left/right border, and
|
|
8
|
+
* left/right padding) and drop the vertical margin, border, and padding. Use it
|
|
9
|
+
* when the text edge must still align with bordered items but the line should not
|
|
10
|
+
* add its own vertical box space — tight text layout inside a content region.
|
|
11
|
+
*/
|
|
12
|
+
horizontalOnly?: boolean;
|
|
6
13
|
className?: string;
|
|
7
14
|
}
|
|
8
15
|
/**
|
|
@@ -10,7 +17,9 @@ interface ListInsetTextProps {
|
|
|
10
17
|
* transparent border, and 8px padding — so a plain string lines up with
|
|
11
18
|
* bordered `.kui-content` items (its text edge lands at the same 17px inset).
|
|
12
19
|
* Use it for text elements that have no margin, border, or padding of their own.
|
|
20
|
+
* Pass `horizontalOnly` to keep the horizontal inset but drop the vertical box
|
|
21
|
+
* space for tight text layout.
|
|
13
22
|
*/
|
|
14
|
-
declare function ListInsetText({ children, className }: ListInsetTextProps): SafeHtml;
|
|
23
|
+
declare function ListInsetText({ children, horizontalOnly, className }: ListInsetTextProps): SafeHtml;
|
|
15
24
|
|
|
16
25
|
export { ListInsetText, type ListInsetTextProps };
|
package/dist/list-inset-text.js
CHANGED
package/dist/nav-stack.js
CHANGED
package/dist/panel-header.js
CHANGED
package/dist/split-view.js
CHANGED
package/dist/styles/catalog.css
CHANGED
|
@@ -104,7 +104,28 @@
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
.kui-catalog__items .kui-list-item {
|
|
107
|
-
grid-template-columns: minmax(0, 1fr);
|
|
107
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.kui-catalog__tags {
|
|
111
|
+
display: inline-flex;
|
|
112
|
+
min-width: 0;
|
|
113
|
+
flex-wrap: wrap;
|
|
114
|
+
justify-content: flex-end;
|
|
115
|
+
gap: var(--kui-space-2xs);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.kui-catalog__tag {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
padding: 0.125rem 0.375rem;
|
|
121
|
+
border: 1px solid var(--kui-color-warning-border-quiet);
|
|
122
|
+
border-radius: 999px;
|
|
123
|
+
color: var(--kui-color-warning-text);
|
|
124
|
+
background: var(--kui-color-warning);
|
|
125
|
+
font-size: var(--kui-font-2xs);
|
|
126
|
+
font-weight: 650;
|
|
127
|
+
line-height: 1.2;
|
|
128
|
+
white-space: nowrap;
|
|
108
129
|
}
|
|
109
130
|
|
|
110
131
|
.kui-catalog__group--secondary {
|
|
@@ -3,3 +3,12 @@
|
|
|
3
3
|
border: 1px solid transparent;
|
|
4
4
|
padding: 0.5rem;
|
|
5
5
|
}
|
|
6
|
+
|
|
7
|
+
/* Horizontal-only: keep the inline inset (margin + left/right border + left/right
|
|
8
|
+
padding) so the text edge still aligns with bordered items, but drop the vertical
|
|
9
|
+
box space for tight text layout. */
|
|
10
|
+
.kui-list-inset-text--horizontal {
|
|
11
|
+
margin-block: 0;
|
|
12
|
+
border-block: 0;
|
|
13
|
+
padding-block: 0;
|
|
14
|
+
}
|
|
@@ -9,11 +9,19 @@
|
|
|
9
9
|
color: var(--kui-color-neutral-on-quiet);
|
|
10
10
|
font-weight: 650;
|
|
11
11
|
line-height: 1;
|
|
12
|
-
text-overflow: ellipsis;
|
|
13
|
-
white-space: nowrap;
|
|
14
12
|
align-items: center;
|
|
15
13
|
}
|
|
16
14
|
|
|
15
|
+
/* The text lives in a block child, not directly in the flex box, so
|
|
16
|
+
`text-overflow: ellipsis` actually applies (it is a no-op on a flex item). */
|
|
17
|
+
.kui-toolbar-text__text {
|
|
18
|
+
min-width: 0;
|
|
19
|
+
max-width: 100%;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
white-space: nowrap;
|
|
22
|
+
text-overflow: ellipsis;
|
|
23
|
+
}
|
|
24
|
+
|
|
17
25
|
.kui-toolbar-text[data-size="xlarge"] {
|
|
18
26
|
/* Matches the page/panel title: the same responsive clamp so a PanelHeader
|
|
19
27
|
title reads at the page-title scale without a bespoke override. Height grows
|
|
@@ -38,3 +46,47 @@
|
|
|
38
46
|
font-family: var(--kui-font-mono);
|
|
39
47
|
font-size: var(--kui-font-xs);
|
|
40
48
|
}
|
|
49
|
+
|
|
50
|
+
/* Single line, no ellipsis: hard-clip the overflow instead of showing …. */
|
|
51
|
+
.kui-toolbar-text[data-ellipsis="false"] .kui-toolbar-text__text {
|
|
52
|
+
text-overflow: clip;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Wrap onto multiple lines. The box grows to fit and switches from the centered
|
|
56
|
+
single-line row to a top-aligned block with readable leading; a min-height keeps
|
|
57
|
+
a one-line label at the toolbar row height. */
|
|
58
|
+
.kui-toolbar-text[data-wrap="true"] {
|
|
59
|
+
align-items: flex-start;
|
|
60
|
+
height: auto;
|
|
61
|
+
min-height: 2.5rem;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.kui-toolbar-text[data-size="xlarge"][data-wrap="true"] {
|
|
65
|
+
min-height: 2.75rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.kui-toolbar-text[data-wrap="true"] .kui-toolbar-text__text {
|
|
69
|
+
white-space: normal;
|
|
70
|
+
line-height: 1.25;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Wrap capped to N lines with an ellipsis at the cut. `-webkit-line-clamp` needs
|
|
74
|
+
the box display and emits the … itself; the unprefixed `line-clamp` follows for
|
|
75
|
+
engines that ship it. */
|
|
76
|
+
.kui-toolbar-text[data-wrap="true"][data-max-lines] .kui-toolbar-text__text {
|
|
77
|
+
display: -webkit-box;
|
|
78
|
+
-webkit-box-orient: vertical;
|
|
79
|
+
-webkit-line-clamp: var(--kui-toolbar-text-max-lines);
|
|
80
|
+
line-clamp: var(--kui-toolbar-text-max-lines);
|
|
81
|
+
overflow: hidden;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Wrap capped to N lines without an ellipsis: clip at a max-height instead of
|
|
85
|
+
line-clamp (which always ellipsizes). */
|
|
86
|
+
.kui-toolbar-text[data-wrap="true"][data-max-lines][data-ellipsis="false"]
|
|
87
|
+
.kui-toolbar-text__text {
|
|
88
|
+
display: block;
|
|
89
|
+
-webkit-line-clamp: none;
|
|
90
|
+
line-clamp: none;
|
|
91
|
+
max-height: calc(var(--kui-toolbar-text-max-lines) * 1.25em);
|
|
92
|
+
}
|
|
@@ -175,6 +175,19 @@
|
|
|
175
175
|
--wa-form-control-border-color: var(--wa-color-neutral-border-normal);
|
|
176
176
|
--wa-form-control-border-radius: var(--wa-border-radius-m);
|
|
177
177
|
--wa-form-control-activated-color: var(--wa-color-brand-fill-loud);
|
|
178
|
+
/* Field inset: a 1px border with 8px inside it, the same content-item
|
|
179
|
+
geometry the Kerf primitives use (docs/layout.md). WA's defaults are a
|
|
180
|
+
larger 0.75em/1em pad; this brings every form field onto our 8px rhythm
|
|
181
|
+
(and a ~40px single-line control height). */
|
|
182
|
+
--wa-form-control-border-width: var(--kui-layout-item-border-width, 1px);
|
|
183
|
+
--wa-form-control-padding-block: var(
|
|
184
|
+
--kui-layout-item-padding,
|
|
185
|
+
0.5rem
|
|
186
|
+
);
|
|
187
|
+
--wa-form-control-padding-inline: var(
|
|
188
|
+
--kui-layout-item-padding,
|
|
189
|
+
0.5rem
|
|
190
|
+
);
|
|
178
191
|
--wa-panel-border-radius: var(--wa-border-radius-l);
|
|
179
192
|
--wa-tooltip-background-color: var(--wa-color-neutral-fill-loud);
|
|
180
193
|
--wa-tooltip-content-color: var(--wa-color-neutral-on-loud);
|
|
@@ -184,6 +197,13 @@
|
|
|
184
197
|
--kui-wa-carousel-dot-hit-size: 20px;
|
|
185
198
|
--kui-wa-carousel-control-size: 28px;
|
|
186
199
|
--kui-wa-carousel-icon-size: 16px;
|
|
200
|
+
/* Non-field chrome uses Kerf's control, surface, and container spacing:
|
|
201
|
+
8px inside controls/surfaces, 8px around bordered surfaces, and 16px
|
|
202
|
+
inside the remaining content containers. */
|
|
203
|
+
--kui-wa-control-inset: var(--kui-layout-item-padding, 0.5rem);
|
|
204
|
+
--kui-wa-surface-inset: var(--kui-layout-item-padding, 0.5rem);
|
|
205
|
+
--kui-wa-surface-margin: var(--kui-layout-inline-margin, 0.5rem);
|
|
206
|
+
--kui-wa-container-inset: var(--kui-space-m, 1rem);
|
|
187
207
|
--kui-disclosure-icon-scale: 0.5;
|
|
188
208
|
--wa-shadow-s: 0 1px 3px rgb(0 0 0 / 0.14);
|
|
189
209
|
--wa-shadow-m: 0 0.35rem 1rem rgb(0 0 0 / 0.11);
|
|
@@ -248,9 +268,120 @@
|
|
|
248
268
|
transform: scale(var(--kui-disclosure-icon-scale));
|
|
249
269
|
}
|
|
250
270
|
|
|
271
|
+
/* Bordered/fill surfaces follow the same 8px outer margin + 8px inner
|
|
272
|
+
padding contract as a Kerf content item. Accordion owns one outer margin
|
|
273
|
+
for the group; its items retain connected borders. */
|
|
274
|
+
:is(wa-accordion, wa-card, wa-details, wa-callout, wa-include) {
|
|
275
|
+
margin-inline: var(--kui-wa-surface-margin);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
wa-card,
|
|
279
|
+
wa-details,
|
|
280
|
+
wa-accordion-item {
|
|
281
|
+
/* WA declares this custom property on :host inside each shadow root. The
|
|
282
|
+
important flag is required for a public host override to cross that
|
|
283
|
+
encapsulation boundary. */
|
|
284
|
+
--spacing: var(--kui-wa-surface-inset) !important;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/* Card halves --spacing for its header block padding upstream, so pin the
|
|
288
|
+
public part to the same full surface inset as its body and footer. */
|
|
289
|
+
wa-card::part(header) {
|
|
290
|
+
padding: var(--kui-wa-surface-inset);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
wa-callout {
|
|
294
|
+
padding: var(--kui-wa-surface-inset) !important;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
wa-include {
|
|
298
|
+
padding: var(--kui-wa-surface-inset);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Interactive and item chrome follows the content-item 8px inset. */
|
|
302
|
+
wa-tab::part(tab) {
|
|
303
|
+
padding: var(--kui-wa-control-inset);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
wa-tab-panel {
|
|
307
|
+
--padding: var(--kui-wa-container-inset) 0 !important;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
wa-tree-item::part(item) {
|
|
311
|
+
margin-inline: var(--kui-layout-inline-margin, 0.5rem);
|
|
312
|
+
padding-inline-end: var(--kui-wa-control-inset);
|
|
313
|
+
border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
wa-tag {
|
|
317
|
+
padding-inline: var(--kui-wa-control-inset) !important;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
wa-dropdown-item {
|
|
321
|
+
padding-inline: var(--kui-wa-control-inset) !important;
|
|
322
|
+
}
|
|
323
|
+
|
|
251
324
|
wa-popover {
|
|
252
325
|
--arrow-size: var(--kui-wa-popover-arrow-size);
|
|
253
326
|
}
|
|
327
|
+
|
|
328
|
+
/* A form field's top label is inset by the field's own border + inline padding
|
|
329
|
+
(1px + 8px = 9px) so the label text lines up with the value inside the field,
|
|
330
|
+
and it is styled exactly like a ListHeader label: uppercase, xs, quiet. */
|
|
331
|
+
:is(
|
|
332
|
+
wa-checkbox-group,
|
|
333
|
+
wa-color-picker,
|
|
334
|
+
wa-input,
|
|
335
|
+
wa-known-date,
|
|
336
|
+
wa-number-input,
|
|
337
|
+
wa-radio-group,
|
|
338
|
+
wa-select,
|
|
339
|
+
wa-textarea,
|
|
340
|
+
wa-time-input
|
|
341
|
+
)::part(form-control-label),
|
|
342
|
+
wa-otp-input::part(label),
|
|
343
|
+
wa-slider::part(label) {
|
|
344
|
+
padding-inline: calc(
|
|
345
|
+
var(--wa-form-control-border-width) +
|
|
346
|
+
var(--wa-form-control-padding-inline)
|
|
347
|
+
);
|
|
348
|
+
color: var(--kui-color-neutral-on-quiet, var(--wa-color-text-quiet));
|
|
349
|
+
font-size: var(--kui-font-xs, var(--wa-font-size-xs));
|
|
350
|
+
font-weight: 650;
|
|
351
|
+
letter-spacing: 0.04em;
|
|
352
|
+
line-height: var(--wa-line-height-condensed);
|
|
353
|
+
text-transform: uppercase;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* Checkbox/radio groups and the color picker have no bordered field shell,
|
|
357
|
+
so their control regions need the content-item's 8px inline outer inset. */
|
|
358
|
+
:is(wa-checkbox-group, wa-color-picker, wa-radio-group)::part(
|
|
359
|
+
form-control-input
|
|
360
|
+
) {
|
|
361
|
+
margin-inline: var(--kui-layout-inline-margin, 0.5rem);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
wa-slider::part(slider) {
|
|
365
|
+
margin-inline: var(--kui-layout-inline-margin, 0.5rem);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/* Secondary captions and hints align with the value inside bordered fields:
|
|
369
|
+
1px border + 8px field padding = a 9px logical inset. */
|
|
370
|
+
wa-known-date::part(field-label),
|
|
371
|
+
:is(
|
|
372
|
+
wa-input,
|
|
373
|
+
wa-known-date,
|
|
374
|
+
wa-number-input,
|
|
375
|
+
wa-otp-input,
|
|
376
|
+
wa-select,
|
|
377
|
+
wa-textarea,
|
|
378
|
+
wa-time-input
|
|
379
|
+
)::part(hint) {
|
|
380
|
+
padding-inline: calc(
|
|
381
|
+
var(--wa-form-control-border-width) +
|
|
382
|
+
var(--wa-form-control-padding-inline)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
254
385
|
}
|
|
255
386
|
|
|
256
387
|
@media (prefers-contrast: more) {
|
package/dist/toolbar-text.d.ts
CHANGED
|
@@ -17,7 +17,23 @@ interface ToolbarTextProps {
|
|
|
17
17
|
headingLevel?: HeadingLevel;
|
|
18
18
|
/** Render the text as an unanimated loading skeleton instead of its value. */
|
|
19
19
|
placeholder?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Wrap onto multiple lines when the text does not fit, instead of the default
|
|
22
|
+
* single line. Combine with `maxLines` to cap the number of lines. Default false.
|
|
23
|
+
*/
|
|
24
|
+
wrap?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Show a trailing ellipsis (…) where the text is truncated — on the single line
|
|
27
|
+
* (default), or at the `maxLines` boundary when wrapping. Set false to hard-clip
|
|
28
|
+
* instead. Default true.
|
|
29
|
+
*/
|
|
30
|
+
ellipsis?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Cap wrapped text to this many lines, truncating past it. Only takes effect with
|
|
33
|
+
* `wrap`; ignored on a single line. `null`/omitted wraps without a line cap. Default null.
|
|
34
|
+
*/
|
|
35
|
+
maxLines?: number | null;
|
|
20
36
|
}
|
|
21
|
-
declare function ToolbarText({ text, size, className, id, headingLevel, placeholder }: ToolbarTextProps): kerfjs.SafeHtml;
|
|
37
|
+
declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, }: ToolbarTextProps): kerfjs.SafeHtml;
|
|
22
38
|
|
|
23
39
|
export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
|
package/dist/toolbar-text.js
CHANGED
package/docs/catalog.md
CHANGED
|
@@ -22,8 +22,9 @@ npm install @kerfjs/ui # kerfjs is a peer; @kerfjs/ui/select/register is neede
|
|
|
22
22
|
## What you supply
|
|
23
23
|
|
|
24
24
|
- **`sections`** — category-grouped entries: `{ category, entries: [{ id, name,
|
|
25
|
-
description?, resources?, related? }] }`. Each entry becomes a sidebar
|
|
26
|
-
under a `ListHeader` for its category.
|
|
25
|
+
description?, tags?, resources?, related? }] }`. Each entry becomes a sidebar
|
|
26
|
+
`ListItem` under a `ListHeader` for its category. Short `tags` render as quiet
|
|
27
|
+
trailing pills for decision metadata such as `Discouraged`.
|
|
27
28
|
- **`content`** — the rendered preview for the active entry. Keep a map of `id →
|
|
28
29
|
() => SafeHtml` in your app and call `renderers[active]()` in your render.
|
|
29
30
|
- **`brand`** — `{ title, subtitle?, logoUrl? }` for the sidebar header.
|
|
@@ -86,7 +87,7 @@ const sections: CatalogSection[] = [
|
|
|
86
87
|
entries: [
|
|
87
88
|
{ id: 'button', name: 'Button', description: 'A pressable control.',
|
|
88
89
|
resources: [{ label: 'Source', href: '/src/button.tsx', detail: 'src/button.tsx' }] },
|
|
89
|
-
{ id: 'field', name: 'Field', description: 'A labeled input.',
|
|
90
|
+
{ id: 'field', name: 'Field', description: 'A labeled input.', tags: ['Discouraged'],
|
|
90
91
|
related: [{ id: 'button', name: 'Button', group: 'Used with' }] },
|
|
91
92
|
],
|
|
92
93
|
},
|
|
@@ -65,12 +65,12 @@ an upstream component or recipe request.
|
|
|
65
65
|
| Application toolbar — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar. | Do not use it for a page, panel, or dialog heading; use `PanelHeader`. | Compose `ToolbarText` and `ToolbarControlGroup` where their contracts fit. | Actions, command availability, responsive relocation, and state. | `@kerfjs/ui/toolbar` | [Toolbar composition](../README.md#component-subpaths) |
|
|
66
66
|
| Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained, borderless, pressed, or single-control treatment. | Do not use it merely to align unrelated buttons; use toolbar slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
67
67
|
| Floating controls over content — `FloatingToolbar` | A small cluster of controls (e.g. a drawer restore) must float over scrolling content — distinct and forced-dark — inside a positioned container. | Do not use it for a primary page or panel toolbar (use `Toolbar`), or for anything that must sit above dialogs/overlays — it is not top-layer. | Compose `ToolbarControlGroup`s and delegate their actions; the app owns visibility and position. | Controls, visibility, and position. | `@kerfjs/ui/floating-toolbar` | [Component subpaths](../README.md#component-subpaths) |
|
|
68
|
-
| Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel` (or prefer `PanelHeader`, which forwards it). | Optional `headingLevel` for `role="heading"` + `aria-level`. | Text, heading level, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
|
|
68
|
+
| Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel` (or prefer `PanelHeader`, which forwards it). | Optional `headingLevel` for `role="heading"` + `aria-level`. Defaults to one line, ellipsized when it does not fit; `wrap` flows onto multiple lines, `ellipsis` toggles the trailing …, and `maxLines` caps a wrap. | Text, heading level, overflow behavior, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
|
|
69
69
|
| Navigation row — `ListItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `ListActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
70
70
|
| Navigation row with trailing action — `ListActionRow` | A full-width row needs a selectable primary action and an independently focusable trailing action. | Use `ListItem` when trailing content is dormant metadata. Do not put controls inside the row's `label`, `icon`, or `trailingActionIcon` SafeHtml slots. Do not use `AppTab` outside tablist semantics or `ToolbarControlGroup` outside a toolbar. | Delegate both action strings; update controlled selection and any popover/context-menu state in the app. | Routing, selection, both action policies, domain metadata, and popover/context-menu behavior. | `@kerfjs/ui/list-action-row` | [Accessibility](./accessibility.md#listactionrow) |
|
|
71
71
|
| Navigation section heading — `ListHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing. Do not shrink its 44px action target to the 18px visual. Do not use it as a page, panel, or dialog title; use `PanelHeader`. | Delegate its optional action; the app controls expanded state and revealed content. Toggle mode supplies `DisclosureArrow` unless `actionIcon` replaces it. Use `triggerAttributes` only for domain `data-*` or a native popover relationship. | Section organization, valid count and localized count label, disclosure state and content, non-count badge content, popover target behavior, and policy. | `@kerfjs/ui/list-header` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
72
72
|
| Inset self-bordered control — `ListInsetControl` | A control that owns its own border and padding but no outer margin (a search input, a `SegmentedControl`) must line up inside a `.kui-content` list with the standard 8px inline margins and stretch to fill the row. | Do not wrap a `.kui-content-item` or a `ListItem`/`ListHeader` that already owns its inline margin — that double-insets it. Do not add ad-hoc `margin`/`padding` around a bare control to align it; use this instead. | Place the self-bordered control(s) as children; they stretch to fill. It applies only the inline margin, flex stretch, and 8px gap — the child owns its own border and padding. | The control(s), their state, and action wiring. | `@kerfjs/ui/list-inset-control` | [Pane geometry](../README.md#component-subpaths) |
|
|
73
|
-
| Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text` | [Pane geometry](../README.md#component-subpaths) |
|
|
73
|
+
| Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. Pass `horizontalOnly` to keep that horizontal inset but drop the vertical margin, border, and padding for tight text layout. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text` | [Pane geometry](../README.md#component-subpaths) |
|
|
74
74
|
| Application layout composition | A sidebar, main area, inspector, or dialog needs shared toolbar/content/footer and child geometry. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Use `.kui-pane` and one `.kui-pane__content`; add `.kui-content` and `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, scroll ownership, responsive relocation, and pane visibility state. | `@kerfjs/ui/layout.css` | [Pane anatomy](./layout.md#anatomy) |
|
|
75
75
|
| Menu composition | Navigation sections need full-size rows and the same content-item geometry as every other pane. | Do not add sidebar-specific wrapper padding, shrink targets to icon size, nest an interactive trailing control in `ListItem`, or use a chevron on a row that does not disclose content. Use ordinary links for a different navigation contract. | Compose `ListHeader`, `ListItem`, and `ListActionRow` in `.kui-content`; use `ListHeader` toggle mode with real controlled content, and use `.kui-content-item` for other surfaces plus a pane footer for toolbar actions. | Information architecture, disclosure content and state, responsive drawer/shell behavior, and token overrides. | `@kerfjs/ui/layout.css` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
76
76
|
| Resizable application pane — `ResizableRegion`, `clampRegionSize`, `resizeRegionFromPointer` | A controlled split pane needs the Kerf separator, collapse state, pointer plus keyboard resizing, or a product-specific decorative grip. | Do not use it for a static two-column layout; use CSS grid. Prefer it over Web Awesome `wa-split-panel` unless that component's distinct API is required. Keep `handleIcon` noninteractive. | Call `wireResizableRegions` from `@kerfjs/ui/wire-resizable-regions` once and retain its disposer. | Size signal, min/max policy, collapse policy, persistence, and optional decorative handle icon. | `@kerfjs/ui/resizable-region` | [ResizableRegion contract](./accessibility.md#resizableregion) |
|
|
@@ -167,7 +167,10 @@ forks the package anatomy and spacing contract.
|
|
|
167
167
|
|
|
168
168
|
Web Awesome catalog coverage means supported and themed, not preferred. Import
|
|
169
169
|
`@kerfjs/ui/webawesome` for Kerf JSX types, individual component modules for
|
|
170
|
-
registration, and the CSS-only `@kerfjs/ui/webawesome.css` theme.
|
|
170
|
+
registration, and the CSS-only `@kerfjs/ui/webawesome.css` theme. The UX catalog
|
|
171
|
+
marks the superseded or exceptional choices below with a visible `Discouraged`
|
|
172
|
+
tag; Popup remains untagged because low-level anchored positioning can be the
|
|
173
|
+
right primitive.
|
|
171
174
|
|
|
172
175
|
| Web Awesome choice | Kerf decision |
|
|
173
176
|
| --- | --- |
|
package/docs/ux-demo.md
CHANGED
|
@@ -10,9 +10,9 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
10
10
|
- The `ListActionRow` route demonstrates sibling primary/trailing native controls, independent disabled states, controlled selection, first-line leading-icon alignment for wrapped labels, and an application-owned native popover relationship without nesting controls. The `ListItem` route demonstrates the same multiline leading-icon anchor alongside its single-control navigation contract.
|
|
11
11
|
- The `AppTab` route demonstrates a runtime-filtered domain metadata slot and a decorative replacement close icon without changing TabBar selection, close, reorder, or focus ownership. The `ResizableRegion` route likewise replaces only the decorative handle glyph while retaining separator semantics and shared wiring.
|
|
12
12
|
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu, feedback, and theme scenarios remain addressable alongside their subcomponents; the root opens the first Kerf component.
|
|
13
|
-
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Demo paths resolve to `ui/ux-demo/
|
|
13
|
+
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, recommendation, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Non-supported Web Awesome recommendations project to a visible `Discouraged` sidebar tag, with Popup as the deliberate conditional exception. Demo paths resolve to the matching `ui/ux-demo/demos/<id>.tsx` or `ui/ux-demo/recipes/*.tsx` file, or to `ui/ux-demo/webawesome-demos.tsx` for Web Awesome entries. `ui/ux-demo/main.tsx` owns only the catalog shell, shared state, routing, and interaction wiring. First-party component entries additionally derive `ui/src/<browser-subpath>.tsx` from their canonical `delivery.browserImport`.
|
|
14
14
|
- Every detail footer groups compact `Demo source` and `Guidance` actions; first-party component details also expose `Component source`. Web Awesome details say `Integration guidance` to distinguish the local integration contract from the upstream component implementation. Each button retains its repository-relative path in the DOM for verification and uses a deploy-safe absolute GitHub blob URL with a contextual new-tab name; the demo does not depend on a local source server or add a package runtime export. At phone widths, the resource group and related-component selector stack as full-width rows, with any resource overflow contained locally so labels cannot overlap the selector or widen the document.
|
|
15
|
-
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
15
|
+
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. Catalog entries can supply short reusable trailing tags; the Web Awesome projection uses them to label exactly the 15 discouraged choices. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
16
16
|
- The shell itself uses `@kerfjs/ui/layout.css`: sidebars, details, previews, dialogs, and resize specimens share unpadded panes plus self-contained content items. Its sidebar identity uses the Kerf logo beside a vertically centered title, with the subtitle in its own aligned row like `PanelHeader`; the current-view heading is also a toolbar. Collapsing the catalog removes the pane completely and moves its restore action to the main toolbar's leading edge instead of leaving an icon-only rail. The selected view description remains inset below the page toolbar. The checkerboard belongs to the complete scrollable preview region rather than a nested card. A lightly separated footer keeps live status above compact source, guidance, and relationship groups. The focused `ResizableRegion` specimen stretches its surface through the available stage height and reports committed width in that shared status footer; narrow layouts retain local horizontal access when the pane is resized wider than the stage, and the split remains readable at 200% root scaling. Geometry coverage checks wide, intermediate, narrow, and 200% zoom layouts.
|
|
17
17
|
- The composer-form recipe demonstrates one coherent visible form surface with `PanelHeader` title/summary hierarchy, fields and actions on the shared 8px control gutter, and 24px major rhythm. Its conditional error or success `StateBanner` is the only nested semantic surface. Reset synchronizes the upgraded Web Awesome fields' live value properties with their empty controlled attributes and announces `Draft reset`; browser coverage preserves behavior and verifies wide, narrow, dark, validation, success, reset, 200% zoom, and forced-colors states.
|
|
18
18
|
- The list-detail dialog recipe places its header directly on the dialog edge while preserving the header's internal inset, gives the selected project title the complete outer-plus-inner content gutter, lets the value table fill the available detail column between the shared outer margins, and keeps record actions on one outer gutter without an extra content-item inset. Browser geometry coverage protects those relationships at wide and narrow widths.
|
package/docs/webawesome-theme.md
CHANGED
|
@@ -54,6 +54,71 @@ pointer targets. Override `--kui-wa-carousel-icon-size`,
|
|
|
54
54
|
`--kui-wa-carousel-dot-hit-size` on a carousel or containing scope when a
|
|
55
55
|
product needs different geometry.
|
|
56
56
|
|
|
57
|
+
Form fields carry the same content-item inset as the Kerf primitives: a 1px
|
|
58
|
+
border with 8px inside it (`--wa-form-control-border-width`,
|
|
59
|
+
`--wa-form-control-padding-block`, and `--wa-form-control-padding-inline` are set
|
|
60
|
+
to the `--kui-layout-item-border-width` / `--kui-layout-item-padding` values), so
|
|
61
|
+
a single-line control lands at the standard ~40px height and the value sits 9px
|
|
62
|
+
in from the field edge. Each field's top label is inset by that same border +
|
|
63
|
+
padding (9px) so it lines up with the value inside the field, and is styled
|
|
64
|
+
exactly like a `ListHeader` label — uppercase, `--kui-font-xs`, weight 650, quiet
|
|
65
|
+
foreground. This applies to every free field that exposes a top label
|
|
66
|
+
(`::part(form-control-label)` plus the Slider's `::part(label)`). OTP Input
|
|
67
|
+
exposes `label` instead of `form-control-label`; the theme gives it the same
|
|
68
|
+
uppercase 12px/650 treatment. Inline control labels (Checkbox, Switch) keep
|
|
69
|
+
their natural sentence case.
|
|
70
|
+
|
|
71
|
+
Known Date's field captions and bordered text-like field hints use the same 9px
|
|
72
|
+
inline inset, keeping secondary text aligned with the value rather than the
|
|
73
|
+
field's outer border. This covers Input, Known Date, Number Input, OTP Input,
|
|
74
|
+
Select, Textarea, and Time Input hints; unbordered group hints retain their own
|
|
75
|
+
natural geometry. OTP Input's label and hint both use the 9px field-text inset.
|
|
76
|
+
|
|
77
|
+
Checkbox Group and Radio Group option regions receive the shared 8px inline
|
|
78
|
+
outer inset through `::part(form-control-input)`. Unlike bordered fields, these
|
|
79
|
+
groups have no shell of their own, so the explicit margin places their controls
|
|
80
|
+
on the same content-item geometry without adding padding to each option. The
|
|
81
|
+
Color Picker trigger receives the same 8px inline outer inset because it also
|
|
82
|
+
has no bordered field shell. Slider's complete interactive region receives the
|
|
83
|
+
shared 8px logical inline outer inset through `::part(slider)`, keeping its
|
|
84
|
+
track, markers, references, and hint together without moving the label.
|
|
85
|
+
|
|
86
|
+
Non-field chrome follows explicit, overridable control, surface, and container
|
|
87
|
+
tiers:
|
|
88
|
+
|
|
89
|
+
- `--kui-wa-control-inset` defaults to the 8px content-item padding. It applies
|
|
90
|
+
to tabs, tree-item trailing content, tags, and dropdown items. Tree selection
|
|
91
|
+
also uses Kerf's 8px inline outer margin, so its background reads as an inset
|
|
92
|
+
list item instead of an edge-to-edge stripe. Buttons already consume the same
|
|
93
|
+
`--wa-form-control-padding-inline` 8px value at every size, so no extra part
|
|
94
|
+
override is needed.
|
|
95
|
+
- `--kui-wa-surface-margin` and `--kui-wa-surface-inset` default to 8px.
|
|
96
|
+
Accordion, Card, Details, Callout, and Include use the margin around their
|
|
97
|
+
complete surface and the inset within it. Accordion applies the outer margin
|
|
98
|
+
once to the group rather than separating connected items; Card's header,
|
|
99
|
+
body, and footer all receive the full inset.
|
|
100
|
+
- `--kui-wa-container-inset` defaults to the 16px homogeneous-group step. Tab
|
|
101
|
+
Panel retains this roomier tier for unframed panel content.
|
|
102
|
+
|
|
103
|
+
Badge remains intentionally compact at Web Awesome's intrinsic `0.375em` block /
|
|
104
|
+
`0.625em` inline padding (4.5px / 7.5px at its default 12px text size): it is a
|
|
105
|
+
short status or count, not a content item. Breadcrumb has no bordered or filled
|
|
106
|
+
container, and Scroller delegates item chrome to its slotted children, so both
|
|
107
|
+
retain their upstream geometry. Web Awesome 3.12's free catalog has
|
|
108
|
+
`wa-dropdown-item`, but no `wa-menu-item`; the theme therefore styles the
|
|
109
|
+
supported dropdown item rather than carrying a dead selector.
|
|
110
|
+
|
|
111
|
+
Override a tier for a product scope after importing the theme:
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
.roomy-editor {
|
|
115
|
+
--kui-wa-control-inset: 0.75rem;
|
|
116
|
+
--kui-wa-surface-margin: 0.75rem;
|
|
117
|
+
--kui-wa-surface-inset: 0.75rem;
|
|
118
|
+
--kui-wa-container-inset: 1.5rem;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
57
122
|
Accordion, Details, Breadcrumb, and Kerf Select share
|
|
58
123
|
`--kui-disclosure-icon-scale` (default `.5`) so disclosure and traversal
|
|
59
124
|
chevrons keep the same visual weight. The Accordion and Details components
|
package/llms.txt
CHANGED
|
@@ -40,6 +40,21 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
40
40
|
own the geometry (8px inline margin + 1px border + 8px padding). Do not add a
|
|
41
41
|
container padding on top of a content-item's own margin — pick one owner. Use
|
|
42
42
|
`.kui-content` for 24px major vertical rhythm.
|
|
43
|
+
- **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
|
|
44
|
+
`--kui-wa-control-inset` (8px controls/items) and
|
|
45
|
+
`--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
|
|
46
|
+
Accordion, Card, Details, Callout, and Include), while
|
|
47
|
+
`--kui-wa-container-inset` keeps Tab Panel at 16px. Override the tier at the
|
|
48
|
+
narrowest useful scope instead of restyling individual shadow parts.
|
|
49
|
+
Checkbox and Radio Group option regions also receive the shared 8px inline
|
|
50
|
+
outer inset because those groups have no bordered field shell. The Color
|
|
51
|
+
Picker trigger receives the same inset for the same unbordered geometry.
|
|
52
|
+
Slider's complete interactive region uses the shared 8px logical inline outer
|
|
53
|
+
inset without shifting its already-aligned label.
|
|
54
|
+
Known Date's Month/Day/Year captions and bordered text-like field hints align
|
|
55
|
+
with field values at the shared 9px border-plus-padding inset. OTP Input's
|
|
56
|
+
label uses the same uppercase xs/650 treatment and its label and hint share
|
|
57
|
+
that 9px alignment.
|
|
43
58
|
- **Trust the defaults.** Render a control at its natural size and color (a
|
|
44
59
|
`LucideIcon` is 24px); if it looks wrong, fix the surrounding layout, not the
|
|
45
60
|
control. Never force a component's width/height to size it — that leaves a halo
|
|
@@ -130,6 +145,6 @@ declared side effects.
|
|
|
130
145
|
- [accessibility.md](./docs/accessibility.md): keyboard and ARIA contracts per component.
|
|
131
146
|
- [recipes.md](./docs/recipes.md): production compositions (app shell, list-detail dialog, composer form, …) as copyable references.
|
|
132
147
|
- [app-layouts.md](./docs/app-layouts.md): choosing `NavStack`/`SplitView`/`Workbench`/`TabScaffold` by data + interaction + device, and dialog presentation.
|
|
133
|
-
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists).
|
|
148
|
+
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists). The UX sidebar visibly tags superseded and exceptional Web Awesome choices as `Discouraged`; Popup remains an available conditional positioning primitive.
|
|
134
149
|
- [component-catalog.json](./ai/component-catalog.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable facts and exact signatures.
|
|
135
150
|
- [README.md](./README.md): package overview and the component subpath table.
|