@kerfjs/ui 5.0.0-beta.64 → 5.0.0-beta.66

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 (74) hide show
  1. package/ai/component-catalog.json +37 -15
  2. package/ai/component-composition.json +28 -4
  3. package/ai/components/content-item.md +4 -1
  4. package/ai/components/grid.md +3 -1
  5. package/ai/components/list.md +4 -2
  6. package/ai/components/nav-stack.md +4 -3
  7. package/ai/components/token-search-field.md +3 -0
  8. package/ai/components/workbench.md +5 -3
  9. package/ai/public-api-signatures-v1.md +66 -42
  10. package/ai/skill.md +4 -0
  11. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  12. package/dist/browser/catalog.js +2 -1
  13. package/dist/browser/workbench.js +4 -1
  14. package/dist/catalog-resources.d.ts +2 -0
  15. package/dist/catalog.d.ts +2 -0
  16. package/dist/catalog.js +3 -2
  17. package/dist/catalog.js.map +1 -1
  18. package/dist/{chunk-NSVLUDUW.js → chunk-5SYE4CCT.js} +25 -3
  19. package/dist/chunk-5SYE4CCT.js.map +1 -0
  20. package/dist/{chunk-2EKHENQK.js → chunk-B2ZMR7NY.js} +9 -1
  21. package/dist/chunk-B2ZMR7NY.js.map +1 -0
  22. package/dist/{chunk-IA4D5XNT.js → chunk-C74LITXE.js} +5 -5
  23. package/dist/{chunk-IA4D5XNT.js.map → chunk-C74LITXE.js.map} +1 -1
  24. package/dist/{chunk-SH6F3CCG.js → chunk-NCSWXG7G.js} +4 -4
  25. package/dist/{chunk-SH6F3CCG.js.map → chunk-NCSWXG7G.js.map} +1 -1
  26. package/dist/{chunk-M5H2RMCH.js → chunk-P4UXSYIJ.js} +16 -2
  27. package/dist/chunk-P4UXSYIJ.js.map +1 -0
  28. package/dist/{chunk-KFYANKJI.js → chunk-TGM424PI.js} +35 -5
  29. package/dist/chunk-TGM424PI.js.map +1 -0
  30. package/dist/chunk-VY6YRCTV.js +123 -0
  31. package/dist/chunk-VY6YRCTV.js.map +1 -0
  32. package/dist/{chunk-NAPE7WUS.js → chunk-W2AC6Q2A.js} +9 -1
  33. package/dist/chunk-W2AC6Q2A.js.map +1 -0
  34. package/dist/collapsible-panel.js +2 -2
  35. package/dist/content-item.d.ts +2 -2
  36. package/dist/content-item.js +1 -1
  37. package/dist/grid.d.ts +5 -1
  38. package/dist/grid.js +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +5 -5
  41. package/dist/list.d.ts +5 -1
  42. package/dist/list.js +1 -1
  43. package/dist/nav-stack.d.ts +5 -1
  44. package/dist/nav-stack.js +1 -1
  45. package/dist/split-view.js +1 -1
  46. package/dist/styles/nav-stack.css +4 -0
  47. package/dist/styles/token-search-field.css +36 -0
  48. package/dist/styles/toolbar.css +5 -1
  49. package/dist/{token-search-field-Xk8jiw8Y.d.ts → token-search-field-CVGwDn2y.d.ts} +14 -4
  50. package/dist/token-search-field.d.ts +1 -1
  51. package/dist/token-search-field.js +1 -1
  52. package/dist/token-search-model.d.ts +1 -1
  53. package/dist/wire-content-items.d.ts +3 -1
  54. package/dist/wire-content-items.js +49 -1
  55. package/dist/wire-content-items.js.map +1 -1
  56. package/dist/wire-token-search-fields.d.ts +1 -1
  57. package/dist/wire-token-search-fields.js +1 -1
  58. package/dist/workbench.d.ts +41 -33
  59. package/dist/workbench.js +4 -1
  60. package/docs/accessibility.md +26 -2
  61. package/docs/component-selection.md +16 -0
  62. package/docs/layout.md +24 -4
  63. package/docs/nav-stack.md +7 -0
  64. package/docs/webawesome-theme.md +6 -0
  65. package/docs/workbench.md +27 -3
  66. package/llms.txt +3 -0
  67. package/package.json +1 -1
  68. package/dist/chunk-2EKHENQK.js.map +0 -1
  69. package/dist/chunk-HXCMWANP.js +0 -116
  70. package/dist/chunk-HXCMWANP.js.map +0 -1
  71. package/dist/chunk-KFYANKJI.js.map +0 -1
  72. package/dist/chunk-M5H2RMCH.js.map +0 -1
  73. package/dist/chunk-NAPE7WUS.js.map +0 -1
  74. package/dist/chunk-NSVLUDUW.js.map +0 -1
