@kerfjs/ui 5.0.0-beta.58 → 5.0.0-beta.59
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 +11 -1
- package/ai/component-catalog.json +48 -15
- package/ai/component-catalog.schema.json +16 -0
- package/ai/component-composition.json +16 -2
- package/ai/components/README.md +2 -2
- package/ai/components/popup-menu.md +96 -7
- package/ai/components/text.md +3 -3
- package/ai/components/token-search-field.md +6 -4
- package/ai/public-api-signatures-v1.md +49 -81
- package/ai/skill.md +5 -1
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/catalog.js +3 -3
- package/dist/chunk-F7F7KRO2.js +187 -0
- package/dist/chunk-F7F7KRO2.js.map +1 -0
- package/dist/{chunk-63ZWBGE3.js → chunk-RRB26JRJ.js} +25 -3
- package/dist/chunk-RRB26JRJ.js.map +1 -0
- package/dist/{chunk-NBYTIVHS.js → chunk-UFYZHYWU.js} +118 -12
- package/dist/chunk-UFYZHYWU.js.map +1 -0
- package/dist/{chunk-WLG6SSNT.js → chunk-UWONG4QE.js} +41 -8
- package/dist/chunk-UWONG4QE.js.map +1 -0
- package/dist/{chunk-553ASUK6.js → chunk-UX2VVXZ3.js} +2 -2
- package/dist/{chunk-553ASUK6.js.map → chunk-UX2VVXZ3.js.map} +1 -1
- package/dist/{chunk-24PHKUR3.js → chunk-UXT7TE6B.js} +1 -1
- package/dist/chunk-UXT7TE6B.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -5
- package/dist/list-header.js +1 -1
- package/dist/popup-menu.d.ts +31 -3
- package/dist/popup-menu.js +1 -1
- package/dist/styles/popup-menu.css +33 -4
- package/dist/styles/text.css +8 -0
- package/dist/styles/token-search-field.css +29 -0
- package/dist/text.d.ts +1 -1
- package/dist/text.js +1 -1
- package/dist/token-search-field-CCke1yvQ.d.ts +126 -0
- package/dist/token-search-field.d.ts +3 -75
- package/dist/token-search-field.js +1 -1
- package/dist/token-search-model.d.ts +3 -0
- package/dist/token-search-model.js +3 -0
- package/dist/token-search-model.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +5 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/docs/accessibility.md +14 -0
- package/docs/component-contract.md +2 -1
- package/docs/component-integration.md +8 -1
- package/docs/component-selection.md +40 -0
- package/docs/layout.md +4 -1
- package/llms.txt +6 -3
- package/package.json +5 -1
- package/dist/chunk-24PHKUR3.js.map +0 -1
- package/dist/chunk-63ZWBGE3.js.map +0 -1
- package/dist/chunk-NBYTIVHS.js.map +0 -1
- package/dist/chunk-WLG6SSNT.js.map +0 -1
package/README.md
CHANGED
|
@@ -224,6 +224,7 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
|
|
|
224
224
|
| `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
|
|
225
225
|
| `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret` | `@kerfjs/ui/token-search-field` | `@kerfjs/ui/token-search-field.css` |
|
|
226
226
|
| `wireTokenSearchFields` | `@kerfjs/ui/wire-token-search-fields` | — |
|
|
227
|
+
| `createTokenSearchModel` | `@kerfjs/ui/token-search-model` | — |
|
|
227
228
|
| `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
|
|
228
229
|
| `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
|
|
229
230
|
| `ValueTable`, `ValueTableRow` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
|
|
@@ -638,7 +639,14 @@ value through `data-segment-value`. Override an instance through
|
|
|
638
639
|
free text and ordered filter chips in one field. Its editable text stays
|
|
639
640
|
DOM-owned between token changes so typing does not replace the caret. Tokens
|
|
640
641
|
expose stable edit/remove actions and remain atomic during editing; the app owns
|
|
641
|
-
parsing, suggestions, query execution, and state.
|
|
642
|
+
parsing, suggestions, query execution, and state in manual mode. For automatic
|
|
643
|
+
handling, create a model with `createTokenSearchModel({ rules, evaluate })`,
|
|
644
|
+
pass it as the field's `model`, and register it under the field id in
|
|
645
|
+
`wireTokenSearchFields(root, { models })`. Rules parse `name:value` expressions;
|
|
646
|
+
their optional `suggest` function supplies selectable completions. The model
|
|
647
|
+
commits valid expressions on whitespace or Enter, owns chips and clear/edit/
|
|
648
|
+
remove actions, and exposes `state`, `suggestions`, and the latest `result` as
|
|
649
|
+
signals. Omit the model to retain full manual control. Use `readTokenSearchField()`
|
|
642
650
|
after browser input to recover text plus token offsets, and
|
|
643
651
|
`placeTokenSearchCaret()` when restoring focus after a controlled update.
|
|
644
652
|
Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
|
|
@@ -693,6 +701,8 @@ import "@kerfjs/ui/select/register";
|
|
|
693
701
|
```
|
|
694
702
|
|
|
695
703
|
That boundary keeps Web Awesome and its custom-element side effects out of bundles that use unrelated components. Automated consumer-bundle tests enforce it. `PopupMenu` follows the same rule: import `@kerfjs/ui/popup-menu/register` once to register the dropdown, item, button, and divider elements it renders. Either registration also installs help tags: an icon-only Select, PopupMenu, or `aria-label`-named `<button>` in a `ToolbarControlGroup` shows its name in an `aria-hidden` tooltip on hover and keyboard focus. A toolbar with icon-only buttons but neither control imports `@kerfjs/ui/help-tags/register`, which registers only the tooltip.
|
|
704
|
+
|
|
705
|
+
`PopupMenu` items may include `submenu` children, `checked` choices, a leading `icon`, trailing `details`, `disabledReason`, and a `danger` tone. The app owns choice state and dispatches each item's `action`. For a right-click menu, set `context: true` and a `label`, then call `openPopupMenuAt(menu, event.clientX, event.clientY)` from the app's `contextmenu` handler; `closePopupMenu(menu)` closes it programmatically. See [component selection](docs/component-selection.md#popup-menu-migration) for examples.
|
|
696
706
|
Use `label` for a visible label or `ariaLabel` for a visually hidden name. A
|
|
697
707
|
nonempty visible label takes precedence when both are supplied. Kerf names the
|
|
698
708
|
actual shadow combobox without adding visible label spacing; this also works
|
|
@@ -1840,7 +1840,7 @@
|
|
|
1840
1840
|
"source": "kerf",
|
|
1841
1841
|
"description": "Semantic native paragraph text by default, with heading and inline-span variants plus composable semantic presentation roles.",
|
|
1842
1842
|
"uses": [],
|
|
1843
|
-
"purpose": "Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact size, or monospace font.",
|
|
1843
|
+
"purpose": "Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact through extra-large size, or monospace font.",
|
|
1844
1844
|
"publicExports": [
|
|
1845
1845
|
"Text"
|
|
1846
1846
|
],
|
|
@@ -1872,7 +1872,7 @@
|
|
|
1872
1872
|
"variants": [
|
|
1873
1873
|
"p, h1 through h6, or inline span semantic variant",
|
|
1874
1874
|
"default, quiet, or danger tone",
|
|
1875
|
-
"default or
|
|
1875
|
+
"compact, default, large, or xlarge size",
|
|
1876
1876
|
"default or monospace font"
|
|
1877
1877
|
],
|
|
1878
1878
|
"accessibility": [
|
|
@@ -1902,6 +1902,8 @@
|
|
|
1902
1902
|
"publicTokens": [
|
|
1903
1903
|
"--kui-color-danger-on-quiet",
|
|
1904
1904
|
"--kui-color-text-quiet",
|
|
1905
|
+
"--kui-font-2xl",
|
|
1906
|
+
"--kui-font-l",
|
|
1905
1907
|
"--kui-font-mono",
|
|
1906
1908
|
"--kui-font-xs",
|
|
1907
1909
|
"--kui-layout-item-padding"
|
|
@@ -3641,8 +3643,13 @@
|
|
|
3641
3643
|
"TokenSearchField",
|
|
3642
3644
|
"readTokenSearchField",
|
|
3643
3645
|
"placeTokenSearchCaret",
|
|
3644
|
-
"wireTokenSearchFields"
|
|
3646
|
+
"wireTokenSearchFields",
|
|
3647
|
+
"createTokenSearchModel"
|
|
3645
3648
|
],
|
|
3649
|
+
"publicExportImports": {
|
|
3650
|
+
"wireTokenSearchFields": "@kerfjs/ui/wire-token-search-fields",
|
|
3651
|
+
"createTokenSearchModel": "@kerfjs/ui/token-search-model"
|
|
3652
|
+
},
|
|
3646
3653
|
"useWhen": [
|
|
3647
3654
|
"Combine DOM-owned free text with ordered editable/removable filter tokens in one searchbox.",
|
|
3648
3655
|
"Enable collapsible mode when an empty, unfocused search should reduce to one iconic action, standalone or inside a toolbar group."
|
|
@@ -3657,10 +3664,7 @@
|
|
|
3657
3664
|
}
|
|
3658
3665
|
],
|
|
3659
3666
|
"appOwns": [
|
|
3660
|
-
"parsing",
|
|
3661
|
-
"suggestions",
|
|
3662
|
-
"tokens",
|
|
3663
|
-
"query execution",
|
|
3667
|
+
"the grammar and evaluation callback when using the optional managed model, or parsing, suggestions, tokens, and query execution in manual mode",
|
|
3664
3668
|
"results",
|
|
3665
3669
|
"the revision that rebuilds the DOM-owned editor for a programmatic text replacement",
|
|
3666
3670
|
"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)"
|
|
@@ -3727,6 +3731,8 @@
|
|
|
3727
3731
|
"kui-token-search__token",
|
|
3728
3732
|
"kui-token-search__token-edit",
|
|
3729
3733
|
"kui-token-search__token-remove",
|
|
3734
|
+
"kui-token-search__suggestions",
|
|
3735
|
+
"kui-token-search__suggestion",
|
|
3730
3736
|
"kui-token-search__trailing"
|
|
3731
3737
|
],
|
|
3732
3738
|
"publicTokens": [
|
|
@@ -4018,20 +4024,23 @@
|
|
|
4018
4024
|
"category": "Controls",
|
|
4019
4025
|
"kind": "component",
|
|
4020
4026
|
"source": "kerf",
|
|
4021
|
-
"description": "A
|
|
4027
|
+
"description": "A typed action menu with nested choices, selected state, and optional pointer-anchored context opening, built on the Web Awesome dropdown.",
|
|
4022
4028
|
"uses": [
|
|
4023
4029
|
"wa-dropdown",
|
|
4024
4030
|
"wa-dropdown-item",
|
|
4025
4031
|
"wa-button",
|
|
4026
4032
|
"wa-divider"
|
|
4027
4033
|
],
|
|
4028
|
-
"purpose": "A
|
|
4034
|
+
"purpose": "A typed action menu with nested choices, selected state, and optional pointer-anchored context opening, built on the Web Awesome dropdown.",
|
|
4029
4035
|
"publicExports": [
|
|
4030
|
-
"PopupMenu"
|
|
4036
|
+
"PopupMenu",
|
|
4037
|
+
"openPopupMenuAt",
|
|
4038
|
+
"closePopupMenu"
|
|
4031
4039
|
],
|
|
4032
4040
|
"useWhen": [
|
|
4033
4041
|
"Offer a short list of commands behind one trigger, such as a toolbar sort or More menu.",
|
|
4034
|
-
"Group related commands under headings and dividers in one popup."
|
|
4042
|
+
"Group related commands under headings and dividers in one popup.",
|
|
4043
|
+
"Nest decisions under a parent command, show checked or trailing choice state, or open a context menu at pointer coordinates."
|
|
4035
4044
|
],
|
|
4036
4045
|
"avoidWhen": [
|
|
4037
4046
|
"Do not use it to choose a persistent value (use Select) or for navigation rows (use ListItem).",
|
|
@@ -4050,7 +4059,8 @@
|
|
|
4050
4059
|
"appOwns": [
|
|
4051
4060
|
"commands and their delegated actions",
|
|
4052
4061
|
"which items are enabled",
|
|
4053
|
-
"reactions to the menu opening or closing"
|
|
4062
|
+
"reactions to the menu opening or closing",
|
|
4063
|
+
"contextmenu event handling and identification of the menu root when using a pointer-anchored context menu"
|
|
4054
4064
|
],
|
|
4055
4065
|
"variants": [
|
|
4056
4066
|
"icon trigger",
|
|
@@ -4059,10 +4069,31 @@
|
|
|
4059
4069
|
"headings and dividers",
|
|
4060
4070
|
"item icons",
|
|
4061
4071
|
"disabled items",
|
|
4072
|
+
"nested actions",
|
|
4073
|
+
"checked choices and trailing details",
|
|
4074
|
+
"danger tone and disabled reasons",
|
|
4075
|
+
"context trigger",
|
|
4062
4076
|
"placement"
|
|
4063
4077
|
],
|
|
4078
|
+
"usageExamples": [
|
|
4079
|
+
{
|
|
4080
|
+
"title": "Nested decisions",
|
|
4081
|
+
"description": "The app owns the current decision, batch disabled state, and delegated actions. Each child keeps its own record metadata.",
|
|
4082
|
+
"code": "<PopupMenu\n label=\"Line actions\"\n items={[\n { label: 'Decide', submenu: [\n { label: 'Approve', action: 'decide', checked: current === 'approve',\n attributes: { 'data-line-id': lineId, 'data-decision': 'approve' } },\n { label: 'Reject', action: 'decide', tone: 'danger',\n disabled: needsPrice, disabledReason: needsPrice ? 'Add a price first' : undefined,\n attributes: { 'data-line-id': lineId, 'data-decision': 'reject' } },\n ] },\n { kind: 'divider' },\n { label: 'Remove', action: 'remove', tone: 'danger' },\n ]}\n/>"
|
|
4083
|
+
},
|
|
4084
|
+
{
|
|
4085
|
+
"title": "Flat selected choices",
|
|
4086
|
+
"description": "Headings separate sort dimensions; trailing safe content marks the active command without changing its accessible label.",
|
|
4087
|
+
"code": "<PopupMenu\n label=\"Sort chat\"\n items={[\n { kind: 'heading', label: 'Sort by' },\n { label: 'Updated', action: 'sort-updated', details: sort === 'updated' ? tick : undefined },\n { label: 'Priority', action: 'sort-priority', details: sort === 'priority' ? tick : undefined },\n { kind: 'heading', label: 'Order' },\n { label: 'Newest first', action: 'order-newest', details: order === 'newest' ? tick : undefined },\n ]}\n/>"
|
|
4088
|
+
},
|
|
4089
|
+
{
|
|
4090
|
+
"title": "Pointer anchored context menu",
|
|
4091
|
+
"description": "Keep the row's visible disabled action separate from the context menu anchor. Find the menu root with a stable data attribute.",
|
|
4092
|
+
"code": "<PopupMenu\n context\n label=\"Demand actions\"\n rootAttributes={{ 'data-demand-menu': '' }}\n items={[{ label: 'Open', action: 'open-demand' }]}\n/>\n// In the app's row wiring:\nrow.addEventListener('contextmenu', (event) => {\n event.preventDefault();\n const menu = row.querySelector('[data-demand-menu]') as PopupMenuElement;\n openPopupMenuAt(menu, event.clientX, event.clientY);\n});\n// Call closePopupMenu(menu) when the app needs to dismiss it."
|
|
4093
|
+
}
|
|
4094
|
+
],
|
|
4064
4095
|
"accessibility": [
|
|
4065
|
-
"An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. Web Awesome provides menu roles, arrow-key navigation, typeahead, and Escape.",
|
|
4096
|
+
"An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. The context anchor stays out of the accessibility tree. Web Awesome provides menu roles, nested arrow-key navigation, typeahead, and Escape.",
|
|
4066
4097
|
"Once registered, an icon-only trigger shows its label as an aria-hidden Web Awesome help tag after a 500ms hover and at once on keyboard focus; it hides while the menu is open, on a press, and on Escape, and never joins aria-labelledby. Do not add a title or another tooltip."
|
|
4067
4098
|
],
|
|
4068
4099
|
"geometry": {
|
|
@@ -4083,13 +4114,15 @@
|
|
|
4083
4114
|
"wiring": [],
|
|
4084
4115
|
"publicClasses": [
|
|
4085
4116
|
"kui-popup-menu",
|
|
4086
|
-
"kui-popup-menu__label"
|
|
4117
|
+
"kui-popup-menu__label",
|
|
4118
|
+
"kui-popup-menu__details",
|
|
4119
|
+
"kui-popup-menu__context-anchor"
|
|
4087
4120
|
],
|
|
4088
4121
|
"publicTokens": [],
|
|
4089
4122
|
"links": {
|
|
4090
4123
|
"catalogRoute": "?component=popup-menu",
|
|
4091
4124
|
"documentation": "docs/component-selection.md",
|
|
4092
|
-
"recipe": "docs/component-selection.md#
|
|
4125
|
+
"recipe": "docs/component-selection.md#popup-menu-migration"
|
|
4093
4126
|
}
|
|
4094
4127
|
},
|
|
4095
4128
|
{
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"purpose": { "type": "string", "minLength": 1 },
|
|
30
30
|
"customElement": { "type": "string" },
|
|
31
31
|
"publicExports": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
32
|
+
"publicExportImports": {
|
|
33
|
+
"description": "Subpath overrides for public exports that do not live in the component delivery import.",
|
|
34
|
+
"type": "object",
|
|
35
|
+
"additionalProperties": { "type": "string", "minLength": 1 }
|
|
36
|
+
},
|
|
32
37
|
"useWhen": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
33
38
|
"avoidWhen": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
34
39
|
"recommendation": { "enum": ["supported", "conditional", "exceptional", "underlying", "avoid"] },
|
|
@@ -37,6 +42,7 @@
|
|
|
37
42
|
"wiring": { "type": "array", "items": { "$ref": "#/$defs/wiring" } },
|
|
38
43
|
"appOwns": { "type": "array", "items": { "type": "string" } },
|
|
39
44
|
"variants": { "type": "array", "items": { "type": "string" } },
|
|
45
|
+
"usageExamples": { "type": "array", "items": { "$ref": "#/$defs/usageExample" } },
|
|
40
46
|
"accessibility": { "type": "array", "items": { "type": "string" } },
|
|
41
47
|
"publicClasses": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
42
48
|
"placeableClasses": { "description": "Public classes an application may place on its own elements (layout utilities, a document root, or item geometry on a non-div carrier). Every other public class is component anatomy: render the component instead.", "type": "array", "items": { "type": "string" }, "uniqueItems": true },
|
|
@@ -49,6 +55,16 @@
|
|
|
49
55
|
},
|
|
50
56
|
"additionalProperties": false
|
|
51
57
|
},
|
|
58
|
+
"usageExample": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"required": ["title", "code"],
|
|
61
|
+
"properties": {
|
|
62
|
+
"title": { "type": "string", "minLength": 1 },
|
|
63
|
+
"description": { "type": "string" },
|
|
64
|
+
"code": { "type": "string", "minLength": 1 }
|
|
65
|
+
},
|
|
66
|
+
"additionalProperties": false
|
|
67
|
+
},
|
|
52
68
|
"geometry": {
|
|
53
69
|
"type": "object",
|
|
54
70
|
"required": ["margin", "border", "padding"],
|
|
@@ -1733,6 +1733,8 @@
|
|
|
1733
1733
|
"publicTokens": [
|
|
1734
1734
|
"--kui-color-danger-on-quiet",
|
|
1735
1735
|
"--kui-color-text-quiet",
|
|
1736
|
+
"--kui-font-2xl",
|
|
1737
|
+
"--kui-font-l",
|
|
1736
1738
|
"--kui-font-mono",
|
|
1737
1739
|
"--kui-font-xs",
|
|
1738
1740
|
"--kui-layout-item-padding"
|
|
@@ -3084,6 +3086,8 @@
|
|
|
3084
3086
|
"kui-token-search__token",
|
|
3085
3087
|
"kui-token-search__token-edit",
|
|
3086
3088
|
"kui-token-search__token-remove",
|
|
3089
|
+
"kui-token-search__suggestions",
|
|
3090
|
+
"kui-token-search__suggestion",
|
|
3087
3091
|
"kui-token-search__trailing"
|
|
3088
3092
|
],
|
|
3089
3093
|
"publicTokens": [
|
|
@@ -3321,6 +3325,11 @@
|
|
|
3321
3325
|
"id": "reactions to the menu opening or closing",
|
|
3322
3326
|
"owner": "application",
|
|
3323
3327
|
"required": false
|
|
3328
|
+
},
|
|
3329
|
+
{
|
|
3330
|
+
"id": "contextmenu event handling and identification of the menu root when using a pointer-anchored context menu",
|
|
3331
|
+
"owner": "application",
|
|
3332
|
+
"required": false
|
|
3324
3333
|
}
|
|
3325
3334
|
],
|
|
3326
3335
|
"wiring": {
|
|
@@ -3336,14 +3345,19 @@
|
|
|
3336
3345
|
},
|
|
3337
3346
|
"accessibility": {
|
|
3338
3347
|
"obligations": [
|
|
3339
|
-
"An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. Web Awesome provides menu roles, arrow-key navigation, typeahead, and Escape.",
|
|
3348
|
+
"An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. The context anchor stays out of the accessibility tree. Web Awesome provides menu roles, nested arrow-key navigation, typeahead, and Escape.",
|
|
3340
3349
|
"Once registered, an icon-only trigger shows its label as an aria-hidden Web Awesome help tag after a 500ms hover and at once on keyboard focus; it hides while the menu is open, on a press, and on Escape, and never joins aria-labelledby. Do not add a title or another tooltip."
|
|
3341
3350
|
]
|
|
3342
3351
|
},
|
|
3343
3352
|
"cssValueProps": [],
|
|
3344
3353
|
"boundaries": {
|
|
3345
3354
|
"rootClass": "kui-popup-menu",
|
|
3346
|
-
"publicClasses": [
|
|
3355
|
+
"publicClasses": [
|
|
3356
|
+
"kui-popup-menu",
|
|
3357
|
+
"kui-popup-menu__label",
|
|
3358
|
+
"kui-popup-menu__details",
|
|
3359
|
+
"kui-popup-menu__context-anchor"
|
|
3360
|
+
],
|
|
3347
3361
|
"publicTokens": []
|
|
3348
3362
|
},
|
|
3349
3363
|
"diagnostics": [],
|
package/ai/components/README.md
CHANGED
|
@@ -29,7 +29,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
|
|
|
29
29
|
- [Surface scaffolds](./surface-scaffold.md) — Configure recurring dialog and popup geometry without consumer ::part() overrides.
|
|
30
30
|
- [FloatingToolbar](./floating-toolbar.md) — A transparent, forced-dark toolbar that floats over its container's content.
|
|
31
31
|
- [ToolbarText](./toolbar-text.md) — Large, default, and compact toolbar identity text.
|
|
32
|
-
- [Text](./text.md) — Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact size, or monospace font.
|
|
32
|
+
- [Text](./text.md) — Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact through extra-large size, or monospace font.
|
|
33
33
|
- [Headers](./headers.md) — Page, dialog, and definition-list hierarchy.
|
|
34
34
|
- [ValueTable](./value-table.md) — Key/value rows with optional icons and aligned separators.
|
|
35
35
|
- [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.
|
|
@@ -55,7 +55,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
|
|
|
55
55
|
- [TokenSearchField](./token-search-field.md) — Token-controlled, optionally collapsible search editor with ordered, editable, removable filter chips.
|
|
56
56
|
- [ResizableRegion](./resize.md) — Pointer and keyboard-operable split region with a customizable handle icon.
|
|
57
57
|
- [Select](./select.md) — Controlled Web Awesome select with typed form, toolbar, navigation, compact, icon-only, truncating, hint, and grouped-choice presentations.
|
|
58
|
-
- [PopupMenu](./popup-menu.md) — A
|
|
58
|
+
- [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
59
|
|
|
60
60
|
## Kerf UI — Feedback
|
|
61
61
|
|
|
@@ -6,10 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
## When to use
|
|
8
8
|
|
|
9
|
-
A
|
|
9
|
+
A typed action menu with nested choices, selected state, and optional pointer-anchored context opening, built on the Web Awesome dropdown.
|
|
10
10
|
|
|
11
11
|
- Offer a short list of commands behind one trigger, such as a toolbar sort or More menu.
|
|
12
12
|
- Group related commands under headings and dividers in one popup.
|
|
13
|
+
- Nest decisions under a parent command, show checked or trailing choice state, or open a context menu at pointer coordinates.
|
|
13
14
|
|
|
14
15
|
**Not when:**
|
|
15
16
|
|
|
@@ -23,7 +24,7 @@ A trigger button that opens a typed list of commands, built on the Web Awesome d
|
|
|
23
24
|
|
|
24
25
|
## Imports
|
|
25
26
|
|
|
26
|
-
- JavaScript: `@kerfjs/ui/popup-menu` — exports `PopupMenu`.
|
|
27
|
+
- JavaScript: `@kerfjs/ui/popup-menu` — exports `PopupMenu`, `openPopupMenuAt`, `closePopupMenu`.
|
|
27
28
|
- CSS: the browser build of `@kerfjs/ui/popup-menu` pulls its CSS automatically; import `@kerfjs/ui/popup-menu.css` manually only without the `browser` export condition.
|
|
28
29
|
- Theme CSS: import `@kerfjs/ui/webawesome.css` once.
|
|
29
30
|
- Registration: import `@kerfjs/ui/popup-menu/register` once (a side effect).
|
|
@@ -41,6 +42,10 @@ Exact prop names and types: [`@kerfjs/ui/popup-menu`](../public-api-signatures-v
|
|
|
41
42
|
- headings and dividers
|
|
42
43
|
- item icons
|
|
43
44
|
- disabled items
|
|
45
|
+
- nested actions
|
|
46
|
+
- checked choices and trailing details
|
|
47
|
+
- danger tone and disabled reasons
|
|
48
|
+
- context trigger
|
|
44
49
|
- placement
|
|
45
50
|
|
|
46
51
|
## Composition
|
|
@@ -52,7 +57,7 @@ Exact prop names and types: [`@kerfjs/ui/popup-menu`](../public-api-signatures-v
|
|
|
52
57
|
|
|
53
58
|
## State and wiring
|
|
54
59
|
|
|
55
|
-
**The app owns:** commands and their delegated actions; which items are enabled; reactions to the menu opening or closing.
|
|
60
|
+
**The app owns:** commands and their delegated actions; which items are enabled; reactions to the menu opening or closing; contextmenu event handling and identification of the menu root when using a pointer-anchored context menu.
|
|
56
61
|
|
|
57
62
|
No wiring helper.
|
|
58
63
|
|
|
@@ -62,21 +67,105 @@ Margin: none · border: child · padding: child (layout role: controls). `self`
|
|
|
62
67
|
|
|
63
68
|
## Accessibility
|
|
64
69
|
|
|
65
|
-
- An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. Web Awesome provides menu roles, arrow-key navigation, typeahead, and Escape.
|
|
70
|
+
- An icon-only trigger requires label, rendered as visually hidden slotted text because a Web Awesome button takes its accessible name from its content; a trigger with visible text is named by that text. The context anchor stays out of the accessibility tree. Web Awesome provides menu roles, nested arrow-key navigation, typeahead, and Escape.
|
|
66
71
|
- Once registered, an icon-only trigger shows its label as an aria-hidden Web Awesome help tag after a 500ms hover and at once on keyboard focus; it hides while the menu is open, on a press, and on Escape, and never joins aria-labelledby. Do not add a title or another tooltip.
|
|
67
72
|
|
|
73
|
+
## Usage examples
|
|
74
|
+
|
|
75
|
+
### Nested decisions
|
|
76
|
+
|
|
77
|
+
The app owns the current decision, batch disabled state, and delegated actions. Each child keeps its own record metadata.
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<PopupMenu
|
|
81
|
+
label="Line actions"
|
|
82
|
+
items={[
|
|
83
|
+
{
|
|
84
|
+
label: 'Decide',
|
|
85
|
+
submenu: [
|
|
86
|
+
{
|
|
87
|
+
label: 'Approve',
|
|
88
|
+
action: 'decide',
|
|
89
|
+
checked: current === 'approve',
|
|
90
|
+
attributes: { 'data-line-id': lineId, 'data-decision': 'approve' },
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
label: 'Reject',
|
|
94
|
+
action: 'decide',
|
|
95
|
+
tone: 'danger',
|
|
96
|
+
disabled: needsPrice,
|
|
97
|
+
disabledReason: needsPrice ? 'Add a price first' : undefined,
|
|
98
|
+
attributes: { 'data-line-id': lineId, 'data-decision': 'reject' },
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
{ kind: 'divider' },
|
|
103
|
+
{ label: 'Remove', action: 'remove', tone: 'danger' },
|
|
104
|
+
]}
|
|
105
|
+
/>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Flat selected choices
|
|
109
|
+
|
|
110
|
+
Headings separate sort dimensions; trailing safe content marks the active command without changing its accessible label.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
<PopupMenu
|
|
114
|
+
label="Sort chat"
|
|
115
|
+
items={[
|
|
116
|
+
{ kind: 'heading', label: 'Sort by' },
|
|
117
|
+
{
|
|
118
|
+
label: 'Updated',
|
|
119
|
+
action: 'sort-updated',
|
|
120
|
+
details: sort === 'updated' ? tick : undefined,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
label: 'Priority',
|
|
124
|
+
action: 'sort-priority',
|
|
125
|
+
details: sort === 'priority' ? tick : undefined,
|
|
126
|
+
},
|
|
127
|
+
{ kind: 'heading', label: 'Order' },
|
|
128
|
+
{
|
|
129
|
+
label: 'Newest first',
|
|
130
|
+
action: 'order-newest',
|
|
131
|
+
details: order === 'newest' ? tick : undefined,
|
|
132
|
+
},
|
|
133
|
+
]}
|
|
134
|
+
/>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Pointer anchored context menu
|
|
138
|
+
|
|
139
|
+
Keep the row's visible disabled action separate from the context menu anchor. Find the menu root with a stable data attribute.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<PopupMenu
|
|
143
|
+
context
|
|
144
|
+
label="Demand actions"
|
|
145
|
+
rootAttributes={{ 'data-demand-menu': '' }}
|
|
146
|
+
items={[{ label: 'Open', action: 'open-demand' }]}
|
|
147
|
+
/>;
|
|
148
|
+
// In the app's row wiring:
|
|
149
|
+
row.addEventListener('contextmenu', (event) => {
|
|
150
|
+
event.preventDefault();
|
|
151
|
+
const menu = row.querySelector('[data-demand-menu]') as PopupMenuElement;
|
|
152
|
+
openPopupMenuAt(menu, event.clientX, event.clientY);
|
|
153
|
+
});
|
|
154
|
+
// Call closePopupMenu(menu) when the app needs to dismiss it.
|
|
155
|
+
```
|
|
156
|
+
|
|
68
157
|
## Styling boundary
|
|
69
158
|
|
|
70
159
|
The component owns its own styles. Configure it through its props and variants; do not override its internals.
|
|
71
160
|
|
|
72
|
-
Public class hooks (select for layout placement only, never to change the component's look): `kui-popup-menu`, `kui-popup-menu__label`.
|
|
161
|
+
Public class hooks (select for layout placement only, never to change the component's look): `kui-popup-menu`, `kui-popup-menu__label`, `kui-popup-menu__details`, `kui-popup-menu__context-anchor`.
|
|
73
162
|
|
|
74
|
-
Never put `kui-popup-menu`, `kui-popup-menu__label` on an element you write; render `PopupMenu` instead (`KUI-L103`).
|
|
163
|
+
Never put `kui-popup-menu`, `kui-popup-menu__label`, `kui-popup-menu__details`, `kui-popup-menu__context-anchor` on an element you write; render `PopupMenu` instead (`KUI-L103`).
|
|
75
164
|
|
|
76
165
|
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`).
|
|
77
166
|
|
|
78
167
|
## Related
|
|
79
168
|
|
|
80
169
|
- Components: [Dropdown](./wa-dropdown.md), [Dropdown Item](./wa-dropdown-item.md), [Button](./wa-button.md), [Divider](./wa-divider.md), [Select](./select.md).
|
|
81
|
-
- Docs: [`docs/component-selection.md`](../../docs/component-selection.md), [`docs/component-selection.md#
|
|
170
|
+
- Docs: [`docs/component-selection.md`](../../docs/component-selection.md), [`docs/component-selection.md#popup-menu-migration`](../../docs/component-selection.md#popup-menu-migration).
|
|
82
171
|
- UX catalog route: `?component=popup-menu`.
|
package/ai/components/text.md
CHANGED
|
@@ -8,7 +8,7 @@ Semantic native paragraph text by default, with heading and inline-span variants
|
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
10
10
|
|
|
11
|
-
Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact size, or monospace font.
|
|
11
|
+
Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact through extra-large size, or monospace font.
|
|
12
12
|
|
|
13
13
|
- Render ordinary application headings or paragraphs with native document semantics, or inline secondary text inside rows, labels, and table cells.
|
|
14
14
|
|
|
@@ -36,7 +36,7 @@ Exact prop names and types: [`@kerfjs/ui/text`](../public-api-signatures-v1.md#k
|
|
|
36
36
|
|
|
37
37
|
- p, h1 through h6, or inline span semantic variant
|
|
38
38
|
- default, quiet, or danger tone
|
|
39
|
-
- default or
|
|
39
|
+
- compact, default, large, or xlarge size
|
|
40
40
|
- default or monospace font
|
|
41
41
|
|
|
42
42
|
## Composition
|
|
@@ -71,7 +71,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
71
71
|
|
|
72
72
|
Never put `kui-text` on an element you write; render `Text` instead (`KUI-L103`).
|
|
73
73
|
|
|
74
|
-
Public tokens it reads: `--kui-color-danger-on-quiet`, `--kui-color-text-quiet`, `--kui-font-mono`, `--kui-font-xs`, `--kui-layout-item-padding`. Set a token only where its public contract allows; prefer a prop.
|
|
74
|
+
Public tokens it reads: `--kui-color-danger-on-quiet`, `--kui-color-text-quiet`, `--kui-font-2xl`, `--kui-font-l`, `--kui-font-mono`, `--kui-font-xs`, `--kui-layout-item-padding`. Set a token only where its public contract allows; prefer a prop.
|
|
75
75
|
|
|
76
76
|
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`).
|
|
77
77
|
|
|
@@ -21,7 +21,9 @@ Token-controlled, optionally collapsible search editor with ordered, editable, r
|
|
|
21
21
|
|
|
22
22
|
## Imports
|
|
23
23
|
|
|
24
|
-
- JavaScript: `@kerfjs/ui/token-search-field` — exports `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret
|
|
24
|
+
- JavaScript: `@kerfjs/ui/token-search-field` — exports `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`.
|
|
25
|
+
- JavaScript: `@kerfjs/ui/wire-token-search-fields` — exports `wireTokenSearchFields`.
|
|
26
|
+
- JavaScript: `@kerfjs/ui/token-search-model` — exports `createTokenSearchModel`.
|
|
25
27
|
- CSS: the browser build of `@kerfjs/ui/token-search-field` pulls its CSS automatically; import `@kerfjs/ui/token-search-field.css` manually only without the `browser` export condition.
|
|
26
28
|
- Wiring: `readTokenSearchField` from `@kerfjs/ui/token-search-field` (required).
|
|
27
29
|
- Wiring: `placeTokenSearchCaret` from `@kerfjs/ui/token-search-field` (optional).
|
|
@@ -30,7 +32,7 @@ Token-controlled, optionally collapsible search editor with ordered, editable, r
|
|
|
30
32
|
|
|
31
33
|
## Props
|
|
32
34
|
|
|
33
|
-
Exact prop names and types: [`@kerfjs/ui/token-search-field`](../public-api-signatures-v1.md#kerfjsuitoken-search-field), [`@kerfjs/ui/wire-token-search-fields`](../public-api-signatures-v1.md#kerfjsuiwire-token-search-fields) in `public-api-signatures-v1.md`. Do not infer props from examples.
|
|
35
|
+
Exact prop names and types: [`@kerfjs/ui/token-search-field`](../public-api-signatures-v1.md#kerfjsuitoken-search-field), [`@kerfjs/ui/wire-token-search-fields`](../public-api-signatures-v1.md#kerfjsuiwire-token-search-fields), [`@kerfjs/ui/token-search-model`](../public-api-signatures-v1.md#kerfjsuitoken-search-model) in `public-api-signatures-v1.md`. Do not infer props from examples.
|
|
34
36
|
|
|
35
37
|
**Variants (configure, do not restyle):**
|
|
36
38
|
|
|
@@ -82,9 +84,9 @@ Margin: none · border: self · padding: self (layout role: controls). `self` me
|
|
|
82
84
|
|
|
83
85
|
The component owns its own styles. Configure it through its props and variants; do not override its internals.
|
|
84
86
|
|
|
85
|
-
Public class hooks (select for layout placement only, never to change the component's look): `kui-token-search`, `kui-token-search__clear`, `kui-token-search__editor`, `kui-token-search__expand`, `kui-token-search__leading`, `kui-token-search__token`, `kui-token-search__token-edit`, `kui-token-search__token-remove`, `kui-token-search__trailing`.
|
|
87
|
+
Public class hooks (select for layout placement only, never to change the component's look): `kui-token-search`, `kui-token-search__clear`, `kui-token-search__editor`, `kui-token-search__expand`, `kui-token-search__leading`, `kui-token-search__token`, `kui-token-search__token-edit`, `kui-token-search__token-remove`, `kui-token-search__suggestions`, `kui-token-search__suggestion`, `kui-token-search__trailing`.
|
|
86
88
|
|
|
87
|
-
Never put `kui-token-search`, `kui-token-search__clear`, `kui-token-search__editor`, `kui-token-search__expand`, `kui-token-search__leading`, `kui-token-search__token`, `kui-token-search__token-edit`, `kui-token-search__token-remove`, `kui-token-search__trailing` on an element you write; render `TokenSearchField` instead (`KUI-L103`).
|
|
89
|
+
Never put `kui-token-search`, `kui-token-search__clear`, `kui-token-search__editor`, `kui-token-search__expand`, `kui-token-search__leading`, `kui-token-search__token`, `kui-token-search__token-edit`, `kui-token-search__token-remove`, `kui-token-search__suggestions`, `kui-token-search__suggestion`, `kui-token-search__trailing` on an element you write; render `TokenSearchField` instead (`KUI-L103`).
|
|
88
90
|
|
|
89
91
|
Public tokens it reads: `--kui-color-brand-fill-normal`, `--kui-color-brand-on-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-text-link`, `--kui-color-surface`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-focus-ring`, `--kui-font-s`, `--kui-font-xs`, `--kui-radius-pill`, `--kui-token-search-background`, `--kui-token-search-border`, `--kui-token-search-line-size`, `--kui-token-search-token-background`, `--kui-token-search-token-foreground`, `--kui-token-search-expanded-width`. Set a token only where its public contract allows; prefer a prop.
|
|
90
92
|
|