@kerfjs/ui 5.0.0-beta.60 → 5.0.0-beta.62

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 (142) hide show
  1. package/README.md +1 -0
  2. package/ai/component-catalog.json +141 -24
  3. package/ai/component-composition-rules.json +8 -0
  4. package/ai/component-composition.d.ts +10 -0
  5. package/ai/component-composition.json +117 -8
  6. package/ai/component-composition.schema.json +21 -0
  7. package/ai/components/README.md +5 -4
  8. package/ai/components/chip.md +72 -0
  9. package/ai/components/grid.md +10 -7
  10. package/ai/components/list-item.md +10 -7
  11. package/ai/components/pane.md +3 -2
  12. package/ai/components/select.md +6 -2
  13. package/ai/components/tabs.md +8 -4
  14. package/ai/components/toolbar-text.md +2 -1
  15. package/ai/components/toolbar.md +3 -2
  16. package/ai/public-api-signatures-v1.md +116 -24
  17. package/ai/skill.md +24 -4
  18. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  19. package/dist/app-tab.d.ts +12 -2
  20. package/dist/app-tab.js +1 -1
  21. package/dist/browser/chip.js +3 -0
  22. package/dist/catalog.js +8 -8
  23. package/dist/chip.d.ts +29 -0
  24. package/dist/chip.js +3 -0
  25. package/dist/chip.js.map +1 -0
  26. package/dist/{chunk-WPLIO5WJ.js → chunk-4MG3KXJM.js} +40 -5
  27. package/dist/chunk-4MG3KXJM.js.map +1 -0
  28. package/dist/{chunk-F7F7KRO2.js → chunk-4SQK27MR.js} +33 -18
  29. package/dist/chunk-4SQK27MR.js.map +1 -0
  30. package/dist/chunk-EAC4CDY7.js +57 -0
  31. package/dist/chunk-EAC4CDY7.js.map +1 -0
  32. package/dist/{chunk-T57AXDFM.js → chunk-ENGVYQPG.js} +4 -3
  33. package/dist/chunk-ENGVYQPG.js.map +1 -0
  34. package/dist/{chunk-5PESG2VP.js → chunk-KYDDCJXU.js} +4 -3
  35. package/dist/chunk-KYDDCJXU.js.map +1 -0
  36. package/dist/{chunk-MERWRTBG.js → chunk-N2DRU35S.js} +1 -1
  37. package/dist/chunk-N2DRU35S.js.map +1 -0
  38. package/dist/{chunk-EZVNC4J6.js → chunk-OD2VXAPL.js} +4 -1
  39. package/dist/chunk-OD2VXAPL.js.map +1 -0
  40. package/dist/{chunk-T66UNBXL.js → chunk-Q6YU3BT7.js} +11 -2
  41. package/dist/chunk-Q6YU3BT7.js.map +1 -0
  42. package/dist/{chunk-N3GKMPDW.js → chunk-RKTTF3L4.js} +3 -1
  43. package/dist/chunk-RKTTF3L4.js.map +1 -0
  44. package/dist/chunk-SWVW56CV.js +188 -0
  45. package/dist/chunk-SWVW56CV.js.map +1 -0
  46. package/dist/{chunk-46263QLK.js → chunk-UA6JW52D.js} +53 -7
  47. package/dist/chunk-UA6JW52D.js.map +1 -0
  48. package/dist/{chunk-AGXQQFKZ.js → chunk-UCKKT6KO.js} +13 -4
  49. package/dist/chunk-UCKKT6KO.js.map +1 -0
  50. package/dist/{chunk-3SXMEK3B.js → chunk-V3DX3K65.js} +1 -1
  51. package/dist/chunk-V3DX3K65.js.map +1 -0
  52. package/dist/{chunk-UWONG4QE.js → chunk-VCBTX62E.js} +11 -3
  53. package/dist/chunk-VCBTX62E.js.map +1 -0
  54. package/dist/{chunk-2OXQHM7I.js → chunk-X6ADHJNI.js} +45 -20
  55. package/dist/chunk-X6ADHJNI.js.map +1 -0
  56. package/dist/collapsible-panel.js +2 -2
  57. package/dist/grid.d.ts +13 -5
  58. package/dist/grid.js +1 -1
  59. package/dist/index.d.ts +5 -4
  60. package/dist/index.js +17 -16
  61. package/dist/list-item.d.ts +11 -1
  62. package/dist/list-item.js +1 -1
  63. package/dist/nav-stack.d.ts +3 -1
  64. package/dist/nav-stack.js +1 -1
  65. package/dist/pane.d.ts +8 -3
  66. package/dist/pane.js +1 -1
  67. package/dist/popup-menu.d.ts +2 -2
  68. package/dist/popup-menu.js +1 -1
  69. package/dist/select-register.js +46 -0
  70. package/dist/select-register.js.map +1 -1
  71. package/dist/select.d.ts +16 -0
  72. package/dist/select.js +1 -1
  73. package/dist/split-view.d.ts +1 -1
  74. package/dist/split-view.js +1 -1
  75. package/dist/styles/app-tab.css +119 -0
  76. package/dist/styles/chip.css +118 -0
  77. package/dist/styles/grid.css +7 -0
  78. package/dist/styles/list-item.css +14 -9
  79. package/dist/styles/nav-stack.css +13 -0
  80. package/dist/styles/pane.css +33 -0
  81. package/dist/styles/popup-menu.css +2 -1
  82. package/dist/styles/resizable-region.css +9 -0
  83. package/dist/styles/segmented-control.css +2 -1
  84. package/dist/styles/select.css +45 -0
  85. package/dist/styles/split-view.css +6 -0
  86. package/dist/styles/styles.css +1 -0
  87. package/dist/styles/tab-bar.css +3 -0
  88. package/dist/styles/tab-scaffold.css +13 -0
  89. package/dist/styles/toolbar-text.css +15 -6
  90. package/dist/styles/toolbar.css +15 -5
  91. package/dist/styles/workbench.css +117 -93
  92. package/dist/tab-bar.d.ts +6 -2
  93. package/dist/tab-bar.js +1 -1
  94. package/dist/tab-scaffold.d.ts +3 -0
  95. package/dist/tab-scaffold.js +1 -0
  96. package/dist/tab-scaffold.js.map +1 -1
  97. package/dist/{token-search-field-CCke1yvQ.d.ts → token-search-field-DvgFLhLL.d.ts} +6 -2
  98. package/dist/token-search-field.d.ts +1 -1
  99. package/dist/token-search-model.d.ts +1 -1
  100. package/dist/token-search-model.js +1 -1
  101. package/dist/toolbar-text.d.ts +1 -1
  102. package/dist/toolbar-text.js +1 -1
  103. package/dist/toolbar.d.ts +2 -2
  104. package/dist/toolbar.js +1 -1
  105. package/dist/wire-catalog.js +1 -1
  106. package/dist/wire-tab-bars.js +1 -1
  107. package/dist/wire-token-search-fields.d.ts +1 -1
  108. package/dist/workbench.js +1 -1
  109. package/docs/accessibility.md +29 -3
  110. package/docs/collapsible-panel.md +4 -3
  111. package/docs/component-contract.md +5 -0
  112. package/docs/component-selection.md +92 -11
  113. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  114. package/docs/design/templates/segmented-control/equal.svg +1 -1
  115. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
  116. package/docs/design/templates/segmented-control/pill-small.svg +1 -1
  117. package/docs/design/templates/segmented-control-dark.svg +1 -1
  118. package/docs/design/templates/segmented-control.svg +1 -1
  119. package/docs/layout.md +51 -9
  120. package/docs/nav-stack.md +5 -0
  121. package/docs/split-view.md +5 -0
  122. package/docs/sunken-panel.md +12 -0
  123. package/docs/tab-scaffold.md +5 -0
  124. package/docs/webawesome-theme.md +62 -0
  125. package/docs/workbench.md +22 -10
  126. package/llms.txt +40 -8
  127. package/package.json +7 -1
  128. package/dist/chunk-2OXQHM7I.js.map +0 -1
  129. package/dist/chunk-3SXMEK3B.js.map +0 -1
  130. package/dist/chunk-46263QLK.js.map +0 -1
  131. package/dist/chunk-5I7OHCIP.js +0 -96
  132. package/dist/chunk-5I7OHCIP.js.map +0 -1
  133. package/dist/chunk-5PESG2VP.js.map +0 -1
  134. package/dist/chunk-AGXQQFKZ.js.map +0 -1
  135. package/dist/chunk-EZVNC4J6.js.map +0 -1
  136. package/dist/chunk-F7F7KRO2.js.map +0 -1
  137. package/dist/chunk-MERWRTBG.js.map +0 -1
  138. package/dist/chunk-N3GKMPDW.js.map +0 -1
  139. package/dist/chunk-T57AXDFM.js.map +0 -1
  140. package/dist/chunk-T66UNBXL.js.map +0 -1
  141. package/dist/chunk-UWONG4QE.js.map +0 -1
  142. package/dist/chunk-WPLIO5WJ.js.map +0 -1
