@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.
- package/README.md +1 -0
- package/ai/component-catalog.json +141 -24
- package/ai/component-composition-rules.json +8 -0
- package/ai/component-composition.d.ts +10 -0
- package/ai/component-composition.json +117 -8
- package/ai/component-composition.schema.json +21 -0
- package/ai/components/README.md +5 -4
- package/ai/components/chip.md +72 -0
- package/ai/components/grid.md +10 -7
- package/ai/components/list-item.md +10 -7
- package/ai/components/pane.md +3 -2
- package/ai/components/select.md +6 -2
- package/ai/components/tabs.md +8 -4
- package/ai/components/toolbar-text.md +2 -1
- package/ai/components/toolbar.md +3 -2
- package/ai/public-api-signatures-v1.md +116 -24
- package/ai/skill.md +24 -4
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/app-tab.d.ts +12 -2
- package/dist/app-tab.js +1 -1
- package/dist/browser/chip.js +3 -0
- package/dist/catalog.js +8 -8
- package/dist/chip.d.ts +29 -0
- package/dist/chip.js +3 -0
- package/dist/chip.js.map +1 -0
- package/dist/{chunk-WPLIO5WJ.js → chunk-4MG3KXJM.js} +40 -5
- package/dist/chunk-4MG3KXJM.js.map +1 -0
- package/dist/{chunk-F7F7KRO2.js → chunk-4SQK27MR.js} +33 -18
- package/dist/chunk-4SQK27MR.js.map +1 -0
- package/dist/chunk-EAC4CDY7.js +57 -0
- package/dist/chunk-EAC4CDY7.js.map +1 -0
- package/dist/{chunk-T57AXDFM.js → chunk-ENGVYQPG.js} +4 -3
- package/dist/chunk-ENGVYQPG.js.map +1 -0
- package/dist/{chunk-5PESG2VP.js → chunk-KYDDCJXU.js} +4 -3
- package/dist/chunk-KYDDCJXU.js.map +1 -0
- package/dist/{chunk-MERWRTBG.js → chunk-N2DRU35S.js} +1 -1
- package/dist/chunk-N2DRU35S.js.map +1 -0
- package/dist/{chunk-EZVNC4J6.js → chunk-OD2VXAPL.js} +4 -1
- package/dist/chunk-OD2VXAPL.js.map +1 -0
- package/dist/{chunk-T66UNBXL.js → chunk-Q6YU3BT7.js} +11 -2
- package/dist/chunk-Q6YU3BT7.js.map +1 -0
- package/dist/{chunk-N3GKMPDW.js → chunk-RKTTF3L4.js} +3 -1
- package/dist/chunk-RKTTF3L4.js.map +1 -0
- package/dist/chunk-SWVW56CV.js +188 -0
- package/dist/chunk-SWVW56CV.js.map +1 -0
- package/dist/{chunk-46263QLK.js → chunk-UA6JW52D.js} +53 -7
- package/dist/chunk-UA6JW52D.js.map +1 -0
- package/dist/{chunk-AGXQQFKZ.js → chunk-UCKKT6KO.js} +13 -4
- package/dist/chunk-UCKKT6KO.js.map +1 -0
- package/dist/{chunk-3SXMEK3B.js → chunk-V3DX3K65.js} +1 -1
- package/dist/chunk-V3DX3K65.js.map +1 -0
- package/dist/{chunk-UWONG4QE.js → chunk-VCBTX62E.js} +11 -3
- package/dist/chunk-VCBTX62E.js.map +1 -0
- package/dist/{chunk-2OXQHM7I.js → chunk-X6ADHJNI.js} +45 -20
- package/dist/chunk-X6ADHJNI.js.map +1 -0
- package/dist/collapsible-panel.js +2 -2
- package/dist/grid.d.ts +13 -5
- package/dist/grid.js +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +17 -16
- package/dist/list-item.d.ts +11 -1
- package/dist/list-item.js +1 -1
- package/dist/nav-stack.d.ts +3 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +8 -3
- package/dist/pane.js +1 -1
- package/dist/popup-menu.d.ts +2 -2
- package/dist/popup-menu.js +1 -1
- package/dist/select-register.js +46 -0
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +16 -0
- package/dist/select.js +1 -1
- package/dist/split-view.d.ts +1 -1
- package/dist/split-view.js +1 -1
- package/dist/styles/app-tab.css +119 -0
- package/dist/styles/chip.css +118 -0
- package/dist/styles/grid.css +7 -0
- package/dist/styles/list-item.css +14 -9
- package/dist/styles/nav-stack.css +13 -0
- package/dist/styles/pane.css +33 -0
- package/dist/styles/popup-menu.css +2 -1
- package/dist/styles/resizable-region.css +9 -0
- package/dist/styles/segmented-control.css +2 -1
- package/dist/styles/select.css +45 -0
- package/dist/styles/split-view.css +6 -0
- package/dist/styles/styles.css +1 -0
- package/dist/styles/tab-bar.css +3 -0
- package/dist/styles/tab-scaffold.css +13 -0
- package/dist/styles/toolbar-text.css +15 -6
- package/dist/styles/toolbar.css +15 -5
- package/dist/styles/workbench.css +117 -93
- package/dist/tab-bar.d.ts +6 -2
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +3 -0
- package/dist/tab-scaffold.js +1 -0
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/{token-search-field-CCke1yvQ.d.ts → token-search-field-DvgFLhLL.d.ts} +6 -2
- package/dist/token-search-field.d.ts +1 -1
- package/dist/token-search-model.d.ts +1 -1
- package/dist/token-search-model.js +1 -1
- package/dist/toolbar-text.d.ts +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +2 -2
- package/dist/toolbar.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/workbench.js +1 -1
- package/docs/accessibility.md +29 -3
- package/docs/collapsible-panel.md +4 -3
- package/docs/component-contract.md +5 -0
- package/docs/component-selection.md +92 -11
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
- package/docs/design/templates/segmented-control/equal.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small.svg +1 -1
- package/docs/design/templates/segmented-control-dark.svg +1 -1
- package/docs/design/templates/segmented-control.svg +1 -1
- package/docs/layout.md +51 -9
- package/docs/nav-stack.md +5 -0
- package/docs/split-view.md +5 -0
- package/docs/sunken-panel.md +12 -0
- package/docs/tab-scaffold.md +5 -0
- package/docs/webawesome-theme.md +62 -0
- package/docs/workbench.md +22 -10
- package/llms.txt +40 -8
- package/package.json +7 -1
- package/dist/chunk-2OXQHM7I.js.map +0 -1
- package/dist/chunk-3SXMEK3B.js.map +0 -1
- package/dist/chunk-46263QLK.js.map +0 -1
- package/dist/chunk-5I7OHCIP.js +0 -96
- package/dist/chunk-5I7OHCIP.js.map +0 -1
- package/dist/chunk-5PESG2VP.js.map +0 -1
- package/dist/chunk-AGXQQFKZ.js.map +0 -1
- package/dist/chunk-EZVNC4J6.js.map +0 -1
- package/dist/chunk-F7F7KRO2.js.map +0 -1
- package/dist/chunk-MERWRTBG.js.map +0 -1
- package/dist/chunk-N3GKMPDW.js.map +0 -1
- package/dist/chunk-T57AXDFM.js.map +0 -1
- package/dist/chunk-T66UNBXL.js.map +0 -1
- package/dist/chunk-UWONG4QE.js.map +0 -1
- package/dist/chunk-WPLIO5WJ.js.map +0 -1
package/ai/components/tabs.md
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
`@kerfjs/ui:tabs` · Kerf UI · component · Navigation
|
|
6
6
|
|
|
7
|
+
Roving-tabindex-ready tabs with typed compact, segmented, icon-only, drop-target, pinned, and name-overflow presentations.
|
|
8
|
+
|
|
7
9
|
## When to use
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
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.
|
|
10
12
|
|
|
11
13
|
- Render one controlled application tab inside TabBar.
|
|
12
14
|
|
|
@@ -40,7 +42,9 @@ Exact prop names and types: [`@kerfjs/ui/app-tab`](../public-api-signatures-v1.m
|
|
|
40
42
|
- compact size
|
|
41
43
|
- segmented presentation
|
|
42
44
|
- icon-only accessible presentation
|
|
43
|
-
- label maximum width and
|
|
45
|
+
- label maximum width and ellipsis or visible name overflow
|
|
46
|
+
- drop-target highlight
|
|
47
|
+
- pinned leading position within a scrolling tablist
|
|
44
48
|
- attention name color
|
|
45
49
|
|
|
46
50
|
## Composition
|
|
@@ -58,7 +62,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
|
|
|
58
62
|
|
|
59
63
|
## State and wiring
|
|
60
64
|
|
|
61
|
-
**The app owns:** tab identity; selection; close policy; content; application data attribute values; outer placement.
|
|
65
|
+
**The app owns:** tab identity; selection; drop-target state; close policy; content; application data attribute values; outer placement.
|
|
62
66
|
|
|
63
67
|
No wiring helper.
|
|
64
68
|
|
|
@@ -80,7 +84,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
80
84
|
|
|
81
85
|
Never put `kui-app-tab`, `kui-app-tab__close`, `kui-app-tab__close-icon`, `kui-app-tab__name`, `kui-app-tab__select`, `kui-app-tab__trailing` on an element you write; render `AppTab` instead (`KUI-L103`).
|
|
82
86
|
|
|
83
|
-
Public tokens it reads: `--kui-app-tab-attention-color`, `--kui-app-tab-color`, `--kui-app-tab-drop-indicator`, `--kui-app-tab-hover-background`, `--kui-app-tab-selected-background`, `--kui-app-tab-selected-border`, `--kui-app-tab-selected-color`, `--kui-color-brand-border-normal`, `--kui-color-brand-on-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-surface`, `--kui-color-text`, `--kui-focus-ring`, `--kui-font-xs`, `--kui-radius-pill`, `--kui-shadow-s`, `--kui-space-2xs`, `--kui-space-xs`. Set a token only where its public contract allows; prefer a prop.
|
|
87
|
+
Public tokens it reads: `--kui-app-tab-attention-color`, `--kui-app-tab-color`, `--kui-app-tab-drop-indicator`, `--kui-app-tab-drop-target-background`, `--kui-app-tab-drop-target-color`, `--kui-app-tab-drop-target-ring`, `--kui-app-tab-hover-background`, `--kui-app-tab-pinned-background`, `--kui-app-tab-pinned-hover-background`, `--kui-app-tab-selected-background`, `--kui-app-tab-selected-border`, `--kui-app-tab-selected-color`, `--kui-color-brand-border-normal`, `--kui-color-brand-on-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-on-quiet`, `--kui-color-surface`, `--kui-color-text`, `--kui-focus-ring`, `--kui-font-xs`, `--kui-radius-pill`, `--kui-shadow-s`, `--kui-space-2xs`, `--kui-space-xs`. Set a token only where its public contract allows; prefer a prop.
|
|
84
88
|
|
|
85
89
|
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
90
|
|
|
@@ -13,7 +13,7 @@ Extra-large through extra-small toolbar identity text.
|
|
|
13
13
|
**Not when:**
|
|
14
14
|
|
|
15
15
|
- Do not omit headingLevel when the text is the page or section heading.
|
|
16
|
-
-
|
|
16
|
+
- Large, default, and small are intentionally quiet toolbar identity text and have no tone option. Use xlarge-fixed for a normal-color toolbar heading at the fixed font-l step; use Text with an h2-h6 variant for a content subsection title, or ListHeader for a list or menu section.
|
|
17
17
|
|
|
18
18
|
**Alternatives:**
|
|
19
19
|
|
|
@@ -33,6 +33,7 @@ Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures
|
|
|
33
33
|
**Variants (configure, do not restyle):**
|
|
34
34
|
|
|
35
35
|
- xlarge
|
|
36
|
+
- xlarge-fixed (fixed font-l heading)
|
|
36
37
|
- large
|
|
37
38
|
- default
|
|
38
39
|
- small
|
package/ai/components/toolbar.md
CHANGED
|
@@ -36,6 +36,7 @@ Exact prop names and types: [`@kerfjs/ui/toolbar`](../public-api-signatures-v1.m
|
|
|
36
36
|
- center priority for an expanded center control
|
|
37
37
|
- trailing priority for an expanded trailing control at compact or narrow widths
|
|
38
38
|
- trailing groups wrap instead of clipping
|
|
39
|
+
- outer inset independently configurable from zone gap
|
|
39
40
|
- app bar or bottom bar claiming its screen edges (safeAreaEdges)
|
|
40
41
|
|
|
41
42
|
## Composition
|
|
@@ -66,7 +67,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
|
|
|
66
67
|
|
|
67
68
|
Margin: none · border: conditional · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
|
|
68
69
|
|
|
69
|
-
- Padding belongs to the toolbar; dividerSides selects any canonical combination of its physical top, right, bottom, and left edges.
|
|
70
|
+
- 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.
|
|
70
71
|
- 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.
|
|
71
72
|
|
|
72
73
|
## Accessibility
|
|
@@ -81,7 +82,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
81
82
|
|
|
82
83
|
Never put `kui-toolbar`, `kui-toolbar__center`, `kui-toolbar__leading`, `kui-toolbar__trailing` on an element you write; render `Toolbar` instead (`KUI-L103`).
|
|
83
84
|
|
|
84
|
-
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-font-sans`, `--kui-toolbar-center-padding-inline`, `--kui-toolbar-divider-color`, `--kui-toolbar-leading-min-width`, `--kui-toolbar-leading-padding-inline`, `--kui-toolbar-trailing-gap`, `--kui-toolbar-trailing-justify`, `--kui-toolbar-trailing-justify-self`, `--kui-toolbar-trailing-padding-inline`, `--kui-toolbar-zone-padding-inline`. Set a token only where its public contract allows; prefer a prop.
|
|
85
|
+
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-font-sans`, `--kui-toolbar-center-padding-inline`, `--kui-toolbar-divider-color`, `--kui-toolbar-inset`, `--kui-toolbar-leading-min-width`, `--kui-toolbar-leading-padding-inline`, `--kui-toolbar-trailing-gap`, `--kui-toolbar-trailing-justify`, `--kui-toolbar-trailing-justify-self`, `--kui-toolbar-trailing-padding-inline`, `--kui-toolbar-zone-padding-inline`. Set a token only where its public contract allows; prefer a prop.
|
|
85
86
|
|
|
86
87
|
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`).
|
|
87
88
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public API signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.62` and `kerfjs@5.0.0-beta.62`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
|
|
4
4
|
|
|
5
5
|
## `@kerfjs/ui/css-values`
|
|
6
6
|
|
|
@@ -160,8 +160,8 @@ interface ToolbarProps {
|
|
|
160
160
|
* then draws its facing side the same way.
|
|
161
161
|
*/
|
|
162
162
|
dividerSides?: Sides;
|
|
163
|
-
/**
|
|
164
|
-
centerAlign?: 'center' | 'stretch';
|
|
163
|
+
/** `balanced` gives both side zones equal tracks, centering the middle zone on the toolbar even if only one side has controls. */
|
|
164
|
+
centerAlign?: 'center' | 'stretch' | 'balanced';
|
|
165
165
|
/**
|
|
166
166
|
* Component-owned responsive layout; applications choose the policy rather
|
|
167
167
|
* than restyling toolbar internals. Under every policy the trailing zone
|
|
@@ -210,7 +210,7 @@ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
|
|
|
210
210
|
```ts
|
|
211
211
|
import * as kerfjs from 'kerfjs';
|
|
212
212
|
|
|
213
|
-
type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small' | 'xsmall';
|
|
213
|
+
type ToolbarTextSize = 'xlarge' | 'xlarge-fixed' | 'large' | 'default' | 'small' | 'xsmall';
|
|
214
214
|
/** ARIA heading level for a title exposed as a heading landmark. */
|
|
215
215
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
216
216
|
interface ToolbarTextBaseProps {
|
|
@@ -424,8 +424,8 @@ interface PopupMenuItem {
|
|
|
424
424
|
disabledReason?: string;
|
|
425
425
|
/** Application `data-*` metadata such as a record id. */
|
|
426
426
|
attributes?: PopupMenuDataAttributes;
|
|
427
|
-
/** Child commands opened by hover or keyboard navigation. */
|
|
428
|
-
submenu?: readonly
|
|
427
|
+
/** Child commands, headings, and dividers opened by hover or keyboard navigation. */
|
|
428
|
+
submenu?: readonly PopupMenuEntry[];
|
|
429
429
|
}
|
|
430
430
|
/** A labeled group heading; items that follow it belong to the group. */
|
|
431
431
|
interface PopupMenuHeading {
|
|
@@ -783,9 +783,19 @@ interface ListItemProps {
|
|
|
783
783
|
/** Native named-slot assignment when composed inside a web component. */
|
|
784
784
|
slot?: string;
|
|
785
785
|
}
|
|
786
|
+
interface ListItemLinkProps extends Omit<ListItemProps, 'action' | 'pressed'> {
|
|
787
|
+
/** Native destination for this navigation row. */
|
|
788
|
+
href: string;
|
|
789
|
+
/** Open in a new tab with a safe rel and announce that behavior. */
|
|
790
|
+
external?: boolean;
|
|
791
|
+
action?: never;
|
|
792
|
+
pressed?: never;
|
|
793
|
+
}
|
|
786
794
|
declare function ListItem({ label, description, icon, trailing, status, busy, density, divider, selected, action, itemId, className, pressed, accessibleLabel, title, multiline, multilineIconAlign, state, disabled, tabIndex, placeholder, rootAttributes, slot, }: ListItemProps): SafeHtml;
|
|
795
|
+
/** A navigation row with native link activation and ListItem geometry. */
|
|
796
|
+
declare function ListItemLink({ href, external, label, description, icon, trailing, status, busy, density, divider, selected, itemId, className, accessibleLabel, title, multiline, multilineIconAlign, state, disabled, tabIndex, placeholder, rootAttributes, slot, }: ListItemLinkProps): SafeHtml;
|
|
787
797
|
|
|
788
|
-
export { ListItem, type ListItemProps };
|
|
798
|
+
export { ListItem, ListItemLink, type ListItemLinkProps, type ListItemProps };
|
|
789
799
|
```
|
|
790
800
|
|
|
791
801
|
## `@kerfjs/ui/list-inset-control`
|
|
@@ -948,15 +958,23 @@ type AppTabRootAttributes = Readonly<Record<`data-${string}`, string | undefined
|
|
|
948
958
|
'data-tab-dragging'?: never;
|
|
949
959
|
'data-tab-drop-position'?: never;
|
|
950
960
|
'data-attention'?: never;
|
|
961
|
+
'data-drop-target'?: never;
|
|
962
|
+
'data-name-overflow'?: never;
|
|
963
|
+
'data-pinned'?: never;
|
|
951
964
|
}>;
|
|
952
965
|
type AppTabPresentation = 'pill' | 'segmented' | 'icon-only';
|
|
953
966
|
type AppTabSize = 'default' | 'compact';
|
|
967
|
+
type AppTabNameOverflow = 'ellipsis' | 'visible';
|
|
954
968
|
interface AppTabProps {
|
|
955
969
|
id: string;
|
|
956
970
|
name: string;
|
|
957
971
|
selected?: boolean;
|
|
958
972
|
/** Emphasize the visible tab name with the attention color token. */
|
|
959
973
|
attention?: boolean;
|
|
974
|
+
/** Highlight this tab as the target of a drag over its content. */
|
|
975
|
+
dropTarget?: boolean;
|
|
976
|
+
/** Keep the leading tab visible within its TabBar tablist while peers scroll. */
|
|
977
|
+
pinned?: boolean;
|
|
960
978
|
closable?: boolean;
|
|
961
979
|
draggable?: boolean;
|
|
962
980
|
leading?: KerfUiContent;
|
|
@@ -967,6 +985,8 @@ interface AppTabProps {
|
|
|
967
985
|
size?: AppTabSize;
|
|
968
986
|
/** Maximum visible label width in CSS pixels before ellipsis. */
|
|
969
987
|
labelMaxWidth?: number;
|
|
988
|
+
/** Keep the full name visible for an inline loading treatment. */
|
|
989
|
+
nameOverflow?: AppTabNameOverflow;
|
|
970
990
|
/** Decorative dormant content for the close button. Must not contain interactive descendants. */
|
|
971
991
|
closeIcon?: SafeHtml;
|
|
972
992
|
selectAction?: string;
|
|
@@ -989,9 +1009,9 @@ interface AppTabProps {
|
|
|
989
1009
|
/** Native named-slot assignment when composed inside a web component. */
|
|
990
1010
|
slot?: string;
|
|
991
1011
|
}
|
|
992
|
-
declare function AppTab({ id, name, selected, attention, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
1012
|
+
declare function AppTab({ id, name, selected, attention, dropTarget, pinned, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, nameOverflow, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
993
1013
|
|
|
994
|
-
export { AppTab, type AppTabPresentation, type AppTabProps, type AppTabSize };
|
|
1014
|
+
export { AppTab, type AppTabNameOverflow, type AppTabPresentation, type AppTabProps, type AppTabSize };
|
|
995
1015
|
```
|
|
996
1016
|
|
|
997
1017
|
## `@kerfjs/ui/tab-bar`
|
|
@@ -1004,6 +1024,8 @@ type TabActivation = 'automatic' | 'manual';
|
|
|
1004
1024
|
type TabBarAllocation = 'intrinsic' | 'fill';
|
|
1005
1025
|
type TabBarPresentation = 'rail' | 'segmented' | 'inspector';
|
|
1006
1026
|
type TabBarTrailingPlacement = 'separate' | 'adjacent';
|
|
1027
|
+
/** Tablist width where segmented AppTabs switch to icon-only. */
|
|
1028
|
+
type TabBarIconOnlyAt = 'wide' | 'narrow' | 'compact';
|
|
1007
1029
|
interface TabBarProps {
|
|
1008
1030
|
id: string;
|
|
1009
1031
|
label: string;
|
|
@@ -1027,15 +1049,17 @@ interface TabBarProps {
|
|
|
1027
1049
|
allocation?: TabBarAllocation;
|
|
1028
1050
|
/** Named strip chrome for application rails, segmented tabs, or inspectors. */
|
|
1029
1051
|
presentation?: TabBarPresentation;
|
|
1052
|
+
/** Switch segmented AppTabs to icon-only at tablist widths of 832, 704, or 448px. Each tab needs a leading icon. */
|
|
1053
|
+
iconOnlyAt?: TabBarIconOnlyAt;
|
|
1030
1054
|
/** Keep a trailing action beside the final tab or at the far edge of the bar. */
|
|
1031
1055
|
trailingPlacement?: TabBarTrailingPlacement;
|
|
1032
1056
|
/** Native named-slot assignment when composed inside a web component. */
|
|
1033
1057
|
slot?: string;
|
|
1034
1058
|
}
|
|
1035
1059
|
/** Render a controlled tab strip. The application owns selection, order, and persistence. */
|
|
1036
|
-
declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
|
|
1060
|
+
declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, iconOnlyAt, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
|
|
1037
1061
|
|
|
1038
|
-
export { type TabActivation, TabBar, type TabBarAllocation, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
|
|
1062
|
+
export { type TabActivation, TabBar, type TabBarAllocation, type TabBarIconOnlyAt, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
|
|
1039
1063
|
```
|
|
1040
1064
|
|
|
1041
1065
|
## `@kerfjs/ui/wire-tab-bars`
|
|
@@ -1155,10 +1179,10 @@ export { type ScrollDividerTarget, type WireScrollDividersOptions, wireScrollDiv
|
|
|
1155
1179
|
|
|
1156
1180
|
```ts
|
|
1157
1181
|
import * as kerfjs from 'kerfjs';
|
|
1182
|
+
import { PaneAppearance } from './pane.js';
|
|
1158
1183
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
1159
1184
|
import { ToolbarConfig } from './toolbar.js';
|
|
1160
1185
|
import { ToolbarTextSize, HeadingLevel } from './toolbar-text.js';
|
|
1161
|
-
import './pane.js';
|
|
1162
1186
|
import './sides-BPSWde0A.js';
|
|
1163
1187
|
|
|
1164
1188
|
/**
|
|
@@ -1169,6 +1193,8 @@ interface NavStackView {
|
|
|
1169
1193
|
/** Stable identity for keyed reconcile and transition direction. */
|
|
1170
1194
|
key: string;
|
|
1171
1195
|
content: KerfUiContent;
|
|
1196
|
+
/** Background of this view's scrolling work surface. */
|
|
1197
|
+
appearance?: PaneAppearance;
|
|
1172
1198
|
/** Title shown in the top toolbar for this view. */
|
|
1173
1199
|
title?: string;
|
|
1174
1200
|
/** Leading groups for this view's top toolbar, after the back control and before the title. */
|
|
@@ -1274,8 +1300,8 @@ import * as kerfjs from 'kerfjs';
|
|
|
1274
1300
|
import { NavStackProps, NavStackView } from './nav-stack.js';
|
|
1275
1301
|
import { ResizableRegionProps } from './resizable-region.js';
|
|
1276
1302
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
1277
|
-
import './toolbar.js';
|
|
1278
1303
|
import './pane.js';
|
|
1304
|
+
import './toolbar.js';
|
|
1279
1305
|
import './sides-BPSWde0A.js';
|
|
1280
1306
|
import './toolbar-text.js';
|
|
1281
1307
|
import './css-values.js';
|
|
@@ -1373,6 +1399,7 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
|
|
|
1373
1399
|
'data-safe-area-inline-end'?: never;
|
|
1374
1400
|
'data-chrome-placement'?: never;
|
|
1375
1401
|
'data-chrome-dividers'?: never;
|
|
1402
|
+
'data-appearance'?: never;
|
|
1376
1403
|
}>;
|
|
1377
1404
|
/** How a Pane's header and footer relate to its scrolling content. */
|
|
1378
1405
|
type PaneChromePlacement = 'fixed' | 'auto';
|
|
@@ -1382,6 +1409,8 @@ type PaneChromePlacement = 'fixed' | 'auto';
|
|
|
1382
1409
|
* chrome, as `wireScrollDividers` reports; `always`; or `none`.
|
|
1383
1410
|
*/
|
|
1384
1411
|
type PaneChromeDividers = 'scroll' | 'always' | 'none';
|
|
1412
|
+
/** Background treatment of the Pane's scrolling work surface. */
|
|
1413
|
+
type PaneAppearance = 'default' | 'sunken';
|
|
1385
1414
|
interface PaneProps {
|
|
1386
1415
|
/** Optional fixed chrome above the scrolling content, arranged vertically. */
|
|
1387
1416
|
header?: KerfUiContent;
|
|
@@ -1407,6 +1436,8 @@ interface PaneProps {
|
|
|
1407
1436
|
* The line is drawn inside the chrome, so no state moves the content.
|
|
1408
1437
|
*/
|
|
1409
1438
|
chromeDividers?: PaneChromeDividers;
|
|
1439
|
+
/** Paint the scrolling work surface with the shared lowered-surface color. */
|
|
1440
|
+
appearance?: PaneAppearance;
|
|
1410
1441
|
/** Root semantics. Defaults to `div`. */
|
|
1411
1442
|
element?: PaneElement;
|
|
1412
1443
|
/** Scrolling content semantics. Defaults to `div`. */
|
|
@@ -1441,16 +1472,16 @@ interface PaneProps {
|
|
|
1441
1472
|
* or a CollapsiblePanel) forwards, so the app configures that pane instead of
|
|
1442
1473
|
* styling it. An omitted or `undefined` field keeps the composite's default.
|
|
1443
1474
|
*/
|
|
1444
|
-
type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
|
|
1475
|
+
type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers' | 'appearance'>;
|
|
1445
1476
|
/**
|
|
1446
1477
|
* An unpadded application column with optional fixed header/footer slots and one
|
|
1447
1478
|
* scrolling vertical content owner. Separator lines are independently opt-in on
|
|
1448
1479
|
* each logical edge, so the same component works as a sidebar, main area,
|
|
1449
1480
|
* inspector, or dialog column.
|
|
1450
1481
|
*/
|
|
1451
|
-
declare function Pane({ header, children, footer, chromePlacement, chromeDividers, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
|
|
1482
|
+
declare function Pane({ header, children, footer, chromePlacement, chromeDividers, appearance, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
|
|
1452
1483
|
|
|
1453
|
-
export { Pane, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
|
|
1484
|
+
export { Pane, type PaneAppearance, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
|
|
1454
1485
|
```
|
|
1455
1486
|
|
|
1456
1487
|
## `@kerfjs/ui/workbench`
|
|
@@ -2015,6 +2046,7 @@ export { type SidebarStorage, type WireSidebarOptions, type WireSidebarPanel, wi
|
|
|
2015
2046
|
|
|
2016
2047
|
```ts
|
|
2017
2048
|
import { SafeHtml } from 'kerfjs';
|
|
2049
|
+
import { PaneAppearance } from './pane.js';
|
|
2018
2050
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
2019
2051
|
|
|
2020
2052
|
interface TabScaffoldTabBase<Id extends string> {
|
|
@@ -2024,6 +2056,8 @@ interface TabScaffoldTabBase<Id extends string> {
|
|
|
2024
2056
|
icon?: SafeHtml;
|
|
2025
2057
|
/** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
|
|
2026
2058
|
content: KerfUiContent;
|
|
2059
|
+
/** Background of this scene's scrolling work surface. */
|
|
2060
|
+
appearance?: PaneAppearance;
|
|
2027
2061
|
}
|
|
2028
2062
|
/** A tab with an optional count or short-status badge. */
|
|
2029
2063
|
interface TabScaffoldTabCountBadge {
|
|
@@ -2548,6 +2582,10 @@ interface SelectChoice<Value extends string = string> {
|
|
|
2548
2582
|
*/
|
|
2549
2583
|
color?: CssForegroundColor;
|
|
2550
2584
|
group?: string;
|
|
2585
|
+
/** Keep an unavailable choice visible but prevent selection. */
|
|
2586
|
+
disabled?: boolean;
|
|
2587
|
+
/** Optional explanation exposed as the disabled option's native tooltip. */
|
|
2588
|
+
disabledReason?: string;
|
|
2551
2589
|
/**
|
|
2552
2590
|
* Draw a divider between this choice and the previous choice in the same
|
|
2553
2591
|
* list. A group boundary is already a separator, so the first choice of a
|
|
@@ -2584,6 +2622,8 @@ interface SelectBaseProps<Value extends string = string> {
|
|
|
2584
2622
|
size?: SelectSize;
|
|
2585
2623
|
/** Closed trigger width; omit to keep the presentation's default. */
|
|
2586
2624
|
triggerWidth?: SelectTriggerWidth;
|
|
2625
|
+
/** Show the disclosure caret (default); omit it for a compact icon-only trigger. */
|
|
2626
|
+
caret?: boolean;
|
|
2587
2627
|
/** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
|
|
2588
2628
|
focusRingOwner?: SelectFocusRingOwner;
|
|
2589
2629
|
/** Maximum closed-control label width in CSS pixels before ellipsis. */
|
|
@@ -2599,6 +2639,8 @@ interface SelectSingleValueProps<Value extends string = string> {
|
|
|
2599
2639
|
/** Show only the selected choice icon while retaining the Select's accessible name. */
|
|
2600
2640
|
selectedPresentation?: SelectSelectedPresentation;
|
|
2601
2641
|
triggerIcon?: never;
|
|
2642
|
+
selectAllLabel?: never;
|
|
2643
|
+
clearLabel?: never;
|
|
2602
2644
|
}
|
|
2603
2645
|
/**
|
|
2604
2646
|
* Any number of chosen values. The popup stays open while the person toggles
|
|
@@ -2611,6 +2653,10 @@ interface SelectMultipleLabelProps<Value extends string = string> {
|
|
|
2611
2653
|
renderSelected?: never;
|
|
2612
2654
|
selectedPresentation?: 'label';
|
|
2613
2655
|
triggerIcon?: never;
|
|
2656
|
+
/** Opt in to a footer action that selects every enabled choice. */
|
|
2657
|
+
selectAllLabel?: string;
|
|
2658
|
+
/** Opt in to a footer action that clears the current selection. */
|
|
2659
|
+
clearLabel?: string;
|
|
2614
2660
|
}
|
|
2615
2661
|
/**
|
|
2616
2662
|
* A multiple Select drawn as an icon-only toolbar trigger, such as a
|
|
@@ -2629,6 +2675,10 @@ interface SelectMultipleIconProps<Value extends string = string> {
|
|
|
2629
2675
|
* purpose (a funnel for a filter), independent of the selection.
|
|
2630
2676
|
*/
|
|
2631
2677
|
triggerIcon: KerfUiContent;
|
|
2678
|
+
/** Opt in to a footer action that selects every enabled choice. */
|
|
2679
|
+
selectAllLabel?: string;
|
|
2680
|
+
/** Opt in to a footer action that clears the current selection. */
|
|
2681
|
+
clearLabel?: string;
|
|
2632
2682
|
}
|
|
2633
2683
|
type SelectMultipleValueProps<Value extends string = string> = SelectMultipleLabelProps<Value> | SelectMultipleIconProps<Value>;
|
|
2634
2684
|
type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName & (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);
|
|
@@ -2777,14 +2827,14 @@ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
|
|
|
2777
2827
|
```ts
|
|
2778
2828
|
import 'kerfjs';
|
|
2779
2829
|
import './semantic-content-BbzjvSu9.js';
|
|
2780
|
-
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-field-
|
|
2830
|
+
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-field-DvgFLhLL.js';
|
|
2781
2831
|
```
|
|
2782
2832
|
|
|
2783
2833
|
## `@kerfjs/ui/wire-token-search-fields`
|
|
2784
2834
|
|
|
2785
2835
|
```ts
|
|
2786
2836
|
import { Signal } from 'kerfjs';
|
|
2787
|
-
import { d as TokenSearchModel } from './token-search-field-
|
|
2837
|
+
import { d as TokenSearchModel } from './token-search-field-DvgFLhLL.js';
|
|
2788
2838
|
import './semantic-content-BbzjvSu9.js';
|
|
2789
2839
|
|
|
2790
2840
|
interface TokenSearchSubmit {
|
|
@@ -3034,6 +3084,40 @@ declare function Badge(props: BadgeProps): SafeHtml;
|
|
|
3034
3084
|
export { Badge, type BadgeAppearance, type BadgeDotProps, type BadgeProps, type BadgeShape, type BadgeSize, type BadgeTextProps, type BadgeTone };
|
|
3035
3085
|
```
|
|
3036
3086
|
|
|
3087
|
+
## `@kerfjs/ui/chip`
|
|
3088
|
+
|
|
3089
|
+
```ts
|
|
3090
|
+
import { SafeHtml } from 'kerfjs';
|
|
3091
|
+
import { BadgeTone, BadgeAppearance, BadgeShape, BadgeSize } from './badge.js';
|
|
3092
|
+
|
|
3093
|
+
interface ChipCommonProps {
|
|
3094
|
+
/** Visible, non-interactive chip content. */
|
|
3095
|
+
children: SafeHtml | string | number;
|
|
3096
|
+
tone?: BadgeTone;
|
|
3097
|
+
appearance?: BadgeAppearance;
|
|
3098
|
+
shape?: BadgeShape;
|
|
3099
|
+
size?: BadgeSize;
|
|
3100
|
+
disabled?: boolean;
|
|
3101
|
+
/** Record identifier available to an application delegated action handler. */
|
|
3102
|
+
itemId?: string;
|
|
3103
|
+
className?: string;
|
|
3104
|
+
/** Native named-slot assignment when composed inside a web component. */
|
|
3105
|
+
slot?: string;
|
|
3106
|
+
}
|
|
3107
|
+
/** A removable chip needs both a delegated action and a specific accessible name. */
|
|
3108
|
+
type ChipProps = ChipCommonProps & ({
|
|
3109
|
+
removeAction: string;
|
|
3110
|
+
removeLabel: string;
|
|
3111
|
+
} | {
|
|
3112
|
+
removeAction?: never;
|
|
3113
|
+
removeLabel?: never;
|
|
3114
|
+
});
|
|
3115
|
+
/** A short label with an optional native remove button. The application owns removal. */
|
|
3116
|
+
declare function Chip({ children, tone, appearance, shape, size, disabled, itemId, className, slot, ...remove }: ChipProps): SafeHtml;
|
|
3117
|
+
|
|
3118
|
+
export { Chip, type ChipProps };
|
|
3119
|
+
```
|
|
3120
|
+
|
|
3037
3121
|
## `@kerfjs/ui/lucide-icon`
|
|
3038
3122
|
|
|
3039
3123
|
```ts
|
|
@@ -3196,13 +3280,12 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
|
3196
3280
|
type GridRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
3197
3281
|
'data-component'?: never;
|
|
3198
3282
|
'data-columns'?: never;
|
|
3283
|
+
'data-min-column-width'?: never;
|
|
3199
3284
|
'data-flex'?: never;
|
|
3200
3285
|
'data-fill'?: never;
|
|
3201
3286
|
}>;
|
|
3202
|
-
interface
|
|
3287
|
+
interface GridCommonProps {
|
|
3203
3288
|
children?: KerfUiContent;
|
|
3204
|
-
/** Number of equal-width columns. Must be a positive safe integer. */
|
|
3205
|
-
columns: number;
|
|
3206
3289
|
/** A named UI spacing token or typed CSS length. Defaults to xs. */
|
|
3207
3290
|
gap?: UiSpaceName | CssLength;
|
|
3208
3291
|
/** Allow this grid to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */
|
|
@@ -3219,8 +3302,17 @@ interface GridProps {
|
|
|
3219
3302
|
/** Native named-slot assignment when composed inside a web component. */
|
|
3220
3303
|
slot?: string;
|
|
3221
3304
|
}
|
|
3222
|
-
|
|
3223
|
-
|
|
3305
|
+
type GridProps = GridCommonProps & ({
|
|
3306
|
+
/** Number of equal-width columns. Must be a positive safe integer. */
|
|
3307
|
+
columns: number;
|
|
3308
|
+
minColumnWidth?: never;
|
|
3309
|
+
} | {
|
|
3310
|
+
columns?: never;
|
|
3311
|
+
/** Fit equal columns of at least this width; collapse as the container narrows. */
|
|
3312
|
+
minColumnWidth: CssLength;
|
|
3313
|
+
});
|
|
3314
|
+
/** Render equal tracks with a fixed count or a responsive minimum width. */
|
|
3315
|
+
declare function Grid({ children, columns, minColumnWidth, gap, flex, fill, className, rootAttributes, slot, }: GridProps): kerfjs.SafeHtml;
|
|
3224
3316
|
|
|
3225
3317
|
export { CssFlex, CssFlexKeyword, CssLength, Grid, type GridProps, UiSpaceName };
|
|
3226
3318
|
```
|
|
@@ -3252,6 +3344,6 @@ export { CssLength, Spacer, type SpacerProps, UiSpaceName };
|
|
|
3252
3344
|
|
|
3253
3345
|
```ts
|
|
3254
3346
|
import 'kerfjs';
|
|
3255
|
-
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion, k as createTokenSearchModel } from './token-search-field-
|
|
3347
|
+
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion, k as createTokenSearchModel } from './token-search-field-DvgFLhLL.js';
|
|
3256
3348
|
import './semantic-content-BbzjvSu9.js';
|
|
3257
3349
|
```
|
package/ai/skill.md
CHANGED
|
@@ -139,7 +139,7 @@ Quick routing:
|
|
|
139
139
|
| ------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
140
140
|
| Navigation row | `ListItem` | Use an ordinary link or button when sidebar/menu anatomy and state do not apply. Its rounded root clips overflowing descendants; set `multiline` when the primary label should wrap. Multiline leading icons stay aligned with the first text line. |
|
|
141
141
|
| Horizontal flex layout | `Row` | Use `hAlign`/`vAlign`, a typed `gap`, and opt-in `wrap`; use `List` when the main axis is vertical. |
|
|
142
|
-
| Equal-width columns | `Grid` | Use
|
|
142
|
+
| Equal-width columns | `Grid` | Use fixed `columns` or typed `minColumnWidth` for automatic container-width collapse, plus typed `gap`/`flex`. Use CSS grid for asymmetric/intrinsic tracks and `ResizableRegion` for adjustable boundaries. |
|
|
143
143
|
| Navigation row with a trailing action | `ListActionRow` | Use `ListItem` when the trailing region is dormant; never put controls inside either component's SafeHtml slots. Multiline leading icons stay aligned with the first text line. |
|
|
144
144
|
| Page, panel, or dialog heading | `Toolbar` + `ToolbarText` | Use a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. |
|
|
145
145
|
| Exclusive choice | `TabBar`, `SegmentedControl`, or `Select` | Tabs switch tabpanels; segments expose a few choices; Select handles a longer value list. |
|
|
@@ -152,6 +152,11 @@ Quick routing:
|
|
|
152
152
|
| Key/value facts | `ValueTable` with `ValueTableRow` | Use rows with `icon` only when the optional 24px leading visual adds context. |
|
|
153
153
|
| Command search | Application-local semantics using shared layout vocabulary | No runtime component or production recipe is exported; the app owns behavior, policy, and copy. |
|
|
154
154
|
|
|
155
|
+
For equal-width responsive forms, set `Grid minColumnWidth={px(376)}` instead of
|
|
156
|
+
`columns`. Grid fits tracks from its own container width and collapses to one
|
|
157
|
+
when a second minimum-width track plus the gap no longer fits. Constrain the
|
|
158
|
+
outer Grid width when the form should have a maximum column count.
|
|
159
|
+
|
|
155
160
|
For a complete shell, sidebar, workspace header, list-detail dialog, composer
|
|
156
161
|
form, list-state lifecycle, or mixed-control toolbar, start from the runnable
|
|
157
162
|
reference in [`docs/recipes.md`](../docs/recipes.md). Preserve its production
|
|
@@ -190,11 +195,12 @@ Hard rules:
|
|
|
190
195
|
4. Wire `data-action` hooks from one stable root with `delegate()` or `delegateActions()` and retain disposers.
|
|
191
196
|
5. Configure components through their typed props; components own their own styles (see "Components own their styles; configure, never override" above). Use the opinionated `--kui-color-*` semantic ramps for theming, not to reshape a component. Use `pop` only for attractive non-status emphasis such as featured, novel, or celebratory content; never substitute it for info, success, warning, or danger. Set a theme token only at the narrowest useful scope, and never where an equivalent prop exists. `publicClasses` exist for diagnostics, tooling, tests, and package-owned composition, not application styling. Never target a Kerf or Web Awesome component from application CSS; add missing configuration to the owner.
|
|
192
197
|
6. `Select` is pure until the app explicitly imports `@kerfjs/ui/select/register`; once registered, an icon-only `Select` (and, via `@kerfjs/ui/popup-menu/register`, an icon-only `PopupMenu`) shows an `aria-hidden` help tag repeating its accessible name (and a Select's current choice) on hover and keyboard focus, hidden while its popup is open — never add a `title` or your own tooltip to these triggers. The same installer tags an icon-only `<button>` or link in a `ToolbarControlGroup` named by `aria-label` (no visible text, no `title`); a toolbar with such buttons but no registered Select or PopupMenu imports `@kerfjs/ui/help-tags/register` once. Name those buttons with `aria-label`, not `title`: a `title` keeps the browser tooltip and skips the tag. Do not import Web Awesome's full registration bundle. When an app writes direct `wa-*` JSX, add `import type {} from '@kerfjs/ui/webawesome'` for the catalog-supported intrinsic-element declarations, import the CSS-only `@kerfjs/ui/webawesome.css` theme once, and keep importing individual Web Awesome component modules so their JavaScript remains tree-shakeable. The type boundary emits no code and registers nothing. Pass icon-bearing `choices` and `renderSelected` content normally: `Select` preserves its slotted option icons across Kerf rerenders and keys selected content by the controlled value, so app wrappers must not add competing morph-control attributes. Give it a visible `label` or an `ariaLabel` for a visually hidden name; the nonempty visible label takes precedence and the package names the actual shadow combobox, including `renderSelected`, without adding label geometry. Use `hint` for persistent supporting text below the control and `placeholderText` only for the empty value inside the closed control; loading placeholders retain the hint. For any number of choices set `multiple` with an array `value`: the popup stays open while choices toggle and closes on an outside press or Escape, the closed control summarizes the chosen labels, and `change` reports the value array; do not add app code to keep it open or to render tags. For a toolbar filter menu, add `selectedPresentation="icon-only"` plus a fixed `triggerIcon` (such as a funnel `LucideIcon`): the trigger shows that icon, a count badge while any choice is chosen, and ends its accessible name with the chosen labels ("Filter by label: Bug, Docs"); do not render your own count badge or rewrite the name. When testing name or description, target the element with the `combobox` role rather than the `wa-select` wrapper. Web Awesome's hint attribute and explicit hint slot both describe that shadow combobox across supported engines; do not add an `aria-description` mirror or application shadow-DOM patch.
|
|
193
|
-
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. `DisclosureArrow` defaults to an 18px root-scaled visual; size it with its typed `size` prop (`size={remify(24)}`); it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5
|
|
198
|
+
7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. `DisclosureArrow` defaults to an 18px root-scaled visual; size it with its typed `size` prop (`size={remify(24)}`); it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`; an icon-only toolbar Select may set `caret={false}` for a round trigger while preserving its help tag and keyboard listbox.
|
|
194
199
|
8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only. Set `responsiveFillAt="narrow"` or `"compact"` when a responsive composition exposes the pane as its only inline track; the component fills that track and hides its dormant separator. For compact overlays, set `presentation="overlay"` and the overlay maximum variables. A lone child (normally a `Pane`) fills the region and owns scrolling; several children stack at natural height. Do not add descendant width/height overrides.
|
|
195
200
|
9. Use controlled `SegmentedControl` for a small exclusive choice set. Select `appearance="toolbar"` when nesting it inside `ToolbarControlGroup`; use rounded or pill shapes for standalone contexts. The package derives inset hover/selection radii from the owning outer shape through `--kui-layout-highlight-inset`; do not restyle an inner highlight to an independent radius. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
|
|
196
201
|
10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. For a tab-local action followed by a separately pinned workspace action, set `trailingPlacement="adjacent"`, put the local action in `trailing`, and the workspace action in `end`; TabBar owns the shrinking/scrolling tabs and fixed action geometry, so do not add descendant flex overrides. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
|
|
197
|
-
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes; to replace the text programmatically (reseeding a persistent dialog's field on reopen, applying a saved search) change the field's `revision` along with `query
|
|
202
|
+
11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes; to replace the text programmatically (reseeding a persistent dialog's field on reopen, applying a saved search) change the field's `revision` along with `query` for an unmanaged field, or call `model.replace({ query, tokens })` for a model-managed field; never re-key a wrapper. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. For automatic parsing, chips, suggestions, and evaluation, use createTokenSearchModel with grammar rules, pass it as TokenSearchField.model, and register it in wireTokenSearchFields models; a rule's `suggest(input, state)` receives committed tokens so it can exclude selected values. Otherwise the app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. `clearIcon` replaces the clear action's glyph (its `clearLabel` still names it). Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, a clear-button mousedown guard, or reopening after controlled clear or Select All deletion — the helper keeps the replacement editor open and focused. Clear and deletion restoration finish at the replacement mutation checkpoint before the next input task, so shortcut-letter typing cannot escape to the page and delayed animation frames cannot overwrite a later selection. Persist both query and tokens returned by the DOM read. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
|
|
203
|
+
An application helper can call `model.commit(value)` for the active `name:` prefix when it computes a valid value outside suggestions; invalid values and missing prefixes leave the query unchanged.
|
|
198
204
|
12. Demo work uses public production component subpaths and their browser-selected CSS. Focused demos and recipes have no local stylesheet, inline style, or styling-only class; use public components and `CatalogExample.viewport` for unavoidable specimen constraints (a recipe declares its frame through its exported `presentation`). When a recipe needs a capability no component offers, report the component gap instead of adding CSS. Use exactly three demo kinds: a `component` is one component with variants/states, a `composition` is a focused container of components commonly used together, and a `recipe` is the recommended production approach to a task. Organize catalog routes into product-important functional groups; within each group put all components before compositions, order each kind by importance with display-name alphabetical tie-breaking, and put recipes after every component/composition group. Show `Composition` as an entry tag instead of repeating the word in its name. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. For the complete taxonomy, focused/composition decision, `CatalogExample` / `CatalogExampleStack` row/group nesting, exact specimen selection, geometry-overlay legend and exclusions, skip-marker behavior, and metadata ownership, follow the single [Catalog demo authoring contract](../docs/catalog.md#catalog-demo-authoring-contract), discovered machine-readably through [`catalog-authoring.json`](./catalog-authoring.json). Never infer structure from private `kui-catalog-*` classes. Project each component's deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute. Enable `wireCatalog({ revealSelection: true })` for long desktop sidebars so controlled selections remain visible without moving focus; keep its default compact media guard unless compact scrolling is an explicit product behavior, and use `revealCatalogEntry` for an initial deep link.
|
|
199
205
|
13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content and framed disclosure regions). Plain Details use the 8px surface inset on the trigger and keep the body flush; plain Accordion items use it on both trigger and body. Outlined and sunken Details use the 16px container inset on the trigger and 8px on the body; framed Accordion items use 16px on both. Dialog maps its body to the 8px surface tier and its footer to the 16px container tier independently of `--spacing`. Override those tiers instead of restyling individual parts. Filled badges use each variant's quiet fill with normal text so their compact copy stays WCAG-AA readable; override the pair with `--kui-wa-badge-filled-background` / `--kui-wa-badge-filled-foreground`, not host selectors. When a dialog provides another dismissal affordance, put `hide-actions` on the `wa-dialog` host to hide its directly exported `header-actions` part; never chain `::part()` selectors through internal parts. Checkbox and Radio Group option regions, the Color Picker trigger, and Slider's complete interactive region receive the shared 8px logical inline outer inset because those controls have no bordered field shell. Known Date field captions and bordered text-like field hints align with values at the 9px border-plus-padding inset. OTP Input's label uses the same uppercase xs/650 treatment as other field labels, and both its label and hint use that 9px inset.
|
|
200
206
|
14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Its UX sidebar marks superseded and exceptional entries `Discouraged`. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame. Never render a `Discouraged` element directly in application, demo, or recipe markup; reach it only through the Kerf component that wraps it (`PopupMenu` renders `wa-dropdown`, `Select` renders `wa-select` / `wa-option`), and treat a Kerf component gap as a request to file, not a reason to drop to the raw element.
|
|
@@ -203,6 +209,8 @@ Hard rules:
|
|
|
203
209
|
16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
|
|
204
210
|
16a. Dividers between pinned chrome and scrolling content are scroll state, not decoration: a `Toolbar` draws none by default (`dividerSides` is for a permanent edge only). Call `wireScrollDividers(appRoot)` from `@kerfjs/ui/wire-scroll-dividers` once and retain its disposer; every `Pane` then draws the line under its header only while content is scrolled beneath it and over its footer only while more content lies below (never when the content fits), every `NavStack`'s top chrome and bottom toolbar and every `TabScaffold` bar do the same around the active view or scene (keyed on whatever actually scrolls there, including a sole `Pane`'s content), and every `TabBar` marks each side of its strip with tabs scrolled out of view. Configure a pane with `chromeDividers` (`scroll` default, `always`, `none`, also via `PaneConfig`), and a `NavStack` or `TabScaffold` with its own `chromeDividers` (same values: `always` draws the chrome lines without the wiring, `none` never, even when wired; a `SplitView` forwards it through `compactStack`); a `toolbarConfig.dividerSides` edge stays the Toolbar's own. Name app-owned chrome by id in `targets`. The wiring writes only `data-scroll-overflow` / `data-scroll-divider` state; never write a border onto a component to show a divider.
|
|
205
211
|
17. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. Put identity/title text directly in the zone as `ToolbarText`; wrap interactive controls and icon tiles in `ToolbarControlGroup`. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a group. Configure zone behavior with `Toolbar.centerAlign` and its `responsive` / `responsiveAt` policy instead of selecting toolbar zone classes. No policy clips an action: trailing (and stacked center) zones wrap whole groups onto another row, and the center zone never compresses below its content (a leading title too long for the row truncates with an ellipsis instead), so never hide or shrink a toolbar control to make it fit; use `responsive="wrap"` for a heading whose title must stay whole, and move genuinely lower-priority commands into an app-owned "More" popup menu. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature. A popup menu in a toolbar is a `PopupMenu` (`@kerfjs/ui/popup-menu`, registered once via `@kerfjs/ui/popup-menu/register`) in a `single` group with `nestedDropdown` and a `menuInset`: give it typed `items` (commands with `action`s, `heading`s, `divider`s) and a trigger `icon` plus visible `text` or an accessible `label`; never hand-write `wa-dropdown` / `wa-dropdown-item` markup for a menu. Let the group size that trigger from its icon, localized text, and caret; do not force a width on the menu or button. Nothing wraps inside a group: an icon sits beside its label on one row and a group's controls never break onto a second line — the group sizes to its content, so if it does not fit, the toolbar's `responsive` policy relocates whole groups. A `ToolbarText` is one line ending in an ellipsis by default; opt into `wrap` (capped by `maxLines`) or `ellipsis={false}` deliberately. Inside a group, a `Select` or `PopupMenu` trigger drops its focus ring while its popup is open (the open popup and its current row show where focus is) and the ring returns when the popup closes; a ring follows the control's shape (a pill for an icon-and-caret trigger, a circle for a compact icon button) — set `focusRingOwner="group"` on a Select whose group paints the composed ring, and never add CSS to show, hide, or reshape a ring. For a compact mixed group, keep the standard item padding and raised selected chrome; the selected item paints over the outer border without an internal separator. For an avatar control, set `content="avatar"` and `avatarImage` on the group instead of inserting an `img`: a lone control paints the contained image on the outer group and a multi-button group paints it only on the pressed selection highlight. Compose panel/dialog/page headings with a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. A non-interactive heading icon is an icon tile: put the `LucideIcon` directly in its `ToolbarControlGroup` (it takes an icon button's 40px slot and centers), never inside a `<button>` that does nothing. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Each zone item sits in the toolbar's top 44px control band, centered by its own size; a taller item (a wrapped title, a second trailing row) starts at the band's top and grows down without moving the others, so a wrapped `ToolbarText` keeps trailing controls beside its first line — do not add alignment CSS for this. Split dormant and interactive regions: `ListHeader` fills the available inline width by default; set `width="content"` to shrink-wrap while retaining its normal geometry, or `inline` when it belongs in surrounding text without outer margin, border, or padding. It keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square whose transparent hit layer keeps the pointer target at least 44px (44px wide by the 36px row in `density="compact"`); never shrink the target to match the visual, and never force the button to 44px. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets. Dividers are chrome and earn their place: a `Toolbar` draws none by default, and the line between pinned chrome and scrolling content comes from scroll state (rule 16a), so never add a border, a permanent `dividerSides`, or a margin to fake or adjust one.
|
|
212
|
+
For a toolbar heading that must remain at the 20px `--kui-font-l` step, use `ToolbarText size="xlarge-fixed"`; `xlarge` retains the responsive page-title clamp. Pass `headingLevel` when it is a section landmark.
|
|
213
|
+
|
|
206
214
|
18. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, toolbar title/supporting-copy ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. For multi-line banner copy use `copyLayout="stacked"`; use `actionPlacement="below"` for an action on its own trailing row. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
|
|
207
215
|
|
|
208
216
|
For compact `Select` triggers, set `triggerWidth` to `fit-content`, `max-content`,
|
|
@@ -214,12 +222,20 @@ tokens; plain text ellipsizes in a narrow trigger.
|
|
|
214
222
|
|
|
215
223
|
For application tabs, `AppTab presentation="icon-only"` retains its accessible `name`, `labelMaxWidth` truncates the visible name, and `attention` colors it through `--kui-app-tab-attention-color`. Configure TabBar strip geometry through public `--kui-tab-bar-strip-*` tokens.
|
|
216
224
|
|
|
225
|
+
Set `AppTab dropTarget` while content is dragged over a tab to highlight the target without changing selection. Use `nameOverflow="visible"` for an inline loading treatment that needs the full visible name; the default is an ellipsis.
|
|
226
|
+
|
|
227
|
+
Set `pinned` on the first `AppTab` when it must stay visible while peers scroll. Keep it inside `TabBar` children so it remains in the tablist and roving focus order. Use `--kui-app-tab-pinned-background` for a non-default surrounding surface; the pinned backdrop must cover tabs beneath it.
|
|
228
|
+
|
|
217
229
|
Use `--kui-resizable-region-background` for a region surface and `contentOverflow="visible"` while its anchored popup needs to escape. Choose a top or bottom `restorePosition`, typed `restoreInset`, or `restorePlacement="inline"` for its collapsed restore control. `FloatingToolbar placement="inline"` stays in normal flow; its per-edge inset tokens and `safeAreaInsets` configure floating placement.
|
|
218
230
|
|
|
219
231
|
Use `ListItem density="spacious"` for larger option rows, `multiline` plus `multilineIconAlign="center"` when its icon should center on wrapped copy, `divider` for row separators, and `state="drag-target"` for the drop target treatment. Public `--kui-list-item-*` tokens adjust row, icon, label, and trailing geometry and color; ListHeader height, title padding, and border tokens adjust section density.
|
|
220
232
|
|
|
233
|
+
For a filled command list, scope `--kui-list-item-background`, `--kui-list-item-border`, `--kui-list-item-hover-border`, and `--kui-list-item-selected-border` at the List or ListItem boundary. Keep global neutral and brand border colors semantic.
|
|
234
|
+
|
|
221
235
|
Use `Toolbar responsive="trailing-priority"` when an expanded trailing search needs a full second row below its heading at `responsiveAt`. Configure a leading minimum width, trailing gap and justification, or zone inline padding with the public `--kui-toolbar-*` tokens rather than selectors into toolbar zones.
|
|
222
236
|
|
|
237
|
+
Set `--kui-toolbar-inset: 0px` on an embedded Toolbar to remove its outer padding while retaining `--kui-toolbar-gap` between zones. The same inset token controls the minimum-height allowance; safe-area padding still applies at claimed edges.
|
|
238
|
+
|
|
223
239
|
For compact dialog copy, use `Text flush lineHeight="tight"`; for compact metadata, use `ValueTable density="compact"` and its public row columns/padding/gap tokens. `ToolbarText size="xsmall"` fits a dense rail heading. A `TokenSearchField` editor shrinks inside a narrow group by default; set `--kui-token-search-editor-min-width` when a minimum is needed. A full-height shell uses the one `.kui-app-root` mount container documented in `docs/document-baseline.md`.
|
|
224
240
|
|
|
225
241
|
Common mistakes:
|
|
@@ -264,7 +280,11 @@ Common mistakes:
|
|
|
264
280
|
|
|
265
281
|
For prominent content text, use `Text size="large"`; use `size="xlarge"` for display copy. Both sizes work with semantic `variant`, `tone`, and `font`, so keep heading levels based on the document outline.
|
|
266
282
|
|
|
267
|
-
For
|
|
283
|
+
For removable tags use `Chip`, with `removeAction` for delegated handling and a specific `removeLabel` for the native button. `itemId` identifies the tag; the app owns removal. `size="compact"` and `disabled` replace app styling of raw `wa-tag` internals. Use `Badge` for non-interactive metadata.
|
|
284
|
+
|
|
285
|
+
For `Select`, mark an unavailable choice with `disabled` and optionally `disabledReason`. In a multiple Select, `selectAllLabel` and `clearLabel` opt in to localized footer actions that select enabled choices or clear the selection through normal input/change events; the app still owns the controlled `value`.
|
|
286
|
+
|
|
287
|
+
For nested action menus, use `PopupMenuItem.submenu` with item, heading, and divider entries; headings and dividers do not enter keyboard navigation. Items support `checked`, `icon`, `details`, `disabledReason`, and `tone`. The app owns choice state. For a right-click menu, use `PopupMenu` with `context: true` and call `openPopupMenuAt` from the app's `contextmenu` handler; the package positions and opens the menu. Call `closePopupMenu` for programmatic dismissal.
|
|
268
288
|
|
|
269
289
|
## Select lifecycle ownership
|
|
270
290
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from the emitted `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.62` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|