@@ -725,6 +725,7 @@
725
725
  "preferred initial focus targets when DOM order is insufficient",
726
726
  "per-view bottom toolbar content or a persistent fallback",
727
727
  "per-view leading, center, and trailing top-toolbar groups",
728
+ "per-view fixed header content above the active view's scroll area",
728
729
  "top-toolbar configuration, title size, and heading level",
729
730
  "whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers)"
730
731
  ],
@@ -735,6 +736,7 @@
735
736
  "configured top toolbar",
736
737
  "custom back icon or visible back text",
737
738
  "per-view bottom toolbar",
739
+ "persistent final top-toolbar group (panelToggle) when embedded in a Workbench panel",
738
740
  "persistent bottom-toolbar fallback",
739
741
  "chrome and bottom-toolbar dividers only while the active view scrolls beneath them (wired by wireScrollDividers)",
740
742
  "permanent or no chrome dividers (chromeDividers always or none)"
@@ -811,6 +813,7 @@
811
813
  "kui-nav-stack__chrome-copy",
812
814
  "kui-nav-stack__chrome-copy--bottom",
813
815
  "kui-nav-stack__chrome-copy--exiting",
816
+ "kui-nav-stack__header",
814
817
  "kui-nav-stack__viewport",
815
818
  "kui-nav-stack__view",
816
819
  "kui-nav-stack__view--entering",
@@ -1079,7 +1082,9 @@
1079
1082
  "kind": "component",
1080
1083
  "source": "kerf",
1081
1084
  "description": "A desktop-class multi-panel workspace with independently collapsible, optionally drag-resizable left and right rails and a bottom drawer around one central work area.",
1082
- "uses": [],
1085
+ "uses": [
1086
+ "nav-stack"
1087
+ ],
1083
1088
  "purpose": "Arrange a complex tool or editor as a stable central work area with optional peripheral rails and a bottom drawer.",
1084
1089
  "publicExports": [
1085
1090
  "Workbench",
@@ -1088,6 +1093,8 @@
1088
1093
  "WorkbenchMainBottomToolbar",
1089
1094
  "WorkbenchMainToolbar",
1090
1095
  "WorkbenchPanel",
1096
+ "WorkbenchStaticPanel",
1097
+ "WorkbenchNavigationPanel",
1091
1098
  "WorkbenchPanelResizable",
1092
1099
  "WorkbenchPanelToggle",
1093
1100
  "WorkbenchPanelToolbar",
@@ -1114,6 +1121,7 @@
1114
1121
  "panel presence and content",
1115
1122
  "collapsed state",
1116
1123
  "panel sizes",
1124
+ "navigation panel view stack and push/pop actions when navStack is supplied",
1117
1125
  "responsive replacement below desktop",
1118
1126
  "collapse controls and focus policy"
1119
1127
  ],
@@ -1124,6 +1132,7 @@
1124
1132
  "bottom drawer",
1125
1133
  "all panels",
1126
1134
  "independently collapsed panels",
1135
+ "navigation panel with per-screen toolbar, fixed header, and one scroll owner; standard toggle remains last and relocates while collapsed",
1127
1136
  "opt-in drag and keyboard resizable panels with min/max limits",
1128
1137
  "resizable rails that leave the work area a minimum width and shrink in proportion when the Workbench narrows",
1129
1138
  "rails or a drawer that present as overlays below a narrow or compact Workbench container breakpoint",
@@ -2439,10 +2448,12 @@
2439
2448
  "typed CssLength gap",
2440
2449
  "boolean, finite-keyword, or typed CssFlex flex",
2441
2450
  "fill: the layout root fills a definite-height parent",
2442
- "rootAttributes: safe data-* metadata on the root"
2451
+ "rootAttributes: safe data-* metadata on the root",
2452
+ "selectionMode=multiple: labeled multi-select grid for ContentItem tiles"
2443
2453
  ],