@@ -60,6 +60,59 @@
60
60
  "composition": "generated-permissive-default"
61
61
  }
62
62
  },
63
+ {
64
+ "key": "@kerfjs/ui:chip",
65
+ "package": "@kerfjs/ui",
66
+ "id": "chip",
67
+ "name": "Chip",
68
+ "kind": "component",
69
+ "source": "kerf",
70
+ "parents": { "mode": "any", "entries": [] },
71
+ "contexts": ["application-ui"],
72
+ "zones": [],
73
+ "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
74
+ "state": [
75
+ {
76
+ "id": "tag text and identity",
77
+ "owner": "application",
78
+ "required": false
79
+ },
80
+ {
81
+ "id": "remove action and list update",
82
+ "owner": "application",
83
+ "required": false
84
+ },
85
+ { "id": "disabled policy", "owner": "application", "required": false }
86
+ ],
87
+ "wiring": {
88
+ "required": false,
89
+ "helpers": [],
90
+ "obligations": [],
91
+ "stateAttributes": []
92
+ },
93
+ "responsive": { "owner": "not-applicable", "behaviors": [] },
94
+ "layout": {
95
+ "roles": ["foundation"],
96
+ "geometry": { "margin": "none", "border": "self", "padding": "self" }
97
+ },
98
+ "accessibility": {
99
+ "obligations": [
100
+ "The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.",
101
+ "Keep meaningful tag text visible because tone is supplementary."
102
+ ]
103
+ },
104
+ "cssValueProps": [],
105
+ "boundaries": {
106
+ "rootClass": "kui-chip",
107
+ "publicClasses": ["kui-chip"],
108
+ "publicTokens": []
109
+ },
110
+ "diagnostics": [],
111
+ "provenance": {
112
+ "selection": "ai/component-catalog.json",
113
+ "composition": "generated-permissive-default"
114
+ }
115
+ },
63
116
  {
64
117
  "key": "@kerfjs/ui:lucide-icon",
65
118
  "package": "@kerfjs/ui",
@@ -536,6 +589,11 @@
536
589
  "id": "whether the chrome dividers follow the scroll, always show, or never show (chromeDividers)",
537
590
  "owner": "application",
538
591
  "required": false
592
+ },
593
+ {
594
+ "id": "default or sunken scrolling work surface (appearance)",
595
+ "owner": "application",
596
+ "required": false
539
597
  }
540
598
  ],
