@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/dist/tab-scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":"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","file":"tab-scaffold.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Badge } from './badge.js';\nimport type { PaneAppearance } from './pane.js';\nimport type { KerfUiContent } from './semantic-content.js';\n\ninterface TabScaffoldTabBase<Id extends string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: KerfUiContent;\n /** Background of this scene's scrolling work surface. */\n appearance?: PaneAppearance;\n}\n\n/** A tab with an optional count or short-status badge. */\ninterface TabScaffoldTabCountBadge {\n /**\n * Optional count or short status shown as a solid danger `Badge` at the\n * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,\n * or non-finite numbers render no badge. The visual badge is `aria-hidden`;\n * its meaning reaches assistive technology through `badgeLabel`.\n *\n * Pass `true` instead for the text-free dot (new content without a count).\n */\n badge?: string | number;\n /**\n * Localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"3 unread\"` → `\"Inbox, 3 unread\"`).\n * Defaults to the badge text itself. Ignored when no badge renders.\n */\n badgeLabel?: string;\n}\n\n/** A tab with the text-free dot badge (new content without a count). */\ninterface TabScaffoldTabDotBadge {\n /**\n * `true` shows a solid danger dot `Badge` at the top-trailing corner of the\n * tab icon — the iOS tab-bar dot for new content without a count.\n */\n badge: true;\n /**\n * Required localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"New activity\"` →\n * `\"Feed, New activity\"`). A dot has no text, so this is its only meaning.\n */\n badgeLabel: string;\n}\n\n/** One bottom-bar destination: its label, optional icon and badge, and content. */\nexport type TabScaffoldTab<Id extends string = string> =\n TabScaffoldTabBase<Id> & (TabScaffoldTabCountBadge | TabScaffoldTabDotBadge);\n\nexport interface TabScaffoldProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabScaffoldTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n /**\n * The line over the tab bar, where it meets the active scene. `scroll`\n * (default) shows it only while more of the scene's content lies below —\n * never at the scroll end or when the content fits — once\n * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above\n * the scaffold; unwired, it does not show. `always` shows it without the\n * wiring; `none` never, even when wired. The line is the bar's own 1px top\n * border, so no state moves the bar or a tab.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab scaffold: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-scaffold`'s `wireTabScaffold`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabScaffold<Id extends string>({\n id,\n label,\n tabs,\n active,\n chromeDividers = 'scroll',\n className = '',\n slot,\n}: TabScaffoldProps<Id>) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n slot={slot}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n data-appearance={tab.appearance === 'sunken' ? 'sunken' : undefined}\n aria-hidden={String(tab.id !== active)}\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => {\n const dot = tab.badge === true;\n const badgeText = dot ? undefined : normalizeBadge(tab.badge);\n const hasBadge = dot || badgeText !== undefined;\n const badge = hasBadge && (\n <span\n class=\"kui-tab-scaffold__tab-badge\"\n data-badge-kind={dot ? 'dot' : 'text'}\n >\n {badgeText === undefined ? (\n <Badge tone=\"danger\" size=\"dot\" ariaHidden />\n ) : (\n <Badge\n tone=\"danger\"\n appearance=\"solid\"\n size=\"compact\"\n ariaHidden\n >\n {badgeText}\n </Badge>\n )}\n </span>\n );\n // A dot has no text fallback: without a usable badgeLabel (reachable\n // only from untyped callers) the tab keeps its plain accessible name.\n const badgeLabel = hasBadge\n ? tab.badgeLabel?.trim() || badgeText\n : undefined;\n return (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n aria-label={\n badgeLabel === undefined\n ? undefined\n : `${tab.label}, ${badgeLabel}`\n }\n data-has-badge={hasBadge ? 'true' : undefined}\n >\n {tab.icon ? (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n {badge}\n </span>\n ) : (\n badge\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </section>\n );\n}\n\nfunction normalizeBadge(\n badge: string | number | undefined,\n): string | undefined {\n if (typeof badge === 'number')\n return Number.isFinite(badge) ? String(badge) : undefined;\n if (typeof badge === 'string' && badge.trim()) return badge.trim();\n return undefined;\n}\n"]}
|
|
@@ -8,8 +8,8 @@ interface TokenSearchRule {
|
|
|
8
8
|
parse?: (input: string) => string | undefined;
|
|
9
9
|
/** Label for a committed chip. Defaults to `name:input`. */
|
|
10
10
|
label?: (value: string, input: string) => string;
|
|
11
|
-
/** Suggestions for the unfinished value after `name
|
|
12
|
-
suggest?: (input: string) => readonly (string | {
|
|
11
|
+
/** Suggestions for the unfinished value after `name:`, with current committed tokens. */
|
|
12
|
+
suggest?: (input: string, state: TokenSearchState) => readonly (string | {
|
|
13
13
|
value: string;
|
|
14
14
|
label: string;
|
|
15
15
|
})[];
|
|
@@ -33,8 +33,12 @@ interface TokenSearchModel<Result = unknown> {
|
|
|
33
33
|
suggestions: Signal<readonly TokenSearchSuggestion[]>;
|
|
34
34
|
result: Signal<Result | undefined>;
|
|
35
35
|
edit(value: TokenSearchFieldValue, commit?: boolean): void;
|
|
36
|
+
/** Replace app-owned search state and rebuild the DOM-owned editor text. */
|
|
37
|
+
replace(value: TokenSearchFieldValue): void;
|
|
36
38
|
submit(value: TokenSearchFieldValue): void;
|
|
37
39
|
choose(value: string): void;
|
|
40
|
+
/** Commit a value for the active `name:` prefix, even when it is not suggested. */
|
|
41
|
+
commit(value: string): void;
|
|
38
42
|
expandToken(value: string): void;
|
|
39
43
|
remove(value: string): void;
|
|
40
44
|
clear(): void;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import 'kerfjs';
|
|
2
2
|
import './semantic-content-BbzjvSu9.js';
|
|
3
|
-
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-
|
|
3
|
+
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';
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import 'kerfjs';
|
|
2
|
-
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-
|
|
2
|
+
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';
|
|
3
3
|
import './semantic-content-BbzjvSu9.js';
|
package/dist/toolbar-text.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as kerfjs from 'kerfjs';
|
|
2
2
|
|
|
3
|
-
type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small' | 'xsmall';
|
|
3
|
+
type ToolbarTextSize = 'xlarge' | 'xlarge-fixed' | 'large' | 'default' | 'small' | 'xsmall';
|
|
4
4
|
/** ARIA heading level for a title exposed as a heading landmark. */
|
|
5
5
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
6
|
interface ToolbarTextBaseProps {
|
package/dist/toolbar-text.js
CHANGED
package/dist/toolbar.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ interface ToolbarProps {
|
|
|
17
17
|
* then draws its facing side the same way.
|
|
18
18
|
*/
|
|
19
19
|
dividerSides?: Sides;
|
|
20
|
-
/**
|
|
21
|
-
centerAlign?: 'center' | 'stretch';
|
|
20
|
+
/** `balanced` gives both side zones equal tracks, centering the middle zone on the toolbar even if only one side has controls. */
|
|
21
|
+
centerAlign?: 'center' | 'stretch' | 'balanced';
|
|
22
22
|
/**
|
|
23
23
|
* Component-owned responsive layout; applications choose the policy rather
|
|
24
24
|
* than restyling toolbar internals. Under every policy the trailing zone
|
package/dist/toolbar.js
CHANGED
package/dist/wire-catalog.js
CHANGED
package/dist/wire-tab-bars.js
CHANGED
package/dist/workbench.js
CHANGED
package/docs/accessibility.md
CHANGED
|
@@ -7,6 +7,7 @@ These are normative contracts for package components and consuming applications.
|
|
|
7
7
|
- All controls have accessible names and visible `:focus-visible` treatment.
|
|
8
8
|
- Decorative `LucideIcon` output is `aria-hidden`; pass `label` only when the SVG itself conveys meaning.
|
|
9
9
|
- `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Selected rows keep the normal foreground over their brand-tinted fill so text retains WCAG AA contrast in light and dark themes. Its leading icon visual is 18px while the row retains its 44px minimum target; multiline icons align to the first text line. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
|
|
10
|
+
- `ListItemLink` shares that row content and geometry but uses native anchor Enter behavior and requires `href`. It has no `action` or `pressed` state. `external` opens a new tab with `rel="noopener noreferrer"`; the default accessible name announces the new tab for a string label, so an explicit `accessibleLabel` should do the same. Disabled and loading links omit `href`, expose `aria-disabled`, and leave the tab order. Its trailing content remains dormant.
|
|
10
11
|
- `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
|
|
11
12
|
- Dispose `wireTabBars` and `wireTokenSearchFields` with their owning view. Disposal cancels queued controlled-render focus restoration, so a torn-down view cannot reclaim focus from its successor.
|
|
12
13
|
- `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
|
|
@@ -14,6 +15,7 @@ These are normative contracts for package components and consuming applications.
|
|
|
14
15
|
- `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
|
|
15
16
|
- An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
|
|
16
17
|
- `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
|
|
18
|
+
- A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Tag text remains visible because tone does not convey meaning alone.
|
|
17
19
|
- `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
|
|
18
20
|
- `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
|
|
19
21
|
- `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may resize it with the typed `size` prop without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
|
|
@@ -38,6 +40,12 @@ chosen option shows its check, and the closed control reads the chosen labels
|
|
|
38
40
|
in choice order as one short localized list (the `placeholderText` when none
|
|
39
41
|
are chosen) instead of a removable tag per choice. `change` and `input` report
|
|
40
42
|
the value array; in a form, every chosen value is submitted under `name`.
|
|
43
|
+
Disabled choices remain visible with `aria-disabled` and cannot be selected;
|
|
44
|
+
`disabledReason` adds a native tooltip. For a multiple Select, opt-in
|
|
45
|
+
`selectAllLabel` and `clearLabel` render named footer buttons. They keep the
|
|
46
|
+
popup open, select only enabled choices or clear the selection, and emit the
|
|
47
|
+
ordinary `input` and `change` events only when the value changes. Their labels
|
|
48
|
+
come from the application so they can be localized.
|
|
41
49
|
|
|
42
50
|
A toolbar filter menu (a "Filter by label" funnel) is a multiple Select with
|
|
43
51
|
`selectedPresentation="icon-only"` and a fixed `triggerIcon`; the types accept
|
|
@@ -196,7 +204,8 @@ with the Select's current-option fill rather than a second focus ring inside the
|
|
|
196
204
|
open popup. A disabled item stays in the menu but cannot be
|
|
197
205
|
chosen; disable the whole trigger only when every command is unavailable.
|
|
198
206
|
Nested items use Web Awesome's submenu pointer and Left/Right arrow routing;
|
|
199
|
-
|
|
207
|
+
headings and dividers can separate nested groups without becoming keyboard
|
|
208
|
+
choices. Checked items expose checkbox menu semantics. `details` supplies optional
|
|
200
209
|
trailing visual content without changing a command's accessible label. A
|
|
201
210
|
`context` menu's invisible anchor is outside the accessibility tree and normal
|
|
202
211
|
Tab order; opening the menu moves focus into its commands and Escape dismisses
|
|
@@ -317,7 +326,11 @@ trailing, and end actions remain visible and do not shrink. The component owns
|
|
|
317
326
|
that geometry; applications must not override its anatomy to create the split.
|
|
318
327
|
`AppTab` provides compact 32px, segmented, truncating-label, and icon-only
|
|
319
328
|
presentations. Icon-only tabs keep the required `name` as the tab button's
|
|
320
|
-
accessible name while visually hiding the duplicate label.
|
|
329
|
+
accessible name while visually hiding the duplicate label. The default name
|
|
330
|
+
overflow is an ellipsis; `nameOverflow="visible"` lets an inline loading
|
|
331
|
+
treatment show the whole name, without changing the accessible name. The app
|
|
332
|
+
sets `dropTarget` during a content drag-over to paint a brand highlight;
|
|
333
|
+
selection and tab focus stay independent of that visual state. A `pending` tab (known,
|
|
321
334
|
still opening) keeps its visible name as the tab button's accessible name, so a
|
|
322
335
|
trailing spinner's own label is not folded into it. It is `aria-busy` and stays
|
|
323
336
|
selectable (in the roving tab order like a live tab), so the application can
|
|
@@ -330,6 +343,12 @@ filtering rejects roles plus case variants of component- or wiring-owned
|
|
|
330
343
|
action, identity, selection, drag, drop, and component attributes. An optional
|
|
331
344
|
`closeIcon` is decorative dormant content inside the already named close button
|
|
332
345
|
and must not contain interactive descendants.
|
|
346
|
+
The first `AppTab` can set `pinned` to stay at the inline start while its peers
|
|
347
|
+
scroll. It remains a normal tab within the same tablist and roving-focus order;
|
|
348
|
+
focus and controlled selection reveal peers beyond the pinned tab. Pin only the
|
|
349
|
+
leading tab of a strip.
|
|
350
|
+
WebKit currently moves a pinned tab outside an RTL strip as it scrolls;
|
|
351
|
+
`KF-MYFQAS` tracks the browser correction.
|
|
333
352
|
`wireTabBars()` adds Left/Right wrapping, Home/End, Delete/Backspace close
|
|
334
353
|
activation, same-bar pointer reordering, `Alt+Shift+ArrowLeft/ArrowRight`
|
|
335
354
|
reordering, focus restoration, scroll-into-view, and pointer-proximity
|
|
@@ -363,7 +382,8 @@ stays in sequential Tab order, matching Hot Sheet 2's compact view and inspector
|
|
|
363
382
|
controls; Enter and Space use native button activation. The application handles
|
|
364
383
|
the supplied `data-action`, reads `data-segment-value`, updates `value`, and
|
|
365
384
|
re-renders. Keep labels unique and meaningful even when `content` shows only an
|
|
366
|
-
icon.
|
|
385
|
+
icon. The filled track uses the normal neutral text role for readable unselected
|
|
386
|
+
labels in light and dark themes. Use tabs—not a segmented control—when choices switch page regions that
|
|
367
387
|
need `tab`/`tabpanel` semantics.
|
|
368
388
|
|
|
369
389
|
## TokenSearchField
|
|
@@ -390,6 +410,12 @@ trailing controls share the first text line's fixed vertical center and remain
|
|
|
390
410
|
there as the editor wraps. In `collapsible` mode, the closed state is one named
|
|
391
411
|
iconic search button and the open state is the same named searchbox, whether
|
|
392
412
|
the field stands alone or is composed inside `ToolbarControlGroup`.
|
|
413
|
+
|
|
414
|
+
For an app-driven query replacement with an unmanaged field, change its
|
|
415
|
+
`revision` along with `query` so the editor text rebuilds. For a model-managed
|
|
416
|
+
field, call `model.replace({ query, tokens })`: it parses the supplied state and
|
|
417
|
+
advances `editorRevision` even when the tokens did not change.
|
|
418
|
+
|
|
393
419
|
Applications set `expanded` while the field is focused, move focus from the
|
|
394
420
|
trigger into the revealed editor, and clear `expanded` only after focus leaves
|
|
395
421
|
the complete component. Text or tokens keep the field expanded even when that
|
|
@@ -80,9 +80,10 @@ and that of the components it renders (`Pane`, `Toolbar`, `ToolbarControlGroup`,
|
|
|
80
80
|
corners, with typed `restoreInset` for the corner distance. Set
|
|
81
81
|
`restorePlacement="inline"` when the container should place the control in
|
|
82
82
|
normal flow. An inline region's surface uses
|
|
83
|
-
`--kui-resizable-region-background`;
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
`--kui-resizable-region-background`; an open descendant `PopupMenu` or Web
|
|
84
|
+
Awesome dropdown releases clipping and raises the popup layer for its
|
|
85
|
+
lifecycle. Set `contentOverflow="visible"` for other anchored content that
|
|
86
|
+
must escape the region's content box.
|
|
86
87
|
Overlay presentation also clamps fixed-size animated content to the configured
|
|
87
88
|
responsive overlay maximum, so a remembered desktop size cannot escape a narrow
|
|
88
89
|
viewport.
|
|
@@ -52,6 +52,11 @@ CSS boundaries, diagnostics, and provenance. A wrapper entry may add
|
|
|
52
52
|
composition checks treat its elements as each root rather than as an unknown
|
|
53
53
|
child. A placement with listed parent constraints produces one `KUI-L201`
|
|
54
54
|
diagnostic even when both the wrapper and a rendered root reject that parent.
|
|
55
|
+
When one catalog entry exports another JSX component with different placement,
|
|
56
|
+
`jsxExports` gives that export its own parent contract. The extra export does
|
|
57
|
+
not stand for the entry's root when a parent zone is checked.
|
|
58
|
+
Generated `boundaries.rootClass` prefers the public `kui-<entry-id>` class when
|
|
59
|
+
present, so a sibling export's class cannot become the entry's root class.
|
|
55
60
|
|
|
56
61
|
`boundaries.placeableClasses` names the subset of `publicClasses` an
|
|
57
62
|
application may write onto its own elements (layout utilities, the document
|
|
@@ -72,6 +72,8 @@ import { Row } from "@kerfjs/ui/row";
|
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
`CssValue` is the common branded base, not an arbitrary-string constructor.
|
|
75
|
+
For a responsive equal-width form, pass `Grid minColumnWidth={px(376)}` instead
|
|
76
|
+
of `columns`; the Grid's container width decides when the tracks collapse.
|
|
75
77
|
Raw strings such as `"0.25rem"` do not satisfy `Row.gap`, `Grid.gap`, or `List.gap`; this
|
|
76
78
|
contract lands before the 5.0 stable release so misspelled tokens and incomplete
|
|
77
79
|
expressions fail during typechecking rather than in the browser.
|
|
@@ -141,7 +143,7 @@ an upstream component or recipe request.
|
|
|
141
143
|
| Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel`. Sizes below `xlarge` are intentionally quiet identity text with no tone option — do not use them as a normal-color subsection title; use `Text` with an `h2`–`h6` variant, or `ListHeader` for a list section. | Optional `headingLevel` for `role="heading"` + `aria-level`. Defaults to one line, ellipsized when it does not fit; `wrap` flows onto multiple lines, `ellipsis` toggles the trailing …, and `maxLines` caps a wrap. | Text, heading level, overflow behavior, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
|
|
142
144
|
| Semantic block or inline text — `Text` | Ordinary application copy needs native `h1`–`h6` or `p` semantics plus standard geometry, or inline secondary copy needs a native `span` without box geometry. | Do not choose heading levels for appearance alone or recreate muted, error, small, or code utility classes. Use `ToolbarText` for toolbar identity/title content and `ListInsetText` when list-aligned prose needs full margin/border/padding geometry. | Omit `variant` for the default `p`, choose `h1`–`h6` from the document outline, or choose `span` inside a row, label, or table cell. Independently compose `tone="quiet | danger"`, `size="compact"`, and `font="monospace"`; ordinary native global, `data-_`, and `aria-_` attributes pass through. | Copy, localization, semantic variant, presentation roles, and document heading hierarchy. | `@kerfjs/ui/text` | [Text](./layout.md#text) |
|
|
143
145
|
| Vertical stack — `List` | Rows, sections, or arbitrary components need a consistent vertical stretch layout, optional standard/custom gap, flex growth, one vertical scroll owner, or edge dividers. | It is layout-only and does not provide `ul`/`ol` semantics. Do not nest scroll owners or use it when a horizontal layout is required. | Choose `gap`, `flex`, `scrollable`, and canonical `dividerSides` (`t`, `r`, `b`, `l` combinations in that order); bound the block size when scrolling. | Child semantics/content, containing height, and which optional layout behaviors apply. | `@kerfjs/ui/list` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
144
|
-
| Equal-width columns — `Grid` |
|
|
146
|
+
| Equal-width columns — `Grid` | Equal-width sibling columns need a fixed count or should collapse as their container narrows, while preserving equal tracks despite intrinsic child widths. | Do not use it for intrinsic, asymmetric, spanning, or masonry tracks; use application-owned CSS grid. Do not use it for a user-operable separator; use `ResizableRegion`. | Choose fixed `columns` or typed `minColumnWidth`, plus a typed `gap` and optional `flex`; responsive tracks preserve source order. | Child semantics/content, outer width, fixed count or minimum width, and typed gap/flex choices. | `@kerfjs/ui/grid` | [Grid](./layout.md#grid) |
|
|
145
147
|
| Navigation row — `ListItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `ListActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. The rounded root clips overflowing descendants; set `multiline` when the primary label should wrap. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
146
148
|
| Navigation row with trailing action — `ListActionRow` | A full-width row needs a selectable primary action and an independently focusable trailing action. | Use `ListItem` when trailing content is dormant metadata. Do not put controls inside the row's `label`, `icon`, or `trailingActionIcon` SafeHtml slots. Do not use `AppTab` outside tablist semantics or `ToolbarControlGroup` outside a toolbar. | Delegate both action strings; update controlled selection and any popover/context-menu state in the app. | Routing, selection, both action policies, domain metadata, and popover/context-menu behavior. | `@kerfjs/ui/list-action-row` | [Accessibility](./accessibility.md#listactionrow) |
|
|
147
149
|
| Navigation section heading — `ListHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing. Keep its 44px hit target; do not resize its 36px square. Do not use it as a page, panel, or dialog title; use a heading `Toolbar`. | Delegate its optional action; the app controls expanded state and revealed content. Toggle mode supplies `DisclosureArrow` unless `actionIcon` replaces it. Use `triggerAttributes` only for domain `data-*` or a native popover relationship. | Section organization, valid count and localized count label, disclosure state and content, non-count badge content, popover target behavior, and policy. | `@kerfjs/ui/list-header` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
@@ -174,10 +176,16 @@ an upstream component or recipe request.
|
|
|
174
176
|
|
|
175
177
|
## Ambiguous choices
|
|
176
178
|
|
|
179
|
+
For a lowered background behind an entire scrolling work area, choose
|
|
180
|
+
`Pane appearance="sunken"` or the appearance option on the layout that owns
|
|
181
|
+
the scroll viewport. Use `SunkenPanel` for a padded content group that does
|
|
182
|
+
not introduce scrolling. See [Lowered work surfaces](./layout.md#lowered-work-surfaces).
|
|
183
|
+
|
|
177
184
|
Set `ResizableRegion`'s `--kui-resizable-region-background` for an inline
|
|
178
|
-
surface.
|
|
179
|
-
|
|
180
|
-
|
|
185
|
+
surface. An open descendant `PopupMenu` or Web Awesome dropdown automatically
|
|
186
|
+
releases clipping and raises the region on its public popup layer. Set
|
|
187
|
+
`contentOverflow="visible"` for other anchored content that must escape the
|
|
188
|
+
region. A collapsed region can place `restoreControl` in a top or bottom corner with
|
|
181
189
|
`restorePosition`, set its typed `restoreInset`, or use
|
|
182
190
|
`restorePlacement="inline"` for a control in normal flow.
|
|
183
191
|
|
|
@@ -194,21 +202,41 @@ whole label. `divider` owns a before or after separator. Set
|
|
|
194
202
|
`--kui-list-item-*` tokens control its row, icon, label, and trailing geometry
|
|
195
203
|
and color. `ListHeader` exposes `--kui-list-header-min-height`, title padding,
|
|
196
204
|
title minimum height, and border-width tokens for section density.
|
|
205
|
+
For a filled command list, set `--kui-list-item-background` and
|
|
206
|
+
`--kui-list-item-border` on the list or row. The matching
|
|
207
|
+
`--kui-list-item-hover-border` and `--kui-list-item-selected-border` tokens
|
|
208
|
+
set state outlines without replacing ListItem CSS or neutralizing global
|
|
209
|
+
semantic border colors.
|
|
210
|
+
|
|
211
|
+
Use `ListItemLink` from `@kerfjs/ui/list-item` for a navigation row with a
|
|
212
|
+
real `href`. It shares `ListItem` content slots, density, selection, and row
|
|
213
|
+
geometry while rendering a native anchor. `external` opens a new tab with
|
|
214
|
+
`noopener noreferrer` and announces that behavior in the default accessible
|
|
215
|
+
name. Disabled and loading links omit `href` and leave the tab order. Use
|
|
216
|
+
`ListItem` for an application action dispatched through `action`.
|
|
197
217
|
|
|
198
218
|
Use `Toolbar responsive="trailing-priority"` for a collapsible search in the
|
|
199
219
|
trailing zone that should take a full second row when expanded. `responsiveAt`
|
|
200
220
|
chooses the compact or narrow container breakpoint. The leading identity stays
|
|
201
|
-
in the first row.
|
|
221
|
+
in the first row. Set `centerAlign="balanced"` when the center zone must sit on
|
|
222
|
+
the toolbar's midpoint despite unequal or empty side content; it gives the
|
|
223
|
+
leading and trailing zones equal tracks. `--kui-toolbar-leading-min-width`,
|
|
202
224
|
`--kui-toolbar-trailing-gap`, `--kui-toolbar-trailing-justify`, and the
|
|
203
225
|
`--kui-toolbar-*-padding-inline` zone tokens adjust local geometry without
|
|
204
226
|
selecting toolbar anatomy from application CSS.
|
|
227
|
+
Set `--kui-toolbar-inset: 0px` on an embedded Toolbar that should have no outer
|
|
228
|
+
padding while keeping its `--kui-toolbar-gap` between control zones. The token
|
|
229
|
+
also reduces its minimum height by the removed inset; safe-area compensation
|
|
230
|
+
still adds to the chosen inset on claimed edges.
|
|
205
231
|
|
|
206
232
|
For compact dialog copy, use `Text flush lineHeight="tight"`; block Text still
|
|
207
233
|
resets native margins. `ValueTable density="compact"` reduces row padding and
|
|
208
234
|
gap. Its `--kui-value-table-row-columns`, `--kui-value-table-row-padding-block`,
|
|
209
235
|
and `--kui-value-table-row-gap` tokens support a specific metadata layout.
|
|
210
|
-
Use `ToolbarText size="xsmall"` for a dense rail heading.
|
|
211
|
-
`
|
|
236
|
+
Use `ToolbarText size="xsmall"` for a dense rail heading. Use
|
|
237
|
+
`size="xlarge-fixed"` for a toolbar heading at the fixed 20px step; `xlarge`
|
|
238
|
+
retains the responsive page-title clamp. Pass `headingLevel` when the text is
|
|
239
|
+
a section landmark. A `TokenSearchField` editor can shrink to zero minimum width inside a narrow
|
|
212
240
|
group; set `--kui-token-search-editor-min-width` only when a wider editor is
|
|
213
241
|
required.
|
|
214
242
|
|
|
@@ -216,11 +244,25 @@ required.
|
|
|
216
244
|
- `TabBar` changes tabpanels and supports overflow/reorder; `SegmentedControl` chooses among a few compact views; `Select` handles a longer value list.
|
|
217
245
|
|
|
218
246
|
Use `AppTab presentation="icon-only"` with its `name` kept as the accessible
|
|
219
|
-
tab name
|
|
220
|
-
|
|
247
|
+
tab name. For segmented tabs that should show names in a wide reader and icons
|
|
248
|
+
in a narrower container, set `TabBar iconOnlyAt="wide"` (832px), `"narrow"`
|
|
249
|
+
(704px), or `"compact"` (448px), and give each segmented `AppTab` a leading
|
|
250
|
+
icon. The tablist's own width controls the switch; the visually hidden name
|
|
251
|
+
remains its accessible name. Use `labelMaxWidth` for an ellipsized visible name. Set `attention`
|
|
252
|
+
to color a tab's name with `--kui-app-tab-attention-color`. Set `dropTarget`
|
|
253
|
+
while an app drag is over a tab's content; the tab keeps its selection semantics
|
|
254
|
+
and uses the `--kui-app-tab-drop-target-*` tokens for its highlight. Set
|
|
255
|
+
`nameOverflow="visible"` when an inline loading treatment needs the full name
|
|
256
|
+
instead of the default ellipsis. A `TabBar` owns its
|
|
221
257
|
scrolling strip; its public `--kui-tab-bar-strip-*` tokens configure strip
|
|
222
258
|
height, spacing, border, radius, background, and scroll inset without styling
|
|
223
259
|
its internal classes. `--kui-tab-bar-trailing-flex` controls the trailing zone.
|
|
260
|
+
Set `pinned` on the first `AppTab` when that tab must remain visible as peers
|
|
261
|
+
scroll. It stays inside the tablist and keyboard order. Set the public
|
|
262
|
+
`--kui-app-tab-pinned-background` token if the surrounding surface differs from
|
|
263
|
+
the default; the pinned tab must cover peers as they scroll beneath it. Call
|
|
264
|
+
`wireTabBars` for keyboard selection and reorder behavior and its WebKit RTL
|
|
265
|
+
scroll correction.
|
|
224
266
|
|
|
225
267
|
- `StateBanner` persists beside affected work; `EmptyState` replaces absent content; `wa-callout` is contextual ecosystem content; `wa-toast` and `wa-toast-item` are transient and must not carry the only copy of important state.
|
|
226
268
|
|
|
@@ -232,11 +274,21 @@ stacked copy's spacing at an instance boundary.
|
|
|
232
274
|
|
|
233
275
|
For a compact `Select`, set `triggerWidth` to `"fit-content"`, `"max-content"`,
|
|
234
276
|
or `"fill"` and cap it with `--kui-select-trigger-max-width` when needed.
|
|
277
|
+
For a round icon-only toolbar trigger, set `selectedPresentation="icon-only"`
|
|
278
|
+
and `caret={false}`. The control keeps its accessible name, current choice help
|
|
279
|
+
tag, and keyboard-operated listbox; the default keeps the visible caret.
|
|
235
280
|
Custom `renderSelected` text inherits the control color by default; the
|
|
236
281
|
`--kui-select-selected-color`, `--kui-select-selected-font-size`, and
|
|
237
282
|
`--kui-select-selected-font-weight` tokens configure its typography. Plain
|
|
238
283
|
selected text stays on one ellipsized line when the trigger narrows.
|
|
239
284
|
|
|
285
|
+
For an unavailable entry, set `SelectChoice.disabled` and optionally
|
|
286
|
+
`disabledReason`; the option stays visible but cannot be chosen. A multiple
|
|
287
|
+
`Select` can opt in to `selectAllLabel` and `clearLabel` footer buttons.
|
|
288
|
+
Select all includes only enabled choices, Clear removes the selection, and
|
|
289
|
+
both report changes through the normal `input` and `change` events. The app
|
|
290
|
+
still owns the controlled `value` and localized action labels.
|
|
291
|
+
|
|
240
292
|
- `ResizableRegion` is an interactive controlled pane. `Grid` is the right answer for static equal-width columns; application CSS grid remains the answer for asymmetric or intrinsic tracks.
|
|
241
293
|
- A `ResizableRegion`'s content spans the whole region, like its separator. Give
|
|
242
294
|
it one child — normally a `Pane` — and that child fills the region, so the
|
|
@@ -271,6 +323,9 @@ selected text stays on one ellipsized line when the trigger narrows.
|
|
|
271
323
|
- `TokenSearchField` is a structured editor. A native input or `wa-input` is the right answer for ordinary text.
|
|
272
324
|
|
|
273
325
|
For common structured search, use `createTokenSearchModel` from `@kerfjs/ui/token-search-model`, pass the model to `TokenSearchField`, and register it under the field id in `wireTokenSearchFields(root, { models })`. Rules parse `name:value` expressions and provide suggestions; the model owns chips, selection, removal, clear, and an optional evaluation result. Omit `model` and `models` for full manual control.
|
|
326
|
+
`TokenSearchRule.suggest(input, state)` receives the unfinished value and current committed tokens, so a rule can omit values already selected. Existing one-argument suggestion callbacks continue to work.
|
|
327
|
+
For a sibling date picker or other app helper, call `model.commit(value)` while a `name:` prefix is active. It parses and commits that value for the active rule even when it is absent from suggestions, replacing the unfinished prefix text. Invalid values and calls without an active prefix leave the query unchanged; `choose(value)` remains restricted to suggested tokens.
|
|
328
|
+
To apply a saved search or restore a query programmatically, call `model.replace({ query, tokens })`. It publishes parsed state and rebuilds the DOM-owned editor text even when no chip changed. For a field without a model, change the field's `revision` prop when setting `query` yourself.
|
|
274
329
|
When one root contains both kinds of field, a registered model enables chip keyboard behavior only for its own field. Other fields keep native editing unless the root opts into `keyboard` with an application removal callback.
|
|
275
330
|
|
|
276
331
|
## Toolbar composition
|
|
@@ -338,7 +393,8 @@ menu.
|
|
|
338
393
|
|
|
339
394
|
Nested decisions use an item with `submenu`. Children keep their own actions,
|
|
340
395
|
`attributes` metadata, icons, `checked` state, disabled state and
|
|
341
|
-
`disabledReason` tooltip.
|
|
396
|
+
`disabledReason` tooltip. Nested `heading` and `divider` entries group those
|
|
397
|
+
commands without entering keyboard navigation. `tone: 'danger'` maps to the Web Awesome destructive
|
|
342
398
|
variant. A parent can sit among ordinary commands and dividers, so the same
|
|
343
399
|
items shape covers single-line and batch actions; compute each batch child's
|
|
344
400
|
`disabled` state from the current selection.
|
|
@@ -349,8 +405,11 @@ items shape covers single-line and batch actions; compute each batch child's
|
|
|
349
405
|
items={[
|
|
350
406
|
{ label: 'Copy reference', action: 'copy-reference', attributes: { 'data-item-id': lineId } },
|
|
351
407
|
{ label: 'Decide', submenu: [
|
|
408
|
+
{ kind: 'heading', label: 'Review' },
|
|
352
409
|
{ label: 'Approve', action: 'decide', checked: current === 'approve', attributes: { 'data-item-id': lineId, 'data-decision': 'approve' } },
|
|
353
410
|
{ label: 'Reject', action: 'decide', tone: 'danger', disabled: needsPrice, disabledReason: needsPrice ? 'Add a price first' : undefined, attributes: { 'data-item-id': lineId, 'data-decision': 'reject' } },
|
|
411
|
+
{ kind: 'divider' },
|
|
412
|
+
{ label: 'Other…', action: 'choose-other' },
|
|
354
413
|
] },
|
|
355
414
|
{ kind: 'divider' },
|
|
356
415
|
{ label: 'Remove', action: 'remove', tone: 'danger' },
|
|
@@ -421,6 +480,28 @@ forks the package anatomy and spacing contract.
|
|
|
421
480
|
</aside>
|
|
422
481
|
```
|
|
423
482
|
|
|
483
|
+
## Removable tags
|
|
484
|
+
|
|
485
|
+
Use `Chip` when a short tag has a remove action. `removeAction` becomes the
|
|
486
|
+
native button's `data-action`; `removeLabel` must name the specific tag for
|
|
487
|
+
assistive technology. Use `itemId` for the application's delegated handler.
|
|
488
|
+
The application updates its tag list after the action. `size="compact"` uses a
|
|
489
|
+
20px chip with a 16px remove button, and `disabled` disables removal. Tone,
|
|
490
|
+
appearance, and shape use the same semantic choices as `Badge`; use `Badge`
|
|
491
|
+
when no removal is needed and the content is status or count metadata.
|
|
492
|
+
|
|
493
|
+
```tsx
|
|
494
|
+
<Chip
|
|
495
|
+
size="compact"
|
|
496
|
+
tone="brand"
|
|
497
|
+
itemId={tag.id}
|
|
498
|
+
removeAction="remove-tag"
|
|
499
|
+
removeLabel={`Remove ${tag.name} tag`}
|
|
500
|
+
>
|
|
501
|
+
{tag.name}
|
|
502
|
+
</Chip>
|
|
503
|
+
```
|
|
504
|
+
|
|
424
505
|
## Web Awesome overlap policy
|
|
425
506
|
|
|
426
507
|
Web Awesome catalog coverage means supported and themed, not preferred. Import
|
|
@@ -437,7 +518,7 @@ replaces it (`PopupMenu` renders `wa-dropdown`; `Select` renders `wa-select` /
|
|
|
437
518
|
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
438
519
|
| `wa-button`, `wa-dropdown`, `wa-dropdown-item` | Use buttons for actions and `PopupMenu` for a command menu, never raw dropdown markup. Use `ListItem` for a navigation row and `Select` for a value. |
|
|
439
520
|
| `wa-button-group` | Use only for exceptional grouped actions; use `SegmentedControl` for one-of-many selection. |
|
|
440
|
-
| `wa-input`, `wa-tag` | Use for
|
|
521
|
+
| `wa-input`, `wa-tag` | Use `Chip` for removable or disabled tags; use `TokenSearchField` only when text and ordered filter tokens form one editor. |
|
|
441
522
|
| `wa-select`, `wa-option` | Use `Select`, which owns Kerf spacing, controlled rendering, icon stability, and explicit registration. |
|
|
442
523
|
| `wa-tab-group`, `wa-tab`, `wa-tab-panel` | Use `TabBar`/`AppTab` for application tabs or `SegmentedControl` for compact local views. |
|
|
443
524
|
| `wa-icon` | Use `LucideIcon` in application UI. |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="210.3" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="208.3" height="42" rx="11"/></clipPath><filter id="sh2" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct3"><rect x="38.7" y="36" width="35.3" height="12"/></clipPath><clipPath id="ct4"><rect x="114.1" y="36" width="22" height="12"/></clipPath><clipPath id="ct5"><rect x="168.5" y="36" width="50.8" height="12"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="210.3" height="44" rx="12" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="209" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/></g><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><rect x="22" y="23" width="68.8" height="40" rx="10" fill="rgba(0,0,0,0.5)" filter="url(#sh2)"/><rect x="22" y="22" width="68.8" height="40" rx="10" fill="rgb(28,28,30)"/><rect x="22.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="38.7" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(138,203,255)">Board</text><rect x="91.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="114.13" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="210.3" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="208.3" height="42" rx="11"/></clipPath><filter id="sh2" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct3"><rect x="38.7" y="36" width="35.3" height="12"/></clipPath><clipPath id="ct4"><rect x="114.1" y="36" width="22" height="12"/></clipPath><clipPath id="ct5"><rect x="168.5" y="36" width="50.8" height="12"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="210.3" height="44" rx="12" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="209" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/></g><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><rect x="22" y="23" width="68.8" height="40" rx="10" fill="rgba(0,0,0,0.5)" filter="url(#sh2)"/><rect x="22" y="22" width="68.8" height="40" rx="10" fill="rgb(28,28,30)"/><rect x="22.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="38.7" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(138,203,255)">Board</text><rect x="91.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="114.13" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(245,245,247)">List</text><rect x="160.5" y="22.5" width="67" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="168.5" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(245,245,247)">Timeline</text></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="210.3" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="208.3" height="42" rx="11"/></clipPath><filter id="sh2" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct3"><rect x="38.7" y="36" width="35.3" height="12"/></clipPath><clipPath id="ct4"><rect x="114.1" y="36" width="22" height="12"/></clipPath><clipPath id="ct5"><rect x="168.5" y="36" width="50.8" height="12"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="210.3" height="44" rx="12" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="209" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/></g><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><rect x="22" y="23" width="68.8" height="40" rx="10" fill="rgba(0,0,0,0.14)" filter="url(#sh2)"/><rect x="22" y="22" width="68.8" height="40" rx="10" fill="rgb(255,255,255)"/><rect x="22.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="38.7" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(12,98,243)">Board</text><rect x="91.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="114.13" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="210.3" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="208.3" height="42" rx="11"/></clipPath><filter id="sh2" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct3"><rect x="38.7" y="36" width="35.3" height="12"/></clipPath><clipPath id="ct4"><rect x="114.1" y="36" width="22" height="12"/></clipPath><clipPath id="ct5"><rect x="168.5" y="36" width="50.8" height="12"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="210.3" height="44" rx="12" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="209" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/></g><g clip-path="url(#cp0)"><g clip-path="url(#ov1)"><rect x="22" y="23" width="68.8" height="40" rx="10" fill="rgba(0,0,0,0.14)" filter="url(#sh2)"/><rect x="22" y="22" width="68.8" height="40" rx="10" fill="rgb(255,255,255)"/><rect x="22.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="38.7" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(12,98,243)">Board</text><rect x="91.5" y="22.5" width="68" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="114.13" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(29,29,31)">List</text><rect x="160.5" y="22.5" width="67" height="39" rx="9.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="168.5" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(29,29,31)">Timeline</text></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="141.4" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="139.4" height="42" rx="21"/></clipPath><clipPath id="ct2"><rect x="31.5" y="36.5" width="21.1" height="11"/></clipPath><filter id="sh3" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct4"><rect x="70" y="36.5" width="30.3" height="11"/></clipPath><clipPath id="ct5"><rect x="116.3" y="36.5" width="35.1" height="11"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="141.4" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="140" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="31.47" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="141.4" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="139.4" height="42" rx="21"/></clipPath><clipPath id="ct2"><rect x="31.5" y="36.5" width="21.1" height="11"/></clipPath><filter id="sh3" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct4"><rect x="70" y="36.5" width="30.3" height="11"/></clipPath><clipPath id="ct5"><rect x="116.3" y="36.5" width="35.1" height="11"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="141.4" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="20.5" y="20.5" width="140" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="31.47" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(245,245,247)">Day</text><rect x="62" y="23" width="46.3" height="40" rx="20" fill="rgba(0,0,0,0.5)" filter="url(#sh3)"/><rect x="62" y="22" width="46.3" height="40" rx="20" fill="rgb(28,28,30)"/><rect x="62.5" y="22.5" width="45" height="39" rx="19.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><text x="70" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(138,203,255)">Week</text><rect x="108.5" y="22.5" width="50" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="116.28" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(245,245,247)">Month</text></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="141.4" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="139.4" height="42" rx="21"/></clipPath><clipPath id="ct2"><rect x="31.5" y="36.5" width="21.1" height="11"/></clipPath><filter id="sh3" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct4"><rect x="70" y="36.5" width="30.3" height="11"/></clipPath><clipPath id="ct5"><rect x="116.3" y="36.5" width="35.1" height="11"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="141.4" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="140" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="31.47" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 460 88" width="460" height="88"><defs><clipPath id="cp0"><rect x="20" y="20" width="141.4" height="44"/></clipPath><clipPath id="ov1"><rect x="21" y="21" width="139.4" height="42" rx="21"/></clipPath><clipPath id="ct2"><rect x="31.5" y="36.5" width="21.1" height="11"/></clipPath><filter id="sh3" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="1.5"/></filter><clipPath id="ct4"><rect x="70" y="36.5" width="30.3" height="11"/></clipPath><clipPath id="ct5"><rect x="116.3" y="36.5" width="35.1" height="11"/></clipPath></defs><g clip-path="url(#cp0)"><rect x="20" y="20" width="141.4" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="20.5" y="20.5" width="140" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov1)"><rect x="22.5" y="22.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="31.47" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(29,29,31)">Day</text><rect x="62" y="23" width="46.3" height="40" rx="20" fill="rgba(0,0,0,0.14)" filter="url(#sh3)"/><rect x="62" y="22" width="46.3" height="40" rx="20" fill="rgb(255,255,255)"/><rect x="62.5" y="22.5" width="45" height="39" rx="19.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><text x="70" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(12,98,243)">Week</text><rect x="108.5" y="22.5" width="50" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><text x="116.28" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="11" font-weight="650" fill="rgb(29,29,31)">Month</text></g></g></svg>
|