2444
2454
  "accessibility": [
2445
- "Grid adds layout only and no grid role; children retain responsibility for native or ARIA semantics.",
2455
+ "Grid adds no role by default; selectionMode=multiple requires ariaLabel and supplies a multi-select grid for ContentItem row/gridcell tiles.",
2456
+ "wireContentItems uses rendered tile positions for Left/Right/Up/Down and reaches the first or last tile with Home/End.",
2446
2457
  "Responsive column-count changes preserve source and focus order."
2447
2458
  ],
2448
2459
  "geometry": {
@@ -2731,7 +2742,8 @@
2731
2742
  "Choose a finite gap shorthand such as xs or m, or compose a typed length with @kerfjs/ui/css-values when the spacing scale is insufficient.",
2732
2743
  "Use a finite flex keyword or the flex() builder when List participates in flexible layout.",
2733
2744
  "Apply the standard text or control inset to selected physical sides without an application wrapper.",
2734
- "Align children horizontally or distribute them vertically with the same physical alignment vocabulary as Row."
2745
+ "Align children horizontally or distribute them vertically with the same physical alignment vocabulary as Row.",
2746
+ "Use selectionMode=\"multiple\" and ariaLabel to group selectable rich ContentItem rows in a multi-select grid."
2735
2747
  ],