541
599
  "wiring": {
@@ -592,7 +650,9 @@
592
650
  "--kui-edge-inset-inline-end",
593
651
  "--kui-edge-inset-inline-start",
594
652
  "--kui-pane-separator-color",
595
- "--kui-pane-separator-width"
653
+ "--kui-pane-separator-width",
654
+ "--kui-pane-chrome-background",
655
+ "--kui-sunken-panel-background"
596
656
  ]
597
657
  },
598
658
  "diagnostics": [],
@@ -1383,7 +1443,7 @@
1383
1443
  "border": "conditional",
1384
1444
  "padding": "self",
1385
1445
  "notes": [
1386
- "Padding belongs to the toolbar; dividerSides selects any canonical combination of its physical top, right, bottom, and left edges.",
1446
+ "Padding belongs to the toolbar; --kui-toolbar-inset controls outer padding and minimum height independently of --kui-toolbar-gap. dividerSides selects any canonical combination of its physical top, right, bottom, and left edges.",
1387
1447
  "Safe areas: a Pane header or footer hands a sole Toolbar its inline edges; an app bar or bottom bar at a screen edge claims its sides with safeAreaEdges and pads each claimed side by the --kui-edge-inset-* context or the full device inset, while its box and dividers paint through."
1388
1448
  ]
1389
1449
  }
@@ -1407,6 +1467,7 @@
1407
1467
  "--kui-font-sans",
1408
1468
  "--kui-toolbar-center-padding-inline",
1409
1469
  "--kui-toolbar-divider-color",
1470
+ "--kui-toolbar-inset",
1410
1471
  "--kui-toolbar-leading-min-width",
1411
1472
  "--kui-toolbar-leading-padding-inline",
1412
1473
  "--kui-toolbar-trailing-gap",
@@ -1481,7 +1542,7 @@
1481
1542
  },
1482
1543
  "cssValueProps": [],
1483
1544
  "boundaries": {
1484
- "rootClass": "kui-toolbar-action-link",
1545
+ "rootClass": "kui-toolbar-control-group",
1485
1546
  "publicClasses": [
1486
1547
  "kui-toolbar-action-link",
1487
1548
  "kui-toolbar-control-group"
@@ -1518,6 +1579,14 @@
1518
1579
  "provenance": {
1519
1580
  "selection": "ai/component-catalog.json",
1520
1581
  "composition": "docs/component-selection.md#toolbar-composition"
1582
+ },
1583
+ "jsxExports": {
1584
+ "ToolbarActionLink": {
1585
+ "parents": {
1586
+ "mode": "listed",
1587
+ "entries": ["@kerfjs/ui:toolbar-control-group"]
1588
+ }
1589
+ }
1521
1590
  }
1522
1591
  },
1523
1592
  {
@@ -1976,7 +2045,7 @@
1976
2045
  "required": false
1977
2046
  },
1978
2047
  {
1979
- "id": "column count and responsive changes",
2048
+ "id": "fixed column count or responsive minimum width",
1980
2049
  "owner": "application",
1981
2050
  "required": false
1982
2051
  },
@@ -2000,17 +2069,28 @@
2000
2069
  "border": "none",
2001
2070
  "padding": "none",
2002
2071
  "notes": [
2003
- "Every track uses minmax(0, 1fr), so unequal intrinsic widths cannot break equal distribution."
2072
+ "Fixed tracks use minmax(0, 1fr); responsive tracks use auto-fit with a minimum width capped at 100%, preserving equal distribution without narrow overflow."
2004
2073
  ]
2005
2074
  }
2006
2075
  },
2007
2076
  "accessibility": {
2008
2077
  "obligations": [
2009
2078
  "Grid adds layout only and no grid role; children retain responsibility for native or ARIA semantics.",
2010
- "Responsive column-count changes must preserve source and focus order."
2079
+ "Responsive column-count changes preserve source and focus order."
2011
2080
  ]
2012
2081
  },
