@kerfjs/ui 5.0.0-beta.46 → 5.0.0-beta.48
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/ai/component-catalog-v2-overrides.json +12 -0
- package/ai/component-catalog-v2.json +36 -60
- package/ai/component-catalog.json +54 -134
- package/ai/public-api-signatures-v1.md +12 -3
- package/ai/skill.md +2 -2
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/catalog.js +5 -20
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-SE7MQMW7.js → chunk-GYGM363P.js} +2 -2
- package/dist/{chunk-SE7MQMW7.js.map → chunk-GYGM363P.js.map} +1 -1
- package/dist/chunk-XKFRMGMW.js +31 -0
- package/dist/chunk-XKFRMGMW.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/list-header.js +1 -1
- package/dist/styles/catalog.css +5 -3
- package/dist/styles/text.css +16 -0
- package/dist/styles/webawesome.css +61 -0
- package/dist/text.d.ts +11 -2
- package/dist/text.js +1 -1
- package/docs/component-selection.md +36 -36
- package/docs/examples/command-palette-adapter.tsx +1 -1
- package/docs/layout.md +8 -0
- package/docs/ux-demo.md +6 -5
- package/docs/webawesome-theme.md +21 -5
- package/llms.txt +10 -3
- package/package.json +1 -1
- package/ux-demo/recipes/app-shell.tsx +2 -2
- package/ux-demo/recipes/collapsible-sidebar.tsx +2 -2
- package/ux-demo/recipes/compact-toolbar.tsx +1 -1
- package/ux-demo/recipes/composer-form.tsx +1 -1
- package/ux-demo/recipes/list-detail-dialog.tsx +1 -2
- package/ux-demo/recipes/list-workspace-states.tsx +1 -1
- package/ux-demo/recipes/loading-inspector.tsx +2 -6
- package/ux-demo/recipes/navigation-sidebar.tsx +2 -2
- package/ux-demo/recipes/navigation-stack.tsx +2 -4
- package/ux-demo/recipes/workspace-header.tsx +2 -5
- package/dist/chunk-QM4GQ7W3.js +0 -17
- package/dist/chunk-QM4GQ7W3.js.map +0 -1
|
@@ -116,42 +116,42 @@ an upstream component or recipe request.
|
|
|
116
116
|
|
|
117
117
|
## Problem-to-component matrix
|
|
118
118
|
|
|
119
|
-
| Interface need | Use when | Do not use when; nearest alternative | Required wiring | Application owns | Import
|
|
120
|
-
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
121
|
-
| Icon — `LucideIcon` | A decorative or explicitly labeled Lucide-compatible icon belongs in app UI. | Do not use an icon as the only name of an unfamiliar action; add visible or accessible text. Prefer it over Web Awesome `wa-icon`. | None. | Icon choice and meaningful label. | `@kerfjs/ui/lucide-icon`
|
|
122
|
-
| Disclosure indicator — `DisclosureArrow` | A control needs one animated 18px root-scaled visual for open and closed state, including configurable directions or a replacement icon. | Do not use it as the interactive control or accessible name; place it inside the button or control that exposes expanded state. | Pass the controlled `open` state, render it inside the owning control, author replacement icon content facing right before transforms, and override `--kui-disclosure-arrow-size` only when another visual size is required. Direction changes use the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. | Open state, interaction, accessible name, size override, replacement glyph, direction choices, and shortest-path rotation. | `@kerfjs/ui/disclosure-arrow`
|
|
123
|
-
| Application toolbar or heading — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar or a page/panel/dialog heading. | Do not add bespoke heading geometry or a private wrapper; use the same zone contract everywhere. | Put identity/title text directly in a zone as `ToolbarText`; group controls and icon tiles in `ToolbarControlGroup`. | Actions, command availability, responsive relocation, state, and supporting copy below a heading. | `@kerfjs/ui/toolbar`
|
|
124
|
-
| Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained/borderless chrome, compact/tight geometry, icon/text/mixed/avatar anatomy, selected treatment, or nested dropdown sizing. | Do not use it merely to align unrelated buttons; use Toolbar's named `SafeHtml` prop slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; declare typed content and appearance instead of overriding descendants or `::part(base)`; use `avatarImage` instead of inserting an `img` (single groups paint the outer group; multi-button groups paint the pressed highlight); use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group`
|
|
125
|
-
| Floating controls over content — `FloatingToolbar` | A small cluster of controls (e.g. a drawer restore) must float over scrolling content — distinct and forced-dark — inside a positioned container. | Do not use it for a primary page or panel toolbar (use `Toolbar`), or for anything that must sit above dialogs/overlays — it is not top-layer. | Compose `ToolbarControlGroup`s and delegate their actions; the app owns visibility and position. | Controls, visibility, and position. | `@kerfjs/ui/floating-toolbar`
|
|
126
|
-
| 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`. | 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`
|
|
127
|
-
| Semantic heading or paragraph — `Text` | Ordinary application copy needs native `h1`–`h6` or `p` semantics plus
|
|
128
|
-
| 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`
|
|
129
|
-
| 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`
|
|
130
|
-
| 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`
|
|
131
|
-
| 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. Do not shrink its 44px action target to the 18px visual. 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`
|
|
132
|
-
| Inset self-bordered control — `ListInsetControl` | A control that owns its own border and padding but no outer margin (a search input, a `SegmentedControl`) must line up inside a `.kui-content` list with the standard 8px inline margins and stretch to fill the row. | Do not wrap a `.kui-content-item` or a `ListItem`/`ListHeader` that already owns its inline margin — that double-insets it. Do not add ad-hoc `margin`/`padding` around a bare control to align it; use this instead. | Place the self-bordered control(s) as children; they stretch to fill. It applies only the inline margin, flex stretch, and 8px gap — the child owns its own border and padding. | The control(s), their state, and action wiring. | `@kerfjs/ui/list-inset-control`
|
|
133
|
-
| Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. Pass `horizontalOnly` to keep that horizontal inset but drop the vertical margin, border, and padding for tight text layout. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text`
|
|
134
|
-
| Application column — `Pane` | A sidebar, main area, inspector, or dialog needs shared vertical header/content/footer organization, one scroll owner, and optional edge separators. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Import `Pane`, use `children` for its homogeneous primary content and the named `SafeHtml` prop slots `header`/`footer` for optional fixed chrome, then opt into only the needed logical-edge separators; add `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, responsive relocation, pane visibility state, slot semantics, labels, and separator placement. | `@kerfjs/ui/pane`
|
|
135
|
-
| One-pane navigation — `NavStack` | A compact flow pushes into details while keeping earlier views mounted, or a single-pane screen needs the same stable layout contract. | Do not use it when list and detail should remain visible together; use `SplitView`. Do not use it alone for co-equal top-level destinations; use one stack per `TabScaffold` tab. | Keep the ordered view array controlled, put view-specific bottom chrome on each view (or use the component fallback), import its CSS explicitly, and call `wireNavStack` for back delegation, content-slide/chrome-cross-fade transitions, and focus move/restore. Mark a preferred initial target with `data-nav-focus` when DOM order is insufficient. | View keys/content/titles, push and pop actions, preferred initial focus targets, and per-view or persistent bottom toolbar content. | `@kerfjs/ui/nav-stack`
|
|
136
|
-
| Responsive list-detail — `SplitView` | A primary list and related detail belong together on roomy devices but become a one-pane drill-down on compact devices. | Do not use it for a single linear flow or a multi-panel editor shell. | Provide controlled selection/detail state and device class; opt into resize wiring only when the separator is user adjustable. | Selection, detail content, compact back action, device policy, and optional persisted width. | `@kerfjs/ui/split-view`
|
|
137
|
-
| Compact top-level destinations — `TabScaffold` | A handset or portrait-tablet app has two to five co-equal destinations whose scenes and nested navigation must remain mounted across switches. | Do not use it for document tabs, reorderable work items, or a desktop navigation rail. | Keep the active id controlled, import its CSS explicitly, and call `wireTabScaffold`; commonly place one `NavStack` in each tab scene. | Destination definitions, active id, routing, persistence, and roomy-device replacement. | `@kerfjs/ui/tab-scaffold`
|
|
138
|
-
| Desktop multi-panel workspace — `Workbench` | A desktop-class tool needs a central work area plus independently collapsible navigator, inspector, or console regions. | Do not shrink the full shell onto compact devices or use it for one standalone panel. | Render only the required rails/drawer, keep collapse state controlled, and replace peripheral regions with stacks or overlays below desktop sizes. | Panel presence/content, collapsed states, sizes, persistence, responsive replacement, and controls. | `@kerfjs/ui/workbench`
|
|
139
|
-
| Standalone rail or drawer — `CollapsiblePanel` | One left/right rail or bottom drawer needs controlled collapse without adopting the complete `Workbench` shell. | Do not use it for several coordinated workspace panels or retain an empty icon-only rail while collapsed. | Pair it with `CollapsiblePanelToggle`; call `wireSidebar` for focus transfer, Escape/backdrop dismissal, compact overlay trapping, and persistence integration. | Panel content/size, collapsed state, toggle placement, persistence, and compact policy. | `@kerfjs/ui/collapsible-panel`
|
|
140
|
-
| Lowered content surface — `SunkenPanel` | A main work area or nested content group needs one visually lowered surface with a compact inset and vertical stack. | Do not use it merely to add padding, as a replacement for `Pane` anatomy, or around children that already own the same outer surface. | Compose the application-owned content as children, choose the default `rounded` shape or `square` for a flush edge-to-edge area, and pass `ariaLabel` only when the surface is a distinct named region. | Region semantics, accessible name, shape, scroll ownership, child ordering, and content. | `@kerfjs/ui/sunken-panel`
|
|
141
|
-
| Menu composition | Navigation sections need full-size rows and the same content-item geometry as every other pane. | Do not add sidebar-specific wrapper padding, shrink targets to icon size, nest an interactive trailing control in `ListItem`, or use a chevron on a row that does not disclose content. Use ordinary links for a different navigation contract. | Compose `ListHeader`, `ListItem`, and `ListActionRow` in `.kui-content`; use `ListHeader` toggle mode with real controlled content, and use `.kui-content-item` for other surfaces plus a pane footer for toolbar actions. | Information architecture, disclosure content and state, responsive drawer/shell behavior, and token overrides. | `@kerfjs/ui/layout.css`
|
|
142
|
-
| Resizable application pane — `ResizableRegion`, `clampRegionSize`, `resizeRegionFromPointer` | A controlled split pane needs the Kerf separator, collapse state, pointer plus keyboard resizing, or a product-specific decorative grip. | Do not use it for a static two-column layout; use CSS grid. Prefer it over Web Awesome `wa-split-panel` unless that component's distinct API is required. Keep `handleIcon` noninteractive. | Call `wireResizableRegions` from `@kerfjs/ui/wire-resizable-regions` once and retain its disposer. | Size signal, min/max policy, collapse policy, persistence, and optional decorative handle icon. | `@kerfjs/ui/resizable-region`
|
|
143
|
-
| One application tab — `AppTab` | A controlled app tab needs selection, close, drag, leading/trailing anatomy, compact/segmented/icon-only presentation, label truncation, safe domain metadata, or a product-specific close glyph. | Do not render it alone or use it for a small settings choice; compose in `TabBar`, or use `SegmentedControl`. Keep `closeIcon` noninteractive. | Compose in `TabBar`; let `wireTabBars` manage interaction. Put only domain `data-*` values in `rootAttributes`; use typed appearance props instead of descendant CSS. | Tab identity, order, selection, close policy, content, domain metadata values, and outer placement. | `@kerfjs/ui/app-tab`
|
|
144
|
-
| Application tab strip — `TabBar`, `wireTabBars`, `reorderTabs` | Tabs switch page regions and may overflow, close, reorder, fill a segmented inspector strip, or sit beside a trailing action. | Do not use it for a compact local view toggle; use `SegmentedControl`. Do not use it for a long choice list; use `Select`. Prefer it over Web Awesome `wa-tab-group`, `wa-tab`, and `wa-tab-panel` for Kerf app tabs. | Call `wireTabBars` once, retain the disposer, and apply `onReorder` synchronously; `reorderTabs` is the default array helper. Choose typed presentation/allocation props while the parent owns outer placement. | Ordered tabs, selection, panels, routing, closing, persistence, and outer placement. | `@kerfjs/ui/tab-bar` plus `@kerfjs/ui/wire-tab-bars`
|
|
145
|
-
| Panel, dialog, or page heading — `Toolbar` + `ToolbarText` | A panel, dialog, or page needs an extra-large title, optional icon, grouped trailing actions, and optional supporting copy. | Do not add a private heading wrapper or bespoke layout. The toolbar supplies structure, not modal behavior; use an application overlay or Web Awesome `wa-dialog` for that behavior. | Connect title/supporting-copy ids to the host, group controls, and delegate actions. **For a page or view title set `headingLevel` (usually `1`)** on `ToolbarText`; omit it for a dialog title referenced by `aria-labelledby`. | Open state, focus lifecycle, dismissal, controls, ids, copy, and heading level. | `@kerfjs/ui/toolbar` + `@kerfjs/ui/toolbar-text`
|
|
146
|
-
| Dialog or popup geometry — `DialogSurface`, `PopupSurface` | Recurring Web Awesome dialogs need standard sizes/presentations/body/footer insets, or dropdown menus need list-compatible inset ownership. | Do not use these wrappers as generic layout or to replace native dialog/dropdown behavior. Avoid consumer `::part()` overrides and do not stack a dialog body inset around list-owned child geometry. | Wrap one `wa-dialog` or `wa-dropdown`; choose the typed geometry while retaining native labeling, open state, focus, dismissal, and menu semantics. Compose a dialog body as a `List` by default, use `bodyInset="none"` when its children own list geometry, and wrap bare prose in `ListInsetText`. | State, focus lifecycle, dismissal, labels, content, and outer placement. | `@kerfjs/ui/surface-scaffold`
|
|
147
|
-
| Key/value facts — `ValueTable`, `ValueTableRow` | Read-only labels and values form a semantic definition list, optionally with a leading icon. | Do not use it for editable form fields or a row/column data grid; use native form or table semantics. | Compose typed `ValueTableRow` entries; pass `icon` when a 24px leading icon adds useful context. | Values, formatting, icon meaning, and empty/loading policy. | `@kerfjs/ui/value-table`
|
|
148
|
-
| Indeterminate activity — `LoadingSpinner` | A Kerf surface needs compact, labeled or decorative indeterminate progress. | Do not use it for known progress; use Web Awesome `wa-progress-bar` or `wa-progress-ring`. Direct Web Awesome UI may use `wa-spinner`; do not mix spinner systems within one surface. | None; pass a label when the spinner conveys status. | Loading lifecycle and adjacent status copy. | `@kerfjs/ui/loading-spinner`
|
|
149
|
-
| Loading placeholder — `Skeleton` + a component's `placeholder` prop | A value or a whole component is still loading and should hold its space as a subtle, unanimated block, keeping the layout stable — an inspector or detail view rendering its real chrome with per-record values absent. | Do not use it for known progress (use `LoadingSpinner`), do not animate it, and do not hand-rebuild a component's empty state — set `placeholder` on the component instead. Prefer it over `wa-skeleton`, which the pure-Kerf primitives avoid to stay Web-Awesome-free. | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render skeletons in its value slots with interactivity disabled; use the standalone `Skeleton` for a custom slot. | Loading lifecycle, which slots are unknown, and announcing the loading region. | `@kerfjs/ui/skeleton`
|
|
150
|
-
| Value selection — `Select` | A controlled form, toolbar, or compact navigation value comes from a moderate or long choice list, possibly grouped, icon-bearing, icon-only when closed, or truncating. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once for registration and current-request animation ownership; listen for standard input/change events. Do not add consumer popup timing or positioning repairs. Use typed presentation props rather than consumer `::part()` overrides; let the parent own placement. | Controlled value, validation, choices, domain mapping, and outer placement. | `@kerfjs/ui/select`
|
|
151
|
-
| Small exclusive choice — `SegmentedControl` | A few visible choices switch a compact view or setting, with toolbar, rounded, or pill presentation. | Do not use it for tabpanel semantics; use `TabBar`. Do not use it for many choices; use `Select`. Prefer it over `wa-button-group` when the controls select one value. | Delegate its action, read `data-segment-value`, update `value`, and rerender. | Controlled value, labels, action, and persistence. | `@kerfjs/ui/segmented-control`
|
|
152
|
-
| Structured search editor — `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields` | Free text and ordered, editable, removable filter tokens share one searchbox; enable `collapsible` when an empty, unfocused field should reduce to one iconic action, standalone or in a toolbar group. | Do not use it for ordinary text entry; use a native input or Web Awesome `wa-input`. Do not use it when filters belong in separate form controls. | Read DOM-owned text on input, empty `textContent` on clear, and use `placeTokenSearchCaret` after explicit controlled focus changes. Call `wireTokenSearchFields` from `@kerfjs/ui/wire-token-search-fields` once so Enter submits without adding a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. In `collapsible` mode it also 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 signal on the returned handle (`handle.expanded(id)`) or adopt your own via `collapsible.signals`, and opt out per behavior only when the app must own it. | Parsing, suggestions, tokens, query execution, results, announcements, and — only if overriding the default — the collapsible `expanded` signal. | `@kerfjs/ui/token-search-field`
|
|
153
|
-
| Persistent inline status — `StateBanner` | A neutral, info, pop, success, warning, or danger message belongs next to the affected work; pop highlights featured or novel content without implying status. | Do not use pop as a success, warning, or danger substitute. Do not use StateBanner for a no-content screen; use `EmptyState`. Do not use it for transient confirmation; use a toast. Web Awesome `wa-callout` is the ecosystem alternative for Web Awesome-owned content. | Delegate an optional action; choose alert urgency only for attention-requiring failure. Use the optional tone-tinted `badge` for a terse count or status beside the title, not as the only expression of meaning. | State mapping, message lifetime, retry/action behavior, badge content, and copy. | `@kerfjs/ui/state-banner`
|
|
154
|
-
| Empty or busy content area — `EmptyState` | A content region has no items, cannot proceed, or is loading and needs explanation plus an optional action. | Do not use it for an inline status update; use `StateBanner`. Do not use it for transient success; use `wa-toast`/`wa-toast-item` or the application's toast system. | Delegate its optional action; it composes `LoadingSpinner` when busy. | Empty/busy policy, recovery action, illustration, and copy. | `@kerfjs/ui/empty-state`
|
|
119
|
+
| Interface need | Use when | Do not use when; nearest alternative | Required wiring | Application owns | Import | Recipe |
|
|
120
|
+
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
121
|
+
| Icon — `LucideIcon` | A decorative or explicitly labeled Lucide-compatible icon belongs in app UI. | Do not use an icon as the only name of an unfamiliar action; add visible or accessible text. Prefer it over Web Awesome `wa-icon`. | None. | Icon choice and meaningful label. | `@kerfjs/ui/lucide-icon` | [Accessibility](./accessibility.md#shared-rules) |
|
|
122
|
+
| Disclosure indicator — `DisclosureArrow` | A control needs one animated 18px root-scaled visual for open and closed state, including configurable directions or a replacement icon. | Do not use it as the interactive control or accessible name; place it inside the button or control that exposes expanded state. | Pass the controlled `open` state, render it inside the owning control, author replacement icon content facing right before transforms, and override `--kui-disclosure-arrow-size` only when another visual size is required. Direction changes use the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. | Open state, interaction, accessible name, size override, replacement glyph, direction choices, and shortest-path rotation. | `@kerfjs/ui/disclosure-arrow` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
123
|
+
| Application toolbar or heading — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar or a page/panel/dialog heading. | Do not add bespoke heading geometry or a private wrapper; use the same zone contract everywhere. | Put identity/title text directly in a zone as `ToolbarText`; group controls and icon tiles in `ToolbarControlGroup`. | Actions, command availability, responsive relocation, state, and supporting copy below a heading. | `@kerfjs/ui/toolbar` | [Toolbar composition](../README.md#component-subpaths) |
|
|
124
|
+
| Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained/borderless chrome, compact/tight geometry, icon/text/mixed/avatar anatomy, selected treatment, or nested dropdown sizing. | Do not use it merely to align unrelated buttons; use Toolbar's named `SafeHtml` prop slots or ordinary layout. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; declare typed content and appearance instead of overriding descendants or `::part(base)`; use `avatarImage` instead of inserting an `img` (single groups paint the outer group; multi-button groups paint the pressed highlight); use `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
125
|
+
| Floating controls over content — `FloatingToolbar` | A small cluster of controls (e.g. a drawer restore) must float over scrolling content — distinct and forced-dark — inside a positioned container. | Do not use it for a primary page or panel toolbar (use `Toolbar`), or for anything that must sit above dialogs/overlays — it is not top-layer. | Compose `ToolbarControlGroup`s and delegate their actions; the app owns visibility and position. | Controls, visibility, and position. | `@kerfjs/ui/floating-toolbar` | [Component subpaths](../README.md#component-subpaths) |
|
|
126
|
+
| 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`. | 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) |
|
|
127
|
+
| Semantic heading or paragraph — `Text` | Ordinary application copy needs native `h1`–`h6` or `p` semantics plus standard geometry, or a semantic quiet/danger tone, compact size, or monospace font. | 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`, or choose `h1`–`h6` from the document outline. 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) |
|
|
128
|
+
| 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) |
|
|
129
|
+
| 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) |
|
|
130
|
+
| 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) |
|
|
131
|
+
| 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. Do not shrink its 44px action target to the 18px visual. 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) |
|
|
132
|
+
| Inset self-bordered control — `ListInsetControl` | A control that owns its own border and padding but no outer margin (a search input, a `SegmentedControl`) must line up inside a `.kui-content` list with the standard 8px inline margins and stretch to fill the row. | Do not wrap a `.kui-content-item` or a `ListItem`/`ListHeader` that already owns its inline margin — that double-insets it. Do not add ad-hoc `margin`/`padding` around a bare control to align it; use this instead. | Place the self-bordered control(s) as children; they stretch to fill. It applies only the inline margin, flex stretch, and 8px gap — the child owns its own border and padding. | The control(s), their state, and action wiring. | `@kerfjs/ui/list-inset-control` | [Pane geometry](../README.md#component-subpaths) |
|
|
133
|
+
| Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. Pass `horizontalOnly` to keep that horizontal inset but drop the vertical margin, border, and padding for tight text layout. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text` | [Pane geometry](../README.md#component-subpaths) |
|
|
134
|
+
| Application column — `Pane` | A sidebar, main area, inspector, or dialog needs shared vertical header/content/footer organization, one scroll owner, and optional edge separators. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Import `Pane`, use `children` for its homogeneous primary content and the named `SafeHtml` prop slots `header`/`footer` for optional fixed chrome, then opt into only the needed logical-edge separators; add `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, responsive relocation, pane visibility state, slot semantics, labels, and separator placement. | `@kerfjs/ui/pane` | [Pane anatomy](./layout.md#anatomy) |
|
|
135
|
+
| One-pane navigation — `NavStack` | A compact flow pushes into details while keeping earlier views mounted, or a single-pane screen needs the same stable layout contract. | Do not use it when list and detail should remain visible together; use `SplitView`. Do not use it alone for co-equal top-level destinations; use one stack per `TabScaffold` tab. | Keep the ordered view array controlled, put view-specific bottom chrome on each view (or use the component fallback), import its CSS explicitly, and call `wireNavStack` for back delegation, content-slide/chrome-cross-fade transitions, and focus move/restore. Mark a preferred initial target with `data-nav-focus` when DOM order is insufficient. | View keys/content/titles, push and pop actions, preferred initial focus targets, and per-view or persistent bottom toolbar content. | `@kerfjs/ui/nav-stack` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
136
|
+
| Responsive list-detail — `SplitView` | A primary list and related detail belong together on roomy devices but become a one-pane drill-down on compact devices. | Do not use it for a single linear flow or a multi-panel editor shell. | Provide controlled selection/detail state and device class; opt into resize wiring only when the separator is user adjustable. | Selection, detail content, compact back action, device policy, and optional persisted width. | `@kerfjs/ui/split-view` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
137
|
+
| Compact top-level destinations — `TabScaffold` | A handset or portrait-tablet app has two to five co-equal destinations whose scenes and nested navigation must remain mounted across switches. | Do not use it for document tabs, reorderable work items, or a desktop navigation rail. | Keep the active id controlled, import its CSS explicitly, and call `wireTabScaffold`; commonly place one `NavStack` in each tab scene. | Destination definitions, active id, routing, persistence, and roomy-device replacement. | `@kerfjs/ui/tab-scaffold` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
138
|
+
| Desktop multi-panel workspace — `Workbench` | A desktop-class tool needs a central work area plus independently collapsible navigator, inspector, or console regions. | Do not shrink the full shell onto compact devices or use it for one standalone panel. | Render only the required rails/drawer, keep collapse state controlled, and replace peripheral regions with stacks or overlays below desktop sizes. | Panel presence/content, collapsed states, sizes, persistence, responsive replacement, and controls. | `@kerfjs/ui/workbench` | [Workbench](./workbench.md) |
|
|
139
|
+
| Standalone rail or drawer — `CollapsiblePanel` | One left/right rail or bottom drawer needs controlled collapse without adopting the complete `Workbench` shell. | Do not use it for several coordinated workspace panels or retain an empty icon-only rail while collapsed. | Pair it with `CollapsiblePanelToggle`; call `wireSidebar` for focus transfer, Escape/backdrop dismissal, compact overlay trapping, and persistence integration. | Panel content/size, collapsed state, toggle placement, persistence, and compact policy. | `@kerfjs/ui/collapsible-panel` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
140
|
+
| Lowered content surface — `SunkenPanel` | A main work area or nested content group needs one visually lowered surface with a compact inset and vertical stack. | Do not use it merely to add padding, as a replacement for `Pane` anatomy, or around children that already own the same outer surface. | Compose the application-owned content as children, choose the default `rounded` shape or `square` for a flush edge-to-edge area, and pass `ariaLabel` only when the surface is a distinct named region. | Region semantics, accessible name, shape, scroll ownership, child ordering, and content. | `@kerfjs/ui/sunken-panel` | [SunkenPanel](./sunken-panel.md) |
|
|
141
|
+
| Menu composition | Navigation sections need full-size rows and the same content-item geometry as every other pane. | Do not add sidebar-specific wrapper padding, shrink targets to icon size, nest an interactive trailing control in `ListItem`, or use a chevron on a row that does not disclose content. Use ordinary links for a different navigation contract. | Compose `ListHeader`, `ListItem`, and `ListActionRow` in `.kui-content`; use `ListHeader` toggle mode with real controlled content, and use `.kui-content-item` for other surfaces plus a pane footer for toolbar actions. | Information architecture, disclosure content and state, responsive drawer/shell behavior, and token overrides. | `@kerfjs/ui/layout.css` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
142
|
+
| Resizable application pane — `ResizableRegion`, `clampRegionSize`, `resizeRegionFromPointer` | A controlled split pane needs the Kerf separator, collapse state, pointer plus keyboard resizing, or a product-specific decorative grip. | Do not use it for a static two-column layout; use CSS grid. Prefer it over Web Awesome `wa-split-panel` unless that component's distinct API is required. Keep `handleIcon` noninteractive. | Call `wireResizableRegions` from `@kerfjs/ui/wire-resizable-regions` once and retain its disposer. | Size signal, min/max policy, collapse policy, persistence, and optional decorative handle icon. | `@kerfjs/ui/resizable-region` | [ResizableRegion contract](./accessibility.md#resizableregion) |
|
|
143
|
+
| One application tab — `AppTab` | A controlled app tab needs selection, close, drag, leading/trailing anatomy, compact/segmented/icon-only presentation, label truncation, safe domain metadata, or a product-specific close glyph. | Do not render it alone or use it for a small settings choice; compose in `TabBar`, or use `SegmentedControl`. Keep `closeIcon` noninteractive. | Compose in `TabBar`; let `wireTabBars` manage interaction. Put only domain `data-*` values in `rootAttributes`; use typed appearance props instead of descendant CSS. | Tab identity, order, selection, close policy, content, domain metadata values, and outer placement. | `@kerfjs/ui/app-tab` | [Tabs contract](./accessibility.md#tabs) |
|
|
144
|
+
| Application tab strip — `TabBar`, `wireTabBars`, `reorderTabs` | Tabs switch page regions and may overflow, close, reorder, fill a segmented inspector strip, or sit beside a trailing action. | Do not use it for a compact local view toggle; use `SegmentedControl`. Do not use it for a long choice list; use `Select`. Prefer it over Web Awesome `wa-tab-group`, `wa-tab`, and `wa-tab-panel` for Kerf app tabs. | Call `wireTabBars` once, retain the disposer, and apply `onReorder` synchronously; `reorderTabs` is the default array helper. Choose typed presentation/allocation props while the parent owns outer placement. | Ordered tabs, selection, panels, routing, closing, persistence, and outer placement. | `@kerfjs/ui/tab-bar` plus `@kerfjs/ui/wire-tab-bars` | [Tabs contract](./accessibility.md#tabs) |
|
|
145
|
+
| Panel, dialog, or page heading — `Toolbar` + `ToolbarText` | A panel, dialog, or page needs an extra-large title, optional icon, grouped trailing actions, and optional supporting copy. | Do not add a private heading wrapper or bespoke layout. The toolbar supplies structure, not modal behavior; use an application overlay or Web Awesome `wa-dialog` for that behavior. | Connect title/supporting-copy ids to the host, group controls, and delegate actions. **For a page or view title set `headingLevel` (usually `1`)** on `ToolbarText`; omit it for a dialog title referenced by `aria-labelledby`. | Open state, focus lifecycle, dismissal, controls, ids, copy, and heading level. | `@kerfjs/ui/toolbar` + `@kerfjs/ui/toolbar-text` | [Toolbar headings](./accessibility.md#toolbar-headings) |
|
|
146
|
+
| Dialog or popup geometry — `DialogSurface`, `PopupSurface` | Recurring Web Awesome dialogs need standard sizes/presentations/body/footer insets, or dropdown menus need list-compatible inset ownership. | Do not use these wrappers as generic layout or to replace native dialog/dropdown behavior. Avoid consumer `::part()` overrides and do not stack a dialog body inset around list-owned child geometry. | Wrap one `wa-dialog` or `wa-dropdown`; choose the typed geometry while retaining native labeling, open state, focus, dismissal, and menu semantics. Compose a dialog body as a `List` by default, use `bodyInset="none"` when its children own list geometry, and wrap bare prose in `ListInsetText`. | State, focus lifecycle, dismissal, labels, content, and outer placement. | `@kerfjs/ui/surface-scaffold` | [Surface scaffolds](./surface-scaffold.md) |
|
|
147
|
+
| Key/value facts — `ValueTable`, `ValueTableRow` | Read-only labels and values form a semantic definition list, optionally with a leading icon. | Do not use it for editable form fields or a row/column data grid; use native form or table semantics. | Compose typed `ValueTableRow` entries; pass `icon` when a 24px leading icon adds useful context. | Values, formatting, icon meaning, and empty/loading policy. | `@kerfjs/ui/value-table` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
148
|
+
| Indeterminate activity — `LoadingSpinner` | A Kerf surface needs compact, labeled or decorative indeterminate progress. | Do not use it for known progress; use Web Awesome `wa-progress-bar` or `wa-progress-ring`. Direct Web Awesome UI may use `wa-spinner`; do not mix spinner systems within one surface. | None; pass a label when the spinner conveys status. | Loading lifecycle and adjacent status copy. | `@kerfjs/ui/loading-spinner` | [Accessibility](./accessibility.md#shared-rules) |
|
|
149
|
+
| Loading placeholder — `Skeleton` + a component's `placeholder` prop | A value or a whole component is still loading and should hold its space as a subtle, unanimated block, keeping the layout stable — an inspector or detail view rendering its real chrome with per-record values absent. | Do not use it for known progress (use `LoadingSpinner`), do not animate it, and do not hand-rebuild a component's empty state — set `placeholder` on the component instead. Prefer it over `wa-skeleton`, which the pure-Kerf primitives avoid to stay Web-Awesome-free. | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render skeletons in its value slots with interactivity disabled; use the standalone `Skeleton` for a custom slot. | Loading lifecycle, which slots are unknown, and announcing the loading region. | `@kerfjs/ui/skeleton` | [Accessibility](./accessibility.md#shared-rules) |
|
|
150
|
+
| Value selection — `Select` | A controlled form, toolbar, or compact navigation value comes from a moderate or long choice list, possibly grouped, icon-bearing, icon-only when closed, or truncating. | Do not use it for commands; use a real action menu. Do not use it for a small visible choice set; use `SegmentedControl`. Prefer it over direct `wa-select`, `wa-option`, or value-like `wa-dropdown`/`wa-dropdown-item` composition. | Import `@kerfjs/ui/select/register` once for registration and current-request animation ownership; listen for standard input/change events. Do not add consumer popup timing or positioning repairs. Use typed presentation props rather than consumer `::part()` overrides; let the parent own placement. | Controlled value, validation, choices, domain mapping, and outer placement. | `@kerfjs/ui/select` | [Web Awesome integration](../README.md#web-awesome-theme) |
|
|
151
|
+
| Small exclusive choice — `SegmentedControl` | A few visible choices switch a compact view or setting, with toolbar, rounded, or pill presentation. | Do not use it for tabpanel semantics; use `TabBar`. Do not use it for many choices; use `Select`. Prefer it over `wa-button-group` when the controls select one value. | Delegate its action, read `data-segment-value`, update `value`, and rerender. | Controlled value, labels, action, and persistence. | `@kerfjs/ui/segmented-control` | [SegmentedControl contract](./accessibility.md#segmentedcontrol) |
|
|
152
|
+
| Structured search editor — `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret`, `wireTokenSearchFields` | Free text and ordered, editable, removable filter tokens share one searchbox; enable `collapsible` when an empty, unfocused field should reduce to one iconic action, standalone or in a toolbar group. | Do not use it for ordinary text entry; use a native input or Web Awesome `wa-input`. Do not use it when filters belong in separate form controls. | Read DOM-owned text on input, empty `textContent` on clear, and use `placeTokenSearchCaret` after explicit controlled focus changes. Call `wireTokenSearchFields` from `@kerfjs/ui/wire-token-search-fields` once so Enter submits without adding a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. In `collapsible` mode it also 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 signal on the returned handle (`handle.expanded(id)`) or adopt your own via `collapsible.signals`, and opt out per behavior only when the app must own it. | Parsing, suggestions, tokens, query execution, results, announcements, and — only if overriding the default — the collapsible `expanded` signal. | `@kerfjs/ui/token-search-field` | [TokenSearchField contract](./accessibility.md#tokensearchfield) |
|
|
153
|
+
| Persistent inline status — `StateBanner` | A neutral, info, pop, success, warning, or danger message belongs next to the affected work; pop highlights featured or novel content without implying status. | Do not use pop as a success, warning, or danger substitute. Do not use StateBanner for a no-content screen; use `EmptyState`. Do not use it for transient confirmation; use a toast. Web Awesome `wa-callout` is the ecosystem alternative for Web Awesome-owned content. | Delegate an optional action; choose alert urgency only for attention-requiring failure. Use the optional tone-tinted `badge` for a terse count or status beside the title, not as the only expression of meaning. | State mapping, message lifetime, retry/action behavior, badge content, and copy. | `@kerfjs/ui/state-banner` | [Feedback accessibility](./accessibility.md#shared-rules) |
|
|
154
|
+
| Empty or busy content area — `EmptyState` | A content region has no items, cannot proceed, or is loading and needs explanation plus an optional action. | Do not use it for an inline status update; use `StateBanner`. Do not use it for transient success; use `wa-toast`/`wa-toast-item` or the application's toast system. | Delegate its optional action; it composes `LoadingSpinner` when busy. | Empty/busy policy, recovery action, illustration, and copy. | `@kerfjs/ui/empty-state` | [Feedback ownership](./component-contract.md#extracted-versus-application-specific) |
|
|
155
155
|
|
|
156
156
|
## Ambiguous choices
|
|
157
157
|
|
|
@@ -49,7 +49,7 @@ export function mountCommandPaletteAdapter(
|
|
|
49
49
|
data-command-query
|
|
50
50
|
/>
|
|
51
51
|
</div>
|
|
52
|
-
<Text
|
|
52
|
+
<Text class="kui-content-item" aria-live="polite">
|
|
53
53
|
{matches.length} matching commands
|
|
54
54
|
</Text>
|
|
55
55
|
<ul class="kui-content-item" aria-label="Matching commands">
|
package/docs/layout.md
CHANGED
|
@@ -129,11 +129,19 @@ typography remains available to the surrounding composition. Choose heading
|
|
|
129
129
|
levels from the document outline, not for visual size. Toolbar identity and
|
|
130
130
|
page-heading compositions continue to use `ToolbarText`.
|
|
131
131
|
|
|
132
|
+
Presentation is independent of the native element: use `tone="quiet"` for
|
|
133
|
+
supporting copy, `tone="danger"` for error or validation copy, `size="compact"`
|
|
134
|
+
for compact metadata, and `font="monospace"` for code or identifiers. These
|
|
135
|
+
finite props compose with each other and with every semantic `variant`; omit
|
|
136
|
+
them to inherit the surrounding color, size, and font.
|
|
137
|
+
|
|
132
138
|
```tsx
|
|
133
139
|
import { Text } from "@kerfjs/ui/text";
|
|
134
140
|
|
|
135
141
|
<Text variant="h2" id="details-title">Details</Text>;
|
|
136
142
|
<Text aria-describedby="details-title">Supporting copy</Text>;
|
|
143
|
+
<Text tone="quiet" size="compact">Updated yesterday</Text>;
|
|
144
|
+
<Text tone="danger" font="monospace">ERR_INVALID_ID</Text>;
|
|
137
145
|
```
|
|
138
146
|
|
|
139
147
|
## Spacer
|
package/docs/ux-demo.md
CHANGED
|
@@ -19,7 +19,7 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
19
19
|
- It imports public component subpaths, exercising their browser-selected reachable CSS rather than a catalog-only style path.
|
|
20
20
|
- The `ListActionRow` route demonstrates sibling primary/trailing native controls, independent disabled states, controlled selection, first-line leading-icon alignment for wrapped labels, and an application-owned native popover relationship without nesting controls. The `ListItem` route demonstrates the same multiline leading-icon anchor alongside its single-control navigation contract.
|
|
21
21
|
- The `AppTab` and `TabBar` routes are focused component specimens: AppTab shows its selected, compact, segmented, icon-only, truncation, placeholder, metadata, and close-icon axes inside the required tablist context; TabBar shows its rail, segmented, inspector, allocation, placement, and accessory-zone axes without application readouts. The separate `Application tabs composition` route demonstrates controlled selection, matching panel content, overflow, adding, closing, keyboard/pointer reordering, and application-owned ordering. The `ResizableRegion` route likewise replaces only the decorative handle glyph while retaining separator semantics and shared wiring.
|
|
22
|
-
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu,
|
|
22
|
+
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu, and feedback scenarios remain addressable alongside their subcomponents; the root opens the first Kerf component. The former aggregate Web Awesome theme specimen is intentionally omitted because its component families are covered by those focused routes.
|
|
23
23
|
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, recommendation, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Non-supported Web Awesome recommendations project to a visible `Discouraged` sidebar tag, with Popup as the deliberate conditional exception. Demo paths resolve to the matching `ui/ux-demo/demos/<id>.tsx` or `ui/ux-demo/recipes/*.tsx` file, or to `ui/ux-demo/webawesome-demos.tsx` for Web Awesome entries. `ui/ux-demo/main.tsx` owns only the catalog shell, shared state, routing, and interaction wiring. First-party component entries additionally derive `ui/src/<public-subpath>.tsx` from their canonical `delivery.browserImport` or opt-in `delivery.moduleImport`.
|
|
24
24
|
- Every detail footer groups compact `Demo source` and `Guidance` actions; first-party component details also expose `Component source`. Web Awesome details say `Integration guidance` to distinguish the local integration contract from the upstream component implementation. Each button retains its repository-relative path in the DOM for verification and uses a deploy-safe absolute GitHub blob URL with a contextual new-tab name; the demo does not depend on a local source server or add a package runtime export. At phone widths, the resource group and related-component selector stack as full-width rows, with any resource overflow contained locally so labels cannot overlap the selector or widen the document.
|
|
25
25
|
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. Catalog entries can supply short reusable trailing tags; the Web Awesome projection uses them to label exactly the 15 discouraged choices. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
@@ -31,12 +31,13 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
31
31
|
- The `DisclosureArrow` route renders the production 18px root-scaled default without a catalog-only size override. Its two native buttons independently control the default right-to-down chevron and a recognizable right-facing replacement arrow with left-to-up custom directions; both use shortest-path rotation and their names stay stable while `aria-expanded` communicates state. Browser coverage verifies the custom clockwise path, pointer and native keyboard activation, focus, narrow and 200%-zoom stacking with contained labels, consumer sizing, and the independent `.5` Web Awesome glyph scale retained by Kerf `Select`.
|
|
32
32
|
- A detail with relationships renders one content-fitted `Components` footer selector: `Uses` links to direct dependencies and `Used by` links to reverse dependents. Its popup owns the standard surface inset so headings and even long component names stay clear of the menu border. Choosing either navigates to that component's demo. The relationship group is absent when both sets are empty; no duplicate summary is rendered.
|
|
33
33
|
- Demo-only CSS supplies only the catalog shell and stages; component appearance stays in package CSS. Decorative chrome and Web Awesome controls share the same semantic system palette instead of carrying a separate demo identity.
|
|
34
|
-
- Scenarios use deterministic data and cover real variants, long content, disabled state, selection, progress, feedback, overlays, media, helpers, and stateful interactions.
|
|
34
|
+
- Scenarios use deterministic data and cover real variants, long content, disabled state, selection, progress, feedback, overlays, media, helpers, and stateful interactions. Individual Web Awesome action, form, layout, navigation, feedback, media, and helper routes provide focused theme specimens without a redundant aggregate route; ListItem and ListHeader demonstrate typed domain metadata, protected native button/disclosure semantics, and a native popover trigger relationship without product props; the Headers composition demonstrates direct toolbar headings with an extra-large title, optional supporting copy, and grouped icon/actions; the Select route verifies that option icons survive unrelated Kerf rerenders and selected slot content follows value changes; the Animation route exposes preset, easing, duration, playback-rate, and transport controls with live lifecycle status; observer routes provide user-driven intersection, mutation, and resize events with live results; ToolbarControlGroup exposes all eight Hot Sheet 2 variants, loads the Web Awesome registrations needed by its popup specimen, and preserves the upgraded dropdown's managed light-DOM children across Kerf rerenders; the Toolbar route composes a collapsible TokenSearchField inside a group, animates between the empty iconic and complete field states, stays open while populated, and focuses the revealed editor; SegmentedControl covers toolbar, rounded-rectangle, pill, equal-width, and disabled presentations; TokenSearchField covers editable ordered chips, pointer and keyboard removal, caret-preserving controlled deletion, editing, clearing, free text, disabled state, and fixed first-line alignment while content wraps; StateBanner exposes every built-in tone with tone-tinted badges plus a scoped override; the Application tabs composition demonstrates overflow, edge autoscroll, and controlled pointer/keyboard reordering.
|
|
35
35
|
- The ToolbarControlGroup route also demonstrates the public compact/tight,
|
|
36
36
|
mixed-content, filled-selection, nested-dropdown, and avatar/scrim contracts
|
|
37
37
|
added for consumers that previously restyled group descendants. The compact
|
|
38
|
-
mixed specimen keeps its separator
|
|
39
|
-
|
|
38
|
+
mixed specimen keeps its connected separator plus the standard 8px dropdown
|
|
39
|
+
trigger inset, label, and caret inside both pill and rounded group shapes.
|
|
40
|
+
Avatar images are chrome rather than nested `img`
|
|
40
41
|
elements: a lone avatar paints the group, while a multi-button avatar group
|
|
41
42
|
paints only the pressed selection, with contain fitting in both cases. Its
|
|
42
43
|
collapsible-search specimen follows the selected group shape with a
|
|
@@ -46,6 +47,6 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
46
47
|
- The footer action log is an `aria-live` region, making interactions visible to both people and browser tests.
|
|
47
48
|
- The focused Toast route calls Web Awesome's documented programmatic stack API and notes that Hot Sheet 2 still uses its own app-level toast implementation; the catalog demonstrates ecosystem support without implying current product adoption.
|
|
48
49
|
- Browser coverage walks every Kerf, composition, and Web Awesome route, checks every listed Web Awesome custom element is registered in its focused specimen, exercises the ecosystem disclosure and both relationship directions, validates offline source/guidance hrefs and accessible wide/narrow/200%-zoom wrapping, and covers tab selection/reordering/overflow, semantic palettes and scoped overrides, light/dark rendering, toolbar popup and responsive find behavior, single/multiline search alignment, menu alignment, banner urgency, keyboard resizing, live custom-element values, and representative wide/narrow captures.
|
|
49
|
-
- The production build keeps the catalog shell and Kerf routes in the entry chunk, then dynamically imports the complete Web Awesome specimen and registration surface when an ecosystem route
|
|
50
|
+
- The production build keeps the catalog shell and Kerf routes in the entry chunk, then dynamically imports the complete Web Awesome specimen and registration surface when an ecosystem route or the ToolbarControlGroup popup specimen is selected. Directly addressed routes pass through the same loader.
|
|
50
51
|
|
|
51
52
|
Before handoff, inspect the actual captures for readability, context, alignment, clipping, spacing, responsiveness, focus, and obvious defects. Fix and recapture rather than treating the screenshot as proof by itself.
|
package/docs/webawesome-theme.md
CHANGED
|
@@ -97,6 +97,11 @@ tiers:
|
|
|
97
97
|
complete surface and the inset within it. Accordion applies the outer margin
|
|
98
98
|
once to the group rather than separating connected items; Card's header,
|
|
99
99
|
body, and footer all receive the full inset.
|
|
100
|
+
- `appearance="sunken"` is a Kerf theme extension for Accordion, Card, and
|
|
101
|
+
Details. It removes raised chrome, paints the lowered semantic surface, and
|
|
102
|
+
uses the shared rounded-rectangle radius. Override
|
|
103
|
+
`--kui-wa-sunken-background` or `--kui-wa-sunken-radius` on an instance or
|
|
104
|
+
containing scope when that surface needs different tokens.
|
|
100
105
|
- `--kui-wa-container-inset` defaults to the 16px homogeneous-group step. Tab
|
|
101
106
|
Panel retains this roomier tier for unframed panel content. Dialog body uses
|
|
102
107
|
the 8px surface inset, while its footer uses the 16px container inset so
|
|
@@ -111,9 +116,19 @@ parts, which CSS shadow parts do not support.
|
|
|
111
116
|
|
|
112
117
|
Badge remains intentionally compact at Web Awesome's intrinsic `0.375em` block /
|
|
113
118
|
`0.625em` inline padding (4.5px / 7.5px at its default 12px text size): it is a
|
|
114
|
-
short status or count, not a content item.
|
|
115
|
-
|
|
116
|
-
|
|
119
|
+
short status or count, not a content item. A badge with `appearance="filled"` or
|
|
120
|
+
`appearance="filled-outlined"` uses its variant's quiet fill with normal text by
|
|
121
|
+
default so every shipped semantic variant meets WCAG AA for that small text;
|
|
122
|
+
filled-outlined keeps its normal variant border. Accent badges keep their loud
|
|
123
|
+
fills, with brand, success, and danger using a dark foreground that clears AA in
|
|
124
|
+
both themes (neutral and warning retain their already-safe variant foregrounds).
|
|
125
|
+
Override
|
|
126
|
+
`--kui-wa-badge-filled-background` and `--kui-wa-badge-filled-foreground` on a
|
|
127
|
+
badge or containing scope when a product needs a different contrast-safe pair,
|
|
128
|
+
or `--kui-wa-badge-accent-foreground` for a reviewed accent foreground.
|
|
129
|
+
Breadcrumb has no bordered or filled container, and Scroller delegates item chrome
|
|
130
|
+
to its slotted children, so both retain their upstream geometry. Web Awesome
|
|
131
|
+
3.12's free catalog has
|
|
117
132
|
`wa-dropdown-item`, but no `wa-menu-item`; the theme therefore styles the
|
|
118
133
|
supported dropdown item rather than carrying a dead selector.
|
|
119
134
|
|
|
@@ -174,8 +189,9 @@ generic Kerf wrappers around them. Their variants and appearances already read
|
|
|
174
189
|
the semantic palette above, and importing their component modules remains
|
|
175
190
|
independent and tree-shakeable.
|
|
176
191
|
|
|
177
|
-
- Use `wa-badge pill` for compact status, count, or activity
|
|
178
|
-
2's pill-shaped ticket status treatment
|
|
192
|
+
- Use `wa-badge pill appearance="filled"` for compact status, count, or activity
|
|
193
|
+
labels. Hot Sheet 2's quiet, contrast-safe pill-shaped ticket status treatment
|
|
194
|
+
is the reference shape.
|
|
179
195
|
- Use the default, non-pill `wa-tag` for categories, filters, and removable
|
|
180
196
|
selections. Its medium-radius rounded rectangle keeps tags distinct from
|
|
181
197
|
status badges. Handle the bubbling `wa-remove` event in the feature that owns
|
package/llms.txt
CHANGED
|
@@ -115,6 +115,11 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
115
115
|
the surface (8px) and container (16px) tiers respectively, independent of the
|
|
116
116
|
dialog's shared `--spacing`. Override the tier at the narrowest useful scope
|
|
117
117
|
instead of restyling individual shadow parts.
|
|
118
|
+
Filled badges use each semantic variant's quiet fill with normal text for
|
|
119
|
+
WCAG-AA compact-copy contrast. Override
|
|
120
|
+
`--kui-wa-badge-filled-background` and
|
|
121
|
+
`--kui-wa-badge-filled-foreground` as a contrast-safe pair instead of adding
|
|
122
|
+
host selectors.
|
|
118
123
|
When a dialog provides another dismissal affordance, add `hide-actions` to
|
|
119
124
|
the `wa-dialog` host; the theme hides its directly exported `header-actions`
|
|
120
125
|
part without an unsupported chained `::part()` selector.
|
|
@@ -160,9 +165,11 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
160
165
|
toolbar.
|
|
161
166
|
- **Use `Text` for ordinary semantic headings and paragraphs outside toolbar
|
|
162
167
|
title zones.** Omit `variant` for the default `p`, or pass `h1`–`h6` based on
|
|
163
|
-
the document outline.
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
the document outline. Independently compose `tone="quiet|danger"`,
|
|
169
|
+
`size="compact"`, and `font="monospace"` for supporting, error, compact, and
|
|
170
|
+
code roles instead of global utility classes. It passes native attributes
|
|
171
|
+
through and owns the standard transparent border plus item padding; keep
|
|
172
|
+
toolbar titles on `ToolbarText` and list-aligned bare prose on `ListInsetText`.
|
|
166
173
|
- **Space by the five-step scale, by relationship not by eye.** `0`
|
|
167
174
|
`--kui-space-none`, `4px` `--kui-space-2xs`, `8px` `--kui-space-xs` (inside a
|
|
168
175
|
group), `16px` `--kui-space-m`, `24px` `--kui-space-l` (between major differing
|
package/package.json
CHANGED
|
@@ -159,7 +159,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
159
159
|
}
|
|
160
160
|
/>
|
|
161
161
|
<div class="recipe-shell__main-body kui-pane__content kui-content">
|
|
162
|
-
<Text
|
|
162
|
+
<Text class="kui-recipe__ownership kui-content-item">
|
|
163
163
|
Recipe owns pane geometry and one scroll owner per pane. The app
|
|
164
164
|
owns routing, data, pane visibility, sizes, and persistence.
|
|
165
165
|
</Text>
|
|
@@ -172,7 +172,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
172
172
|
].map((title) => (
|
|
173
173
|
<article class="recipe-shell__card kui-content-item">
|
|
174
174
|
<strong>{title}</strong>
|
|
175
|
-
<Text
|
|
175
|
+
<Text class="kui-recipe__muted">
|
|
176
176
|
Assigned to the interface systems team · due this week
|
|
177
177
|
</Text>
|
|
178
178
|
</article>
|
|
@@ -147,14 +147,14 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
147
147
|
}
|
|
148
148
|
/>
|
|
149
149
|
<div class="recipe-collapsible-sidebar__body kui-pane__content kui-content">
|
|
150
|
-
<Text
|
|
150
|
+
<Text class="kui-recipe__ownership kui-content-item">
|
|
151
151
|
The app owns each panel's <code>collapsed</code> signal, sizes, and
|
|
152
152
|
content; <code>wireSidebar</code> owns the toggle, focus
|
|
153
153
|
move/restore, the compact overlay, and persistence.
|
|
154
154
|
</Text>
|
|
155
155
|
<article class="recipe-collapsible-sidebar__card kui-content-item">
|
|
156
156
|
<strong>Narrow the window to a compact width</strong>
|
|
157
|
-
<Text
|
|
157
|
+
<Text class="kui-recipe__muted">
|
|
158
158
|
The rail and drawer become a dismissable overlay: a backdrop,
|
|
159
159
|
Escape, and a trapped Tab ring, all managed by the wire.
|
|
160
160
|
</Text>
|
|
@@ -116,7 +116,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
116
116
|
<span class="kui-recipe__muted">One independent command.</span>
|
|
117
117
|
</div>
|
|
118
118
|
</div>
|
|
119
|
-
<Text
|
|
119
|
+
<Text class="kui-recipe__ownership kui-content-item">
|
|
120
120
|
The recipe owns control semantics and wrapping. The app owns values,
|
|
121
121
|
actions, persistence, and responsive priority.
|
|
122
122
|
</Text>
|
|
@@ -124,7 +124,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
124
124
|
Publish update
|
|
125
125
|
</wa-button>
|
|
126
126
|
</div>
|
|
127
|
-
<Text
|
|
127
|
+
<Text class="kui-recipe__ownership">
|
|
128
128
|
The recipe owns field, message, and action rhythm. The app owns
|
|
129
129
|
validation rules, draft persistence, permissions, and transport.
|
|
130
130
|
</Text>
|
|
@@ -59,7 +59,7 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
59
59
|
>
|
|
60
60
|
Open project details
|
|
61
61
|
</button>
|
|
62
|
-
<Text
|
|
62
|
+
<Text class="kui-recipe__ownership kui-content-item">
|
|
63
63
|
Web Awesome owns modal focus and dismissal. The recipe owns
|
|
64
64
|
header/body/list-detail anatomy; the app owns open state, selection, and
|
|
65
65
|
policy.
|
|
@@ -120,7 +120,6 @@ export const createRecipe: RecipeFactory = (announce) => {
|
|
|
120
120
|
}
|
|
121
121
|
/>
|
|
122
122
|
<Text
|
|
123
|
-
variant="p"
|
|
124
123
|
class="kui-recipe__heading-summary"
|
|
125
124
|
id="recipe-dialog-summary"
|
|
126
125
|
>
|