2736
2748
  "avoidWhen": [
2737
2749
  "Do not use List as semantic list markup; use ul/ol when list semantics are required and apply layout deliberately.",
@@ -2742,7 +2754,8 @@
2742
2754
  "appOwns": [
2743
2755
  "child semantics and content",
2744
2756
  "the bounded height needed for scrolling",
2745
- "typed gap, flex, alignment, and divider choices"
2757
+ "typed gap, flex, alignment, and divider choices",
2758
+ "the accessible label and selection state of a multi-select grid"
2746
2759
  ],
2747
2760
  "variants": [
2748
2761
  "no gap",
@@ -2757,10 +2770,11 @@
2757
2770
  "top/right/bottom/left text and control inset combinations",
2758
2771
  "fill: the layout root fills a definite-height parent",
2759
2772
  "rootAttributes: safe data-* metadata on the root",
2760
- "scroll dividers when named as wireScrollDividers targets chrome"
2773
+ "scroll dividers when named as wireScrollDividers targets chrome",
2774
+ "multi-select grid for rich ContentItem rows"
2761
2775
  ],
2762
2776
  "accessibility": [
2763
- "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
2777
+ "List adds layout only and no list role by default; selectionMode=\"multiple\" makes it an aria-multiselectable grid with a required ariaLabel for selectable ContentItem rows.",
2764
2778
  "Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll."
2765
2779
  ],
2766
2780
  "geometry": {
@@ -3312,7 +3326,8 @@
3312
3326
  "useWhen": [
3313
3327
  "An ordinary surface-like child of a Pane or .kui-content stack needs the shared content-item geometry so its content edge lands at the standard 17px inset.",
3314
3328
  "A content item marks a real distinction and must read as visibly bounded: pass frame=\"framed\" (the border is always reserved, so geometry does not change).",
3315
- "A content item should follow a pill control's 22px radius: pass shape=\"pill\"."
3329
+ "A content item should follow a pill control's 22px radius: pass shape=\"pill\".",
3330
+ "A selectable rich card needs nested controls: use selectionMode=\"multiple\" inside a labeled List multi-select grid."
3316
3331
  ],
3317
3332
  "avoidWhen": [
3318
3333
  "Do not wrap a component that already owns content-item geometry (ListItem, ListHeader, StateBanner, Toolbar, ValueTable) or pad around a ContentItem; either double-insets.",
@@ -3342,19 +3357,22 @@
3342
3357
  "whether the item marks a real distinction that warrants a visible frame",
3343
3358
  "corner shape",
3344
3359
  "region semantics and accessible name",
3345
- "whether the item is a programmatic focus target"
3360
+ "whether the item is a programmatic focus target",
3361
+ "the selection set and Shift/Cmd extension for multi-select rich cards"
3346
3362
  ],
3347
3363
  "variants": [
3348
3364
  "unframed rounded item",
3349
3365
  "framed rounded item",
3350
3366
  "pill item",
3351
3367
  "framed pill item",
3352
- "named focus-target region"
3368
+ "named focus-target region",
3369
+ "multi-select rich grid row"
3353
3370
  ],
3354
3371
  "accessibility": [
3355
3372
  "An ordinary item adds no role or name; pass ariaLabel only when the item is a distinct named region (it then renders role=\"region\").",
3356
3373
  "focusTarget makes the item a programmatic focus target (tabindex=\"-1\", never a tab stop), such as a NavStack view's data-nav-focus target.",
3357
- "The frame is decorative and never the only signal of state."
3374
+ "The frame is decorative and never the only signal of state.",
3375
+ "selectionMode=\"multiple\" renders a focusable row with aria-selected and a gridcell for nested controls; place it in a labeled List selectionMode=\"multiple\" grid. wireContentItems moves focus among rows with Up/Down and Home/End while nested controls retain those keys. Guard the app's delegated card action with isContentItemActivation so a nested control does not select the row."
3358
3376
  ],
3359
3377
  "geometry": {
3360
3378
  "margin": "self",
@@ -3837,7 +3855,8 @@
3837
3855
  },
3838
3856
  "useWhen": [
3839
3857
  "Combine DOM-owned free text with ordered editable/removable filter tokens in one searchbox.",
3840
- "Enable collapsible mode when an empty, unfocused search should reduce to one iconic action, standalone or inside a toolbar group."
3858
+ "Enable collapsible mode when an empty, unfocused search should reduce to one iconic action, standalone or inside a toolbar group.",
3859
+ "Use presentation=\"form-field\" for a structured search query beside Web Awesome form controls, with a visible label, optional hint, and required marker."
3841
3860
  ],
3842
3861
  "avoidWhen": [
3843
3862
  "Do not use for ordinary text input or separately labeled filter controls."
@@ -3852,19 +3871,22 @@
3852
3871
  "the grammar and evaluation callback when using the optional managed model, or parsing, suggestions, tokens, and query execution in manual mode",
3853
3872
  "results",
3854
3873
  "the revision that rebuilds the DOM-owned editor for a programmatic text replacement",
3855
- "optional override of the collapsible expand/collapse/focus, which wireTokenSearchFields manages by default (adopt an app expanded signal, opt out per behavior, or drive it via the returned handle)"
3874
+ "optional override of the collapsible expand/collapse/focus, which wireTokenSearchFields manages by default (adopt an app expanded signal, opt out per behavior, or drive it via the returned handle)",
3875
+ "validation of a required form-field value"
3856
3876
  ],
3857
3877
  "variants": [
3858
3878
  "tokens",
3859
3879
  "free text",
3860
3880
  "disabled",
3861
- "collapsible standalone or toolbar composition"
3881
+ "collapsible standalone or toolbar composition",
3882
+ "visible form-field label, hint, and required marker"
3862
3883
  ],
3863
3884
  "accessibility": [
3864
3885
  "Announce result changes when useful and keep tokens atomic during editing.",
3865
3886
  "Keep leading and trailing controls aligned to the first text line while content wraps. Managed Clear restores replacement focus before the next input task, preserving immediate typing and later focus handoffs without a frame delay.",
3866
3887
  "Wire Enter to submit without inserting a contenteditable line break and preserve focus plus the text-relative caret across controlled keyboard chip deletion before the next keystroke. Select All deletion preserves managed open state and replacement focus; persist both edited query and tokens. Visual wrapping remains available.",
3867
- "In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out."
3888
+ "In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out.",
3889
+ "The form-field presentation associates its visible label and optional hint with the searchbox, exposes aria-required when required, and lets wireTokenSearchFields focus the editor from a label click. The app validates required input."
3868
3890
  ],
3869
3891
  "geometry": {
3870
3892
  "margin": "none",
@@ -703,6 +703,11 @@
703
703
  "owner": "application",
704
704
  "required": false
705
705
  },
706
+ {
707
+ "id": "per-view fixed header content above the active view's scroll area",
708
+ "owner": "application",
709
+ "required": false
710
+ },
706
711
  {
707
712
  "id": "top-toolbar configuration, title size, and heading level",
708
713
  "owner": "application",
@@ -783,6 +788,7 @@
783
788
  "kui-nav-stack__chrome-copy",
784
789
  "kui-nav-stack__chrome-copy--bottom",
785
790
  "kui-nav-stack__chrome-copy--exiting",
791
+ "kui-nav-stack__header",
786
792
  "kui-nav-stack__viewport",
787
793
  "kui-nav-stack__view",
788
794
  "kui-nav-stack__view--entering",
@@ -1075,6 +1081,11 @@
1075
1081
  },
1076
1082
  { "id": "collapsed state", "owner": "application", "required": false },
1077
1083
  { "id": "panel sizes", "owner": "application", "required": false },
1084
+ {
1085
+ "id": "navigation panel view stack and push/pop actions when navStack is supplied",
1086
+ "owner": "application",
1087
+ "required": false
1088
+ },
1078
1089
  {
1079
1090
  "id": "responsive replacement below desktop",
1080
1091
  "owner": "application",
@@ -2088,7 +2099,8 @@
2088
2099
  },
2089
2100
  "accessibility": {
2090
2101
  "obligations": [
2091
- "Grid adds layout only and no grid role; children retain responsibility for native or ARIA semantics.",
2102
+ "Grid adds no role by default; selectionMode=multiple requires ariaLabel and supplies a multi-select grid for ContentItem row/gridcell tiles.",
2103
+ "wireContentItems uses rendered tile positions for Left/Right/Up/Down and reaches the first or last tile with Home/End.",
2092
2104
  "Responsive column-count changes preserve source and focus order."
2093
2105
  ]
2094
2106
  },
@@ -2258,6 +2270,11 @@
2258
2270
  "id": "typed gap, flex, alignment, and divider choices",
2259
2271
  "owner": "application",
2260
2272
  "required": false
2273
+ },
2274
+ {
2275
+ "id": "the accessible label and selection state of a multi-select grid",
2276
+ "owner": "application",
2277
+ "required": false
2261
2278
  }
2262
2279
  ],