2013
2082
  "cssValueProps": [
2083
+ {
2084
+ "path": "minColumnWidth",
2085
+ "grammar": "length",
2086
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
2087
+ "nonStandaloneHelpers": ["plus"],
2088
+ "shorthands": [],
2089
+ "canonicalShorthands": [],
2090
+ "exceptionalShorthands": [],
2091
+ "rawPolicy": "forbid",
2092
+ "examples": ["minColumnWidth={px(376)}"]
2093
+ },
2014
2094
  {
2015
2095
  "path": "gap",
2016
2096
  "grammar": "length",
@@ -2430,6 +2510,11 @@
2430
2510
  "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
2431
2511
  "state": [
2432
2512
  { "id": "routing", "owner": "application", "required": false },
2513
+ {
2514
+ "id": "link destinations",
2515
+ "owner": "application",
2516
+ "required": false
2517
+ },
2433
2518
  { "id": "selection", "owner": "application", "required": false },
2434
2519
  { "id": "permissions", "owner": "application", "required": false },
2435
2520
  { "id": "action handling", "owner": "application", "required": false },
@@ -2448,11 +2533,18 @@
2448
2533
  "responsive": { "owner": "not-applicable", "behaviors": [] },
2449
2534
  "layout": {
2450
2535
  "roles": ["navigation"],
2451
- "geometry": { "margin": "self", "border": "self", "padding": "self" }
2536
+ "geometry": {
2537
+ "margin": "self",
2538
+ "border": "self",
2539
+ "padding": "self",
2540
+ "notes": [
2541
+ "Public resting background and border, hover border, and selected border tokens can be scoped to a row or its containing list without changing the default tones."
2542
+ ]
2543
+ }
2452
2544
  },
2453
2545
  "accessibility": {
2454
2546
  "obligations": [
2455
- "Uses native button activation; selected maps to aria-current and pressed to aria-pressed; rootAttributes cannot add role=menuitem or replace owned ARIA; trailing is dormant content and must not contain controls."
2547
+ "ListItem uses native button activation and pressed maps to aria-pressed; ListItemLink uses native anchor activation and external opens a new tab with safe rel and an announced default label. Both map selected to aria-current; disabled or loading links omit href and leave the tab order. rootAttributes cannot add role=menuitem or replace owned ARIA; trailing is dormant content and must not contain controls."
2456
2548
  ]
2457
2549
  },
2458
2550
  "cssValueProps": [
@@ -2480,22 +2572,27 @@
2480
2572
  ],
2481
2573
  "publicTokens": [
2482
2574
  "--kui-color-brand-border-normal",
2575
+ "--kui-color-brand-border-quiet",
2483
2576
  "--kui-color-brand-fill-quiet",
2484
2577
  "--kui-color-brand-fill-normal",
2485
2578
  "--kui-color-neutral-fill-quiet",
2486
2579
  "--kui-color-neutral-on-normal",
2487
2580
  "--kui-color-neutral-on-quiet",
2488
2581
  "--kui-color-neutral-border-quiet",
2582
+ "--kui-color-neutral-border-normal",
2489
2583
  "--kui-focus-ring",
2490
2584
  "--kui-list-item-color",
2585
+ "--kui-list-item-background",
2491
2586
  "--kui-list-item-align-items",
2492
2587
  "--kui-list-item-border-width",
2588
+ "--kui-list-item-border",
2493
2589
  "--kui-list-item-columns",
2494
2590
  "--kui-list-item-drag-target-background",
2495
2591
  "--kui-list-item-drag-target-outline",
2496
2592
  "--kui-list-item-drag-target-outline-offset",
2497
2593
  "--kui-list-item-gap",
2498
2594
  "--kui-list-item-hover-background",
2595
+ "--kui-list-item-hover-border",
2499
2596
  "--kui-list-item-icon-color",
2500
2597
  "--kui-list-item-icon-size",
2501
2598
  "--kui-list-item-label-max-width",
@@ -2505,6 +2602,7 @@
2505
2602
  "--kui-list-item-padding-inline",
2506
2603
  "--kui-list-item-radius",
2507
2604
  "--kui-list-item-selected-background",
2605
+ "--kui-list-item-selected-border",
2508
2606
  "--kui-list-item-selected-color",
2509
2607
  "--kui-list-item-trailing-color",
2510
2608
  "--kui-list-group-divider-color",
@@ -2778,6 +2876,11 @@
2778
2876
  "state": [
2779
2877
  { "id": "tab identity", "owner": "application", "required": false },
2780
2878
  { "id": "selection", "owner": "application", "required": false },
2879
+ {
2880
+ "id": "drop-target state",
2881
+ "owner": "application",
2882
+ "required": false
2883
+ },
2781
2884
  { "id": "close policy", "owner": "application", "required": false },
2782
2885
  { "id": "content", "owner": "application", "required": false },
2783
2886
  {
@@ -2820,7 +2923,12 @@
2820
2923
  "--kui-app-tab-attention-color",
2821
2924
  "--kui-app-tab-color",
2822
2925
  "--kui-app-tab-drop-indicator",
2926
+ "--kui-app-tab-drop-target-background",
2927
+ "--kui-app-tab-drop-target-color",
2928
+ "--kui-app-tab-drop-target-ring",
2823
2929
  "--kui-app-tab-hover-background",
2930
+ "--kui-app-tab-pinned-background",
2931
+ "--kui-app-tab-pinned-hover-background",
2824
2932
  "--kui-app-tab-selected-background",
2825
2933
  "--kui-app-tab-selected-border",
2826
2934
  "--kui-app-tab-selected-color",
@@ -3312,6 +3420,7 @@
3312
3420
  "Hint text is visible below the control through Web Awesome's native hint relationship; placeholderText remains the empty value inside the closed control.",
3313
3421
  "Import select/register once; its scoped lifecycle adapter keeps the latest open/close request authoritative across animation reversals, canceled transitions, and removal. Do not add consumer popup timing or position repairs.",
3314
3422
  "With multiple, the popup stays open while choices toggle (pointer, Enter, or Space) and closes on an outside press, Escape, or focus leaving; each chosen option shows a check, and the closed control summarizes the chosen labels in choice order.",
3423
+ "Disabled choices stay visible but cannot be selected; disabledReason exposes a tooltip. A multiple Select can opt in to localized select-all and clear buttons, which skip disabled choices and publish ordinary input/change events for changed values.",
3315
3424
  "A multiple icon-only trigger shows its fixed triggerIcon and, while any choice is chosen, an aria-hidden count Badge; the combobox's accessible name ends with the chosen labels in choice order, and its hidden value stays empty.",
3316
3425
  "Once registered, an icon-only trigger (single or multiple) shows an aria-hidden Web Awesome help tag repeating its accessible name (a single Select adds its current choice) after a 500ms hover and at once on keyboard focus; it hides while the popup is open, on a press, and on Escape, and never joins aria-labelledby. Do not add a title or another tooltip."
3317
3426
  ]
@@ -166,6 +166,27 @@
166
166
  "items": { "type": "string", "pattern": "^[^:]+:[^:]+$" },
167
167
  "uniqueItems": true
168
168
  },
169
+ "jsxExports": {
170
+ "description": "Placement contracts for additional JSX exports from one selection entry. These exports do not stand for the entry's root or its zones.",
171
+ "type": "object",
172
+ "propertyNames": { "pattern": "^[A-Z][A-Za-z0-9]*$" },
173
+ "additionalProperties": {
174
+ "type": "object",
175
+ "required": ["parents"],
176
+ "properties": {
177
+ "parents": {
178
+ "type": "object",
179
+ "required": ["mode", "entries"],
180
+ "properties": {
181
+ "mode": { "enum": ["any", "root", "listed"] },
182
+ "entries": { "$ref": "#/$defs/stringList" }
183
+ },
184
+ "additionalProperties": false
185
+ }
186
+ },
187
+ "additionalProperties": false
188
+ }
189
+ },
169
190
  "parents": {
170
191
  "type": "object",
171
192
  "required": ["mode", "entries"],
@@ -9,6 +9,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
9
9
  ## Kerf UI — Foundation
10
10
 
11
11
  - [Badge](./badge.md) — Present compact metadata without application-authored badge CSS or consumer styling of component internals.
12
+ - [Chip](./chip.md) — Render removable tags without application rules on Web Awesome internals.
12
13
  - [LucideIcon](./lucide-icon.md) — Decorative and meaningfully labeled Lucide-compatible icons.
13
14
  - [DisclosureArrow](./disclosure-arrow.md) — Indicate whether a disclosure control is open with an overridable 18px root-scaled visual and shortest-path rotation behavior.
14
15
  - [Foundation tokens](./foundation.md) — Provide the shared semantic token foundation for application themes and every styled Kerf UI component.
@@ -33,7 +34,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
33
34
  - [Headers](./headers.md) — Page, dialog, and definition-list hierarchy.
34
35
  - [ValueTable](./value-table.md) — Key/value rows with optional icons and aligned separators.
35
36
  - [Row](./row.md) — Arrange related content horizontally with consistent spacing, optional physical-side text/control insets, and explicit left/center/right/full plus top/middle/bottom/full/baseline alignment instead of application-owned flex wrappers.
36
- - [Grid](./grid.md) — Arrange related siblings in equal-width columns without repeating application-owned grid-template-columns CSS.
37
+ - [Grid](./grid.md) — Arrange related siblings in equal-width columns with either a fixed count or automatic container-width collapse.
37
38
  - [Spacer](./spacer.md) — Express an intentional empty dimension or consume remaining flex space without application-owned spacer markup or raw CSS lengths.
38
39
  - [ListInsetControl](./list-inset-control.md) — Apply the standard 8px outer margin to all physical sides of a self-bordered control by default, or only the sides selected with the canonical Sides contract.
39
40
  - [ListInsetText](./list-inset-text.md) — Apply the full 8px margin + 1px transparent border + 8px padding to all physical sides of bare text by default, or only the sides selected with the canonical Sides contract.
@@ -44,9 +45,9 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
44
45
  - [List](./list.md) — Standardize vertical component layout, optional physical-side text/control insets, and scroll/divider ownership instead of repeating ad-hoc flex-column wrappers.
45
46
  - [ListHeader](./list-header.md) — Fill the available section width by default, or shrink-wrap without outer geometry when inline, while splitting a dormant title and mutually exclusive semantic count or badge from an optional logical-end action with an 18px visual; disclosure mode renders the title cluster as a button with a default production DisclosureArrow.
46
47
  - [ListActionRow](./list-action-row.md) — Keep a selectable primary row action and an independently named trailing action as sibling native controls inside one noninteractive visual row.
47
- - [ListItem](./list-item.md) — Selectable, disabled, trailing, and multiline navigation rows.
48
+ - [ListItem](./list-item.md) — Selectable, disabled, trailing, and multiline action or link rows.
48
49
  - [Application tabs](./application-tabs.md) — Show AppTab and TabBar in a complete controlled composition.
49
- - [AppTab](./tabs.md) — Roving-tabindex-ready tabs with typed compact, segmented, icon-only, and truncating-label presentations.
50
+ - [AppTab](./tabs.md) — Render a controlled application tab with compact or icon-only presentation, a visible drop target, optional full-name display, and an optional pinned leading position.
50
51
  - [TabBar](./tab-bar.md) — Controlled tab strips whose tabs shrink and scroll while fixed leading, trailing, and far-edge end actions remain visible.
51
52
 
52
53
  ## Kerf UI — Controls
@@ -54,7 +55,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
54
55
  - [SegmentedControl](./segmented-control.md) — Controlled exclusive choices in toolbar, rounded-rectangle, and pill presentations.
55
56
  - [TokenSearchField](./token-search-field.md) — Token-controlled, optionally collapsible search editor with ordered, editable, removable filter chips.
56
57
  - [ResizableRegion](./resize.md) — Pointer and keyboard-operable split region with a customizable handle icon.
57
- - [Select](./select.md) — Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
58
+ - [Select](./select.md) — Choose one or more controlled values, keep unavailable choices visible, and optionally select all enabled choices or clear a multiple selection.
58
59
  - [PopupMenu](./popup-menu.md) — A typed action menu with nested choices, selected state, and optional pointer-anchored context opening, built on the Web Awesome dropdown.
59
60
 
60
61
  ## Kerf UI — Feedback
@@ -0,0 +1,72 @@
1
+ # Chip
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:chip` · Kerf UI · component · Foundation
6
+
7
+ A short tag with semantic tone and an optional accessible remove button, including compact and disabled variants.
8
+
9
+ ## When to use
10
+
11
+ Render removable tags without application rules on Web Awesome internals.
12
+
13
+ - Show a short tag that the application can remove through a delegated action, including a compact or disabled tag.
14
+
15
+ **Not when:**
16
+
17
+ - Use Badge for non-interactive status and count metadata.
18
+ - Do not use the remove button without a specific accessible name.
19
+
20
+ ## Imports
21
+
22
+ - JavaScript: `@kerfjs/ui/chip` — exports `Chip`.
23
+ - CSS: the browser build of `@kerfjs/ui/chip` pulls its CSS automatically; import `@kerfjs/ui/chip.css` manually only without the `browser` export condition.
24
+ - Declared side effects: browser-condition-css.
25
+
26
+ ## Props
27
+
28
+ Exact prop names and types: [`@kerfjs/ui/chip`](../public-api-signatures-v1.md#kerfjsuichip) in `public-api-signatures-v1.md`. Do not infer props from examples.
29
+
30
+ **Variants (configure, do not restyle):**
31
+
32
+ - neutral, brand, pop, success, warning, or danger tone
33
+ - quiet, solid, or outline appearance
34
+ - pill or rounded shape
35
+ - compact or default size
36
+ - removable or plain, enabled or disabled
37
+
38
+ ## Composition
39
+
40
+ - Parents: any.
41
+ - Contexts: `application-ui`.
42
+ - Children: unrestricted.
43
+
44
+ ## State and wiring
45
+
46
+ **The app owns:** tag text and identity; remove action and list update; disabled policy.
47
+
48
+ No wiring helper.
49
+
50
+ ## Geometry
51
+
52
+ Margin: none · border: self · padding: self (layout role: foundation). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
53
+
54
+ ## Accessibility
55
+
56
+ - The remove control is a native button and requires an action and a specific removeLabel. A disabled chip disables that button and removes it from keyboard interaction.
57
+ - Keep meaningful tag text visible because tone is supplementary.
58
+
59
+ ## Styling boundary
60
+
61
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
62
+
63
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-chip`.
64
+
65
+ Never put `kui-chip` on an element you write; render `Chip` instead (`KUI-L103`).
66
+
67
+ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
68
+
69
+ ## Related
70
+
71
+ - Docs: [`docs/component-selection.md`](../../docs/component-selection.md), [`docs/component-selection.md#problem-to-component-matrix`](../../docs/component-selection.md#problem-to-component-matrix).
72
+ - UX catalog route: `?component=chip`.
@@ -4,21 +4,22 @@
4
4
 
5
5
  `@kerfjs/ui:grid` · Kerf UI · component · Structure
6
6
 
7
- A fixed positive number of evenly distributed minmax columns with a typed xs gap by default and optional flex participation.
7
+ Equal-width columns with a fixed count or a minimum-width responsive mode, typed gaps, and optional flex participation.
8
8
 
9
9
  ## When to use
10
10
 
11
- Arrange related siblings in equal-width columns without repeating application-owned grid-template-columns CSS.
11
+ Arrange related siblings in equal-width columns with either a fixed count or automatic container-width collapse.
12
12
 
13
13
  - Arrange related siblings into a fixed positive number of equal-width columns.
14
+ - Fit equal-width columns down to a typed minimum and collapse as the container narrows.
14
15
  - Prevent wider intrinsic content from making one fractional track wider than its peers.
15
16
  - Use a finite flex keyword or the flex() builder when Grid participates in a flexible parent layout.
16
17
 
17
18
  **Not when:**
18
19
 
19
- - Do not use Grid for intrinsic, asymmetric, spanning, auto-fit, or masonry tracks; use application-owned CSS grid.
20
+ - Do not use Grid for intrinsic, asymmetric, spanning, or masonry tracks; use application-owned CSS grid.
20
21
  - Do not use Grid when columns need a user-operable separator; use ResizableRegion.
21
- - Do not expect Grid to choose responsive breakpoints or change the column count; the application owns that policy.
22
+ - Do not combine fixed columns with minColumnWidth; choose one layout mode.
22
23
  - Do not pass raw CSS strings to gap or flex, mix their distinct grammars, or use s/xl spacing steps without a deliberate exception.
23
24
 
24
25
  **Alternatives:**
@@ -40,6 +41,7 @@ Exact prop names and types: [`@kerfjs/ui/grid`](../public-api-signatures-v1.md#k
40
41
  **Variants (configure, do not restyle):**
41
42
 
42
43
  - any positive safe-integer equal-track count
44
+ - typed minimum column width with automatic container-width collapse
43
45
  - named none/2xs/xs/s/m/l/xl token gap
44
46
  - typed CssLength gap
45
47
  - boolean, finite-keyword, or typed CssFlex flex
@@ -48,6 +50,7 @@ Exact prop names and types: [`@kerfjs/ui/grid`](../public-api-signatures-v1.md#k
48
50
 
49
51
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
50
52
 
53
+ - `minColumnWidth`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `minColumnWidth={px(376)}`
51
54
  - `gap`: length grammar; raw values: forbid; shorthands `none`, `2xs`, `xs`, `m`, `l`; exceptional (justify) `s`, `xl`; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `gap="m"`
52
55
  - `flex`: flex grammar; raw values: forbid; shorthands `none`, `auto`, `initial`; helpers `flex` — e.g. `flex`
53
56
 
@@ -59,7 +62,7 @@ Exact prop names and types: [`@kerfjs/ui/grid`](../public-api-signatures-v1.md#k
59
62
 
60
63
  ## State and wiring
61
64
 
62
- **The app owns:** child semantics and content; column count and responsive changes; typed gap and flex choices.
65
+ **The app owns:** child semantics and content; fixed column count or responsive minimum width; typed gap and flex choices.
63
66
 
64
67
  No wiring helper.
65
68
 
@@ -67,12 +70,12 @@ No wiring helper.
67
70
 
68
71
  Margin: none · border: none · padding: none (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
69
72
 
70
- - Every track uses minmax(0, 1fr), so unequal intrinsic widths cannot break equal distribution.
73
+ - Fixed tracks use minmax(0, 1fr); responsive tracks use auto-fit with a minimum width capped at 100%, preserving equal distribution without narrow overflow.
71
74
 
72
75
  ## Accessibility
73
76
 
74
77
  - Grid adds layout only and no grid role; children retain responsibility for native or ARIA semantics.
75
- - Responsive column-count changes must preserve source and focus order.
78
+ - Responsive column-count changes preserve source and focus order.
76
79
 
77
80
  ## Styling boundary
78
81
 
@@ -4,13 +4,13 @@
4
4
 
5
5
  `@kerfjs/ui:list-item` · Kerf UI · component · Navigation
6
6
 
7
- Configurable native-button navigation rows with structured labels, status/busy metadata, density, group dividers, protected domain metadata hooks, and rounded-boundary overflow clipping.
7
+ Configurable native-button action rows and native-anchor navigation rows with structured labels, status/busy metadata, density, group dividers, protected domain metadata hooks, and rounded-boundary overflow clipping.
8
8
 
9
9
  ## When to use
10
10
 
11
- Selectable, disabled, trailing, and multiline navigation rows.
11
+ Selectable, disabled, trailing, and multiline action or link rows.
12
12
 
13
- - Render a selectable, disabled, trailing, or multiline sidebar/navigation action row whose descendants must remain clipped to the rounded row boundary.
13
+ - Render a selectable, disabled, trailing, or multiline sidebar action row whose descendants must remain clipped to the rounded row boundary; use ListItemLink when the destination has an href and needs native link activation.
14
14
 
15
15
  **Not when:**
16
16
 
@@ -23,7 +23,7 @@ Selectable, disabled, trailing, and multiline navigation rows.
23
23
 
24
24
  ## Imports
25
25
 
26
- - JavaScript: `@kerfjs/ui/list-item` — exports `ListItem`.
26
+ - JavaScript: `@kerfjs/ui/list-item` — exports `ListItem`, `ListItemLink`.
27
27
  - CSS: the browser build of `@kerfjs/ui/list-item` pulls its CSS automatically; import `@kerfjs/ui/list-item.css` manually only without the `browser` export condition.
28
28
  - Declared side effects: browser-condition-css.
29
29
 
@@ -33,6 +33,7 @@ Exact prop names and types: [`@kerfjs/ui/list-item`](../public-api-signatures-v1
33
33
 
34
34
  **Variants (configure, do not restyle):**
35
35
 
36
+ - native link and external link
36
37
  - selected
37
38
  - pressed
38
39
  - disabled
@@ -60,7 +61,7 @@ Exact prop names and types: [`@kerfjs/ui/list-item`](../public-api-signatures-v1
60
61
 
61
62
  ## State and wiring
62
63
 
63
- **The app owns:** routing; selection; permissions; action handling; domain data attributes.
64
+ **The app owns:** routing; link destinations; selection; permissions; action handling; domain data attributes.
64
65
 
65
66
  No wiring helper.
66
67
 
@@ -68,9 +69,11 @@ No wiring helper.
68
69
 
69
70
  Margin: self · border: self · padding: self (layout role: navigation). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
70
71
 
72
+ - Public resting background and border, hover border, and selected border tokens can be scoped to a row or its containing list without changing the default tones.
73
+
71
74
  ## Accessibility
72
75
 
73
- - Uses native button activation; selected maps to aria-current and pressed to aria-pressed; rootAttributes cannot add role=menuitem or replace owned ARIA; trailing is dormant content and must not contain controls.
76
+ - ListItem uses native button activation and pressed maps to aria-pressed; ListItemLink uses native anchor activation and external opens a new tab with safe rel and an announced default label. Both map selected to aria-current; disabled or loading links omit href and leave the tab order. rootAttributes cannot add role=menuitem or replace owned ARIA; trailing is dormant content and must not contain controls.
74
77
 
75
78
  ## Styling boundary
76
79
 
@@ -80,7 +83,7 @@ Public class hooks (select for layout placement only, never to change the compon
80
83
 
81
84
  Never put `kui-list-item`, `kui-list-item__icon`, `kui-list-item__label`, `kui-list-item__primary-label`, `kui-list-item__description`, `kui-list-item__status`, `kui-list-item__trailing` on an element you write; render `ListItem` instead (`KUI-L103`).
82
85
 
83
- Public tokens it reads: `--kui-color-brand-border-normal`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-focus-ring`, `--kui-list-item-color`, `--kui-list-item-align-items`, `--kui-list-item-border-width`, `--kui-list-item-columns`, `--kui-list-item-drag-target-background`, `--kui-list-item-drag-target-outline`, `--kui-list-item-drag-target-outline-offset`, `--kui-list-item-gap`, `--kui-list-item-hover-background`, `--kui-list-item-icon-color`, `--kui-list-item-icon-size`, `--kui-list-item-label-max-width`, `--kui-list-item-label-weight`, `--kui-list-item-min-height`, `--kui-list-item-padding-block`, `--kui-list-item-padding-inline`, `--kui-list-item-radius`, `--kui-list-item-selected-background`, `--kui-list-item-selected-color`, `--kui-list-item-trailing-color`, `--kui-list-group-divider-color`, `--kui-font-xs`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`. Set a token only where its public contract allows; prefer a prop.
86
+ Public tokens it reads: `--kui-color-brand-border-normal`, `--kui-color-brand-border-quiet`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-fill-normal`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-on-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-neutral-border-quiet`, `--kui-color-neutral-border-normal`, `--kui-focus-ring`, `--kui-list-item-color`, `--kui-list-item-background`, `--kui-list-item-align-items`, `--kui-list-item-border-width`, `--kui-list-item-border`, `--kui-list-item-columns`, `--kui-list-item-drag-target-background`, `--kui-list-item-drag-target-outline`, `--kui-list-item-drag-target-outline-offset`, `--kui-list-item-gap`, `--kui-list-item-hover-background`, `--kui-list-item-hover-border`, `--kui-list-item-icon-color`, `--kui-list-item-icon-size`, `--kui-list-item-label-max-width`, `--kui-list-item-label-weight`, `--kui-list-item-min-height`, `--kui-list-item-padding-block`, `--kui-list-item-padding-inline`, `--kui-list-item-radius`, `--kui-list-item-selected-background`, `--kui-list-item-selected-border`, `--kui-list-item-selected-color`, `--kui-list-item-trailing-color`, `--kui-list-group-divider-color`, `--kui-font-xs`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-layout-rounded-radius`. Set a token only where its public contract allows; prefer a prop.
84
87
 
85
88
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
86
89
 
@@ -13,6 +13,7 @@ Organize a sidebar, main area, inspector, or dialog column into fixed vertical h
13
13
  - An application column needs shared header, content, and optional footer organization with exactly one scrolling content owner.
14
14
  - A pane boundary needs an opt-in separator on any combination of logical sides.
15
15
  - Pinned chrome needs a divider from the scrolling content only while content is scrolled beneath it (wireScrollDividers).
16
+ - A lowered background must cover the scrolling work viewport and blank space after short content without a second scroll container (appearance: sunken).
16
17
 
17
18
  **Not when:**
18
19
 
@@ -60,7 +61,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
60
61
 
61
62
  ## State and wiring
62
63
 
63
- **The app owns:** root and content semantics; accessible labels; header, content, and footer children; which logical boundaries show separators; which sides may compensate for device safe areas in an app-owned arrangement (safeAreaEdges); responsive placement and visibility; whether the chrome dividers follow the scroll, always show, or never show (chromeDividers).
64
+ **The app owns:** root and content semantics; accessible labels; header, content, and footer children; which logical boundaries show separators; which sides may compensate for device safe areas in an app-owned arrangement (safeAreaEdges); responsive placement and visibility; whether the chrome dividers follow the scroll, always show, or never show (chromeDividers); default or sunken scrolling work surface (appearance).
64
65
 
65
66
  **Wiring:** `wireScrollDividers` is optional.
66
67
 
@@ -89,7 +90,7 @@ Public class hooks (select for layout placement only, never to change the compon
89
90
 
90
91
  Never put `kui-pane`, `kui-pane__content`, `kui-pane__footer`, `kui-pane__header`, `kui-pane__toolbar` on an element you write; render `Pane` instead (`KUI-L103`).
91
92
 
92
- Public tokens it reads: `--kui-edge-inset-block-end`, `--kui-edge-inset-block-start`, `--kui-edge-inset-inline-end`, `--kui-edge-inset-inline-start`, `--kui-pane-separator-color`, `--kui-pane-separator-width`. Set a token only where its public contract allows; prefer a prop.
93
+ Public tokens it reads: `--kui-edge-inset-block-end`, `--kui-edge-inset-block-start`, `--kui-edge-inset-inline-end`, `--kui-edge-inset-inline-start`, `--kui-pane-separator-color`, `--kui-pane-separator-width`, `--kui-pane-chrome-background`, `--kui-sunken-panel-background`. Set a token only where its public contract allows; prefer a prop.
93
94
 
94
95
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
95
96
 
@@ -4,11 +4,11 @@
4
4
 
5
5
  `@kerfjs/ui:select` · Kerf UI · component · Controls
6
6
 
7
- Controlled Web Awesome select with typed single or multiple values and form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
7
+ Controlled Web Awesome select with typed single or multiple values, disabled choices, optional bulk actions, and form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
8
8
 
9
9
  ## When to use
10
10
 
11
- Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
11
+ Choose one or more controlled values, keep unavailable choices visible, and optionally select all enabled choices or clear a multiple selection.
12
12
 
13
13
  - Choose a controlled value from a moderate or long list, including grouped and icon-bearing choices.
14
14
  - Color an optional choice icon with a CssForegroundColor: uiColor() with a foreground token such as success-on-quiet, or foregroundColorVar() for an app-owned property. Fill tokens such as success are backgrounds that leave the icon nearly invisible, so they, lengths, raw color strings, and unqualified colorVar() values are rejected.
@@ -46,11 +46,14 @@ Exact prop names and types: [`@kerfjs/ui/select`](../public-api-signatures-v1.md
46
46
  - form, toolbar-borderless, or navigation presentation
47
47
  - default or compact size
48
48
  - label or icon-only selected presentation
49
+ - optional caret-free round icon-only trigger
49
50
  - select- or group-owned focus ring
50
51
  - label maximum width and truncation
51
52
  - fit-content, max-content, or fill trigger width
52
53
  - custom selected content typography and ellipsis
53
54
  - multiple selection
55
+ - disabled choice with an optional reason
56
+ - opt-in select-all and clear actions for multiple selection
54
57
  - multiple icon-only filter trigger with a fixed triggerIcon
55
58
 
56
59
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
@@ -83,6 +86,7 @@ Margin: none · border: self · padding: self (layout role: controls). `self` me
83
86
  - Hint text is visible below the control through Web Awesome's native hint relationship; placeholderText remains the empty value inside the closed control.
84
87
  - Import select/register once; its scoped lifecycle adapter keeps the latest open/close request authoritative across animation reversals, canceled transitions, and removal. Do not add consumer popup timing or position repairs.
85
88
  - With multiple, the popup stays open while choices toggle (pointer, Enter, or Space) and closes on an outside press, Escape, or focus leaving; each chosen option shows a check, and the closed control summarizes the chosen labels in choice order.
89
+ - Disabled choices stay visible but cannot be selected; disabledReason exposes a tooltip. A multiple Select can opt in to localized select-all and clear buttons, which skip disabled choices and publish ordinary input/change events for changed values.
86
90
  - A multiple icon-only trigger shows its fixed triggerIcon and, while any choice is chosen, an aria-hidden count Badge; the combobox's accessible name ends with the chosen labels in choice order, and its hidden value stays empty.
87
91
  - Once registered, an icon-only trigger (single or multiple) shows an aria-hidden Web Awesome help tag repeating its accessible name (a single Select adds its current choice) after a 500ms hover and at once on keyboard focus; it hides while the popup is open, on a press, and on Escape, and never joins aria-labelledby. Do not add a title or another tooltip.
88
92