2263
2280
  "wiring": {
@@ -2293,7 +2310,7 @@
2293
2310
  },
2294
2311
  "accessibility": {
2295
2312
  "obligations": [
2296
- "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
2313
+ "List adds layout only and no list role by default; selectionMode=\"multiple\" makes it an aria-multiselectable grid with a required ariaLabel for selectable ContentItem rows.",
2297
2314
  "Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll."
2298
2315
  ]
2299
2316
  },
@@ -2746,6 +2763,11 @@
2746
2763
  "id": "whether the item is a programmatic focus target",
2747
2764
  "owner": "application",
2748
2765
  "required": false
2766
+ },
2767
+ {
2768
+ "id": "the selection set and Shift/Cmd extension for multi-select rich cards",
2769
+ "owner": "application",
2770
+ "required": false
2749
2771
  }
2750
2772
  ],
2751
2773
  "wiring": {
@@ -2770,7 +2792,8 @@
2770
2792
  "obligations": [
2771
2793
  "An ordinary item adds no role or name; pass ariaLabel only when the item is a distinct named region (it then renders role=\"region\").",
2772
2794
  "focusTarget makes the item a programmatic focus target (tabindex=\"-1\", never a tab stop), such as a NavStack view's data-nav-focus target.",
2773
- "The frame is decorative and never the only signal of state."
2795
+ "The frame is decorative and never the only signal of state.",
2796
+ "selectionMode=\"multiple\" renders a focusable row with aria-selected and a gridcell for nested controls; place it in a labeled List selectionMode=\"multiple\" grid. wireContentItems moves focus among rows with Up/Down and Home/End while nested controls retain those keys. Guard the app's delegated card action with isContentItemActivation so a nested control does not select the row."
2774
2797
  ]
2775
2798
  },
2776
2799
  "cssValueProps": [],
@@ -3243,7 +3266,8 @@
3243
3266
  "Announce result changes when useful and keep tokens atomic during editing.",
3244
3267
  "Keep leading and trailing controls aligned to the first text line while content wraps. Managed Clear restores replacement focus before the next input task, preserving immediate typing and later focus handoffs without a frame delay.",
3245
3268
  "Wire Enter to submit without inserting a contenteditable line break and preserve focus plus the text-relative caret across controlled keyboard chip deletion before the next keystroke. Select All deletion preserves managed open state and replacement focus; persist both edited query and tokens. Visual wrapping remains available.",
3246
- "In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out."
3269
+ "In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out.",
3270
+ "The form-field presentation associates its visible label and optional hint with the searchbox, exposes aria-required when required, and lets wireTokenSearchFields focus the editor from a label click. The app validates required input."
3247
3271
  ]
3248
3272
  },
3249
3273
  "cssValueProps": [],
@@ -13,6 +13,7 @@ Render one self-contained .kui-content child that owns its 8px inline margin, re
13
13
  - An ordinary surface-like child of a Pane or .kui-content stack needs the shared content-item geometry so its content edge lands at the standard 17px inset.
14
14
  - A content item marks a real distinction and must read as visibly bounded: pass frame="framed" (the border is always reserved, so geometry does not change).
15
15
  - A content item should follow a pill control's 22px radius: pass shape="pill".
16
+ - A selectable rich card needs nested controls: use selectionMode="multiple" inside a labeled List multi-select grid.
16
17
 
17
18
  **Not when:**
18
19
 
@@ -44,6 +45,7 @@ Exact prop names and types: [`@kerfjs/ui/content-item`](../public-api-signatures
44
45
  - pill item
45
46
  - framed pill item
46
47
  - named focus-target region
48
+ - multi-select rich grid row
47
49
 
48
50
  ## Composition
49
51
 
@@ -53,7 +55,7 @@ Exact prop names and types: [`@kerfjs/ui/content-item`](../public-api-signatures
53
55
 
54
56
  ## State and wiring
55
57
 
56
- **The app owns:** the item content; whether the item marks a real distinction that warrants a visible frame; corner shape; region semantics and accessible name; whether the item is a programmatic focus target.
58
+ **The app owns:** the item content; whether the item marks a real distinction that warrants a visible frame; corner shape; region semantics and accessible name; whether the item is a programmatic focus target; the selection set and Shift/Cmd extension for multi-select rich cards.
57
59
 
58
60
  No wiring helper.
59
61
 
@@ -68,6 +70,7 @@ Margin: self · border: self · padding: self (layout role: structure). `self` m
68
70
  - An ordinary item adds no role or name; pass ariaLabel only when the item is a distinct named region (it then renders role="region").
69
71
  - focusTarget makes the item a programmatic focus target (tabindex="-1", never a tab stop), such as a NavStack view's data-nav-focus target.
70
72
  - The frame is decorative and never the only signal of state.
73
+ - selectionMode="multiple" renders a focusable row with aria-selected and a gridcell for nested controls; place it in a labeled List selectionMode="multiple" grid. wireContentItems moves focus among rows with Up/Down and Home/End while nested controls retain those keys. Guard the app's delegated card action with isContentItemActivation so a nested control does not select the row.
71
74
 
72
75
  ## Styling boundary
73
76
 
@@ -47,6 +47,7 @@ Exact prop names and types: [`@kerfjs/ui/grid`](../public-api-signatures-v1.md#k
47
47
  - boolean, finite-keyword, or typed CssFlex flex
48
48
  - fill: the layout root fills a definite-height parent
49
49
  - rootAttributes: safe data-\* metadata on the root
50
+ - selectionMode=multiple: labeled multi-select grid for ContentItem tiles
50
51
 
51
52
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
52
53
 
@@ -74,7 +75,8 @@ Margin: none · border: none · padding: none (layout role: structure). `self` m
74
75
 
75
76
  ## Accessibility
76
77
 
77
- - Grid adds layout only and no grid role; children retain responsibility for native or ARIA semantics.
78
+ - Grid adds no role by default; selectionMode=multiple requires ariaLabel and supplies a multi-select grid for ContentItem row/gridcell tiles.
79
+ - wireContentItems uses rendered tile positions for Left/Right/Up/Down and reaches the first or last tile with Home/End.
78
80
  - Responsive column-count changes preserve source and focus order.
79
81
 
80
82
  ## Styling boundary
@@ -16,6 +16,7 @@ Standardize vertical component layout, optional physical-side text/control inset
16
16
  - Use a finite flex keyword or the flex() builder when List participates in flexible layout.
17
17
  - Apply the standard text or control inset to selected physical sides without an application wrapper.
18
18
  - Align children horizontally or distribute them vertically with the same physical alignment vocabulary as Row.
19
+ - Use selectionMode="multiple" and ariaLabel to group selectable rich ContentItem rows in a multi-select grid.
19
20
 
20
21
  **Not when:**
21
22
 
@@ -49,6 +50,7 @@ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#k
49
50
  - fill: the layout root fills a definite-height parent
50
51
  - rootAttributes: safe data-\* metadata on the root
51
52
  - scroll dividers when named as wireScrollDividers targets chrome
53
+ - multi-select grid for rich ContentItem rows
52
54
 
53
55
  **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
54
56
 
@@ -64,7 +66,7 @@ Exact prop names and types: [`@kerfjs/ui/list`](../public-api-signatures-v1.md#k
64
66
 
65
67
  ## State and wiring
66
68
 
67
- **The app owns:** child semantics and content; the bounded height needed for scrolling; typed gap, flex, alignment, and divider choices.
69
+ **The app owns:** child semantics and content; the bounded height needed for scrolling; typed gap, flex, alignment, and divider choices; the accessible label and selection state of a multi-select grid.
68
70
 
69
71
  **Wiring:** `wireScrollDividers` is optional.
70
72
 
@@ -81,7 +83,7 @@ Margin: none · border: conditional · padding: conditional (layout role: naviga
81
83
 
82
84
  ## Accessibility
83
85
 
84
- - List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.
86
+ - List adds layout only and no list role by default; selectionMode="multiple" makes it an aria-multiselectable grid with a required ariaLabel for selectable ContentItem rows.
85
87
  - Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll.
86
88
 
87
89
  ## Styling boundary
@@ -43,6 +43,7 @@ Exact prop names and types: [`@kerfjs/ui/nav-stack`](../public-api-signatures-v1
43
43
  - configured top toolbar
44
44
  - custom back icon or visible back text
45
45
  - per-view bottom toolbar
46
+ - persistent final top-toolbar group (panelToggle) when embedded in a Workbench panel
46
47
  - persistent bottom-toolbar fallback
47
48
  - chrome and bottom-toolbar dividers only while the active view scrolls beneath them (wired by wireScrollDividers)
48
49
  - permanent or no chrome dividers (chromeDividers always or none)
@@ -56,7 +57,7 @@ Exact prop names and types: [`@kerfjs/ui/nav-stack`](../public-api-signatures-v1
56
57
 
57
58
  ## State and wiring
58
59
 
59
- **The app owns:** ordered view stack and stable keys; view content and titles; push and pop actions; preferred initial focus targets when DOM order is insufficient; per-view bottom toolbar content or a persistent fallback; per-view leading, center, and trailing top-toolbar groups; top-toolbar configuration, title size, and heading level; whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers).
60
+ **The app owns:** ordered view stack and stable keys; view content and titles; push and pop actions; preferred initial focus targets when DOM order is insufficient; per-view bottom toolbar content or a persistent fallback; per-view leading, center, and trailing top-toolbar groups; per-view fixed header content above the active view's scroll area; top-toolbar configuration, title size, and heading level; whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers).
60
61
 
61
62
  **Wiring:** `wireNavStack`, `wireScrollDividers` is required.
62
63
 
@@ -88,9 +89,9 @@ Margin: none · border: conditional · padding: child (layout role: structure).
88
89
 
89
90
  The component owns its own styles. Configure it through its props and variants; do not override its internals.
90
91
 
91
- Public class hooks (select for layout placement only, never to change the component's look): `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting`.
92
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__header`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting`.
92
93
 
93
- Never put `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting` on an element you write; render `NavStack` instead (`KUI-L103`).
94
+ Never put `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__header`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting` on an element you write; render `NavStack` instead (`KUI-L103`).
94
95
 
95
96
  Public tokens it reads: `--kui-nav-stack-transition-duration`. Set a token only where its public contract allows; prefer a prop.
96
97
 
@@ -10,6 +10,7 @@ Token-controlled, optionally collapsible search editor with ordered, editable, r
10
10
 
11
11
  - Combine DOM-owned free text with ordered editable/removable filter tokens in one searchbox.
12
12
  - Enable collapsible mode when an empty, unfocused search should reduce to one iconic action, standalone or inside a toolbar group.
13
+ - Use presentation="form-field" for a structured search query beside Web Awesome form controls, with a visible label, optional hint, and required marker.
13
14
 
14
15
  **Not when:**
15
16
 
@@ -40,6 +41,7 @@ Exact prop names and types: [`@kerfjs/ui/token-search-field`](../public-api-sign
40
41
  - free text
41
42
  - disabled
42
43
  - collapsible standalone or toolbar composition
44
+ - visible form-field label, hint, and required marker
43
45
 
44
46
  ## Composition
45
47
 
@@ -79,6 +81,7 @@ Margin: none · border: self · padding: self (layout role: controls). `self` me
79
81
  - Keep leading and trailing controls aligned to the first text line while content wraps. Managed Clear restores replacement focus before the next input task, preserving immediate typing and later focus handoffs without a frame delay.
80
82
  - Wire Enter to submit without inserting a contenteditable line break and preserve focus plus the text-relative caret across controlled keyboard chip deletion before the next keystroke. Select All deletion preserves managed open state and replacement focus; persist both edited query and tokens. Visual wrapping remains available.
81
83
  - In collapsible mode, wireTokenSearchFields manages this by default: activating the trigger reveals the searchbox and moves focus into it, Escape on an empty field collapses and returns focus to the trigger, and focus leaving an empty field collapses it; each behavior is individually opt-out.
84
+ - The form-field presentation associates its visible label and optional hint with the searchbox, exposes aria-required when required, and lets wireTokenSearchFields focus the editor from a label click. The app validates required input.
82
85
 
83
86
  ## Styling boundary
84
87
 
@@ -25,7 +25,7 @@ Arrange a complex tool or editor as a stable central work area with optional per
25
25
 
26
26
  ## Imports
27
27
 
28
- - JavaScript: `@kerfjs/ui/workbench` — exports `Workbench`, `WorkbenchChromePlacement`, `WorkbenchCompactOverlay`, `WorkbenchMainBottomToolbar`, `WorkbenchMainToolbar`, `WorkbenchPanel`, `WorkbenchPanelResizable`, `WorkbenchPanelToggle`, `WorkbenchPanelToolbar`, `WorkbenchProps`, `WorkbenchResponsiveOverlayAt`.
28
+ - JavaScript: `@kerfjs/ui/workbench` — exports `Workbench`, `WorkbenchChromePlacement`, `WorkbenchCompactOverlay`, `WorkbenchMainBottomToolbar`, `WorkbenchMainToolbar`, `WorkbenchPanel`, `WorkbenchStaticPanel`, `WorkbenchNavigationPanel`, `WorkbenchPanelResizable`, `WorkbenchPanelToggle`, `WorkbenchPanelToolbar`, `WorkbenchProps`, `WorkbenchResponsiveOverlayAt`.
29
29
  - CSS: the browser build of `@kerfjs/ui/workbench` pulls its CSS automatically; import `@kerfjs/ui/workbench.css` manually only without the `browser` export condition.
30
30
  - Wiring: `wireWorkbench` from `@kerfjs/ui/wire-workbench` (optional).
31
31
  - Wiring: `wireScrollDividers` from `@kerfjs/ui/wire-scroll-dividers` (optional).
@@ -43,6 +43,7 @@ Exact prop names and types: [`@kerfjs/ui/workbench`](../public-api-signatures-v1
43
43
  - bottom drawer
44
44
  - all panels
45
45
  - independently collapsed panels
46
+ - navigation panel with per-screen toolbar, fixed header, and one scroll owner; standard toggle remains last and relocates while collapsed
46
47
  - opt-in drag and keyboard resizable panels with min/max limits
47
48
  - resizable rails that leave the work area a minimum width and shrink in proportion when the Workbench narrows
48
49
  - rails or a drawer that present as overlays below a narrow or compact Workbench container breakpoint
@@ -60,6 +61,7 @@ Exact prop names and types: [`@kerfjs/ui/workbench`](../public-api-signatures-v1
60
61
  - Parents: any.
61
62
  - Contexts: `desktop-application-shell`.
62
63
  - Children: unrestricted.
64
+ - Built from: [NavStack](./nav-stack.md).
63
65
 
64
66
  Zones (a zone is bound to JSX only through its listed prop; never assume the zone id is a prop):
65
67
 
@@ -70,7 +72,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
70
72
 
71
73
  ## State and wiring
72
74
 
73
- **The app owns:** panel presence and content; collapsed state; panel sizes; responsive replacement below desktop; collapse controls and focus policy.
75
+ **The app owns:** panel presence and content; collapsed state; panel sizes; navigation panel view stack and push/pop actions when navStack is supplied; responsive replacement below desktop; collapse controls and focus policy.
74
76
 
75
77
  **Wiring:** `wireWorkbench`, `wireScrollDividers` is optional.
76
78
 
@@ -111,6 +113,6 @@ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-
111
113
 
112
114
  ## Related
113
115
 
114
- - Components: [Pane](./pane.md).
116
+ - Components: [NavStack](./nav-stack.md), [Pane](./pane.md).
115
117
  - Docs: [`docs/workbench.md`](../../docs/workbench.md), [`docs/workbench.md#state-lives-in-the-app`](../../docs/workbench.md#state-lives-in-the-app).
116
118
  - UX catalog route: `?component=workbench`.