@kerfjs/ui 5.0.0-beta.24 → 5.0.0-beta.26
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 +44 -23
- package/ai/application-ui-diagnostic-ids-v1.json +3 -0
- package/ai/application-ui-profile.defaults.json +1 -1
- package/ai/compile-time-contracts-v1.json +3 -11
- package/ai/component-catalog-v2-overrides.json +7 -37
- package/ai/component-catalog-v2.d.ts +1 -0
- package/ai/component-catalog-v2.json +415 -91
- package/ai/component-catalog-v2.schema.json +2 -1
- package/ai/component-catalog.json +602 -158
- package/ai/public-api-signatures-v1.md +132 -65
- package/ai/skill.md +20 -20
- package/ai/webawesome-jsx-signatures-v1.md +2 -1
- package/analyzer/cli.mjs +5 -2
- package/analyzer/index.d.mts +1 -0
- package/analyzer/index.mjs +117 -10
- package/dist/app-tab.d.ts +10 -2
- package/dist/app-tab.js +1 -1
- package/dist/browser/list-action-row.js +1 -0
- package/dist/browser/list-item.js +1 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/catalog.js +5 -4
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-FEAMR7S4.js → chunk-4EF2CMYS.js} +24 -5
- package/dist/chunk-4EF2CMYS.js.map +1 -0
- package/dist/{chunk-NWSEP5RT.js → chunk-FRVS5RFM.js} +23 -5
- package/dist/chunk-FRVS5RFM.js.map +1 -0
- package/dist/{chunk-PSKN344N.js → chunk-GWEAPEZI.js} +15 -2
- package/dist/chunk-GWEAPEZI.js.map +1 -0
- package/dist/chunk-HP2B2L26.js +102 -0
- package/dist/chunk-HP2B2L26.js.map +1 -0
- package/dist/{chunk-OJWWHFH3.js → chunk-JFGXQBIP.js} +49 -23
- package/dist/chunk-JFGXQBIP.js.map +1 -0
- package/dist/chunk-OBLTAKSX.js +43 -0
- package/dist/chunk-OBLTAKSX.js.map +1 -0
- package/dist/{chunk-Y45PPBDV.js → chunk-OT6RPYAP.js} +16 -2
- package/dist/chunk-OT6RPYAP.js.map +1 -0
- package/dist/{chunk-UFZKLBCF.js → chunk-VCE4MPVE.js} +25 -3
- package/dist/chunk-VCE4MPVE.js.map +1 -0
- package/dist/{chunk-5VTB2BKP.js → chunk-WNWD54GR.js} +16 -2
- package/dist/chunk-WNWD54GR.js.map +1 -0
- package/dist/{chunk-M7JBER5U.js → chunk-X2U3QJCJ.js} +8 -2
- package/dist/chunk-X2U3QJCJ.js.map +1 -0
- package/dist/{chunk-DPDBVKNA.js → chunk-YMKH5XTF.js} +5 -3
- package/dist/chunk-YMKH5XTF.js.map +1 -0
- package/dist/collapsible-panel.d.ts +9 -1
- package/dist/collapsible-panel.js +36 -15
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -12
- package/dist/list-action-row.d.ts +11 -1
- package/dist/list-action-row.js +2 -1
- package/dist/list-header.d.ts +15 -2
- package/dist/list-header.js +1 -1
- package/dist/list-item.d.ts +12 -1
- package/dist/list-item.js +2 -1
- package/dist/resizable-region.d.ts +19 -2
- package/dist/resizable-region.js +1 -1
- package/dist/select.d.ts +12 -1
- package/dist/select.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/styles/app-tab.css +26 -0
- package/dist/styles/collapsible-panel.css +66 -4
- package/dist/styles/list-action-row.css +64 -0
- package/dist/styles/list-header.css +32 -0
- package/dist/styles/list-item.css +39 -0
- package/dist/styles/resizable-region.css +132 -0
- package/dist/styles/select.css +68 -0
- package/dist/styles/styles.css +1 -1
- package/dist/styles/surface-scaffold.css +51 -0
- package/dist/styles/tab-bar.css +24 -0
- package/dist/styles/toolbar-control-group.css +73 -1
- package/dist/styles/toolbar-text.css +1 -1
- package/dist/styles/webawesome.css +12 -0
- package/dist/styles/workbench.css +89 -0
- package/dist/surface-scaffold.d.ts +25 -0
- package/dist/surface-scaffold.js +3 -0
- package/dist/surface-scaffold.js.map +1 -0
- package/dist/tab-bar.d.ts +11 -2
- package/dist/tab-bar.js +1 -1
- package/dist/toolbar-control-group.d.ts +16 -2
- package/dist/toolbar-control-group.js +1 -1
- package/dist/webawesome.d.ts +1 -0
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +6 -1
- package/dist/wire-sidebar.js +27 -8
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +8 -0
- package/dist/workbench.js +42 -0
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +55 -12
- package/docs/collapsible-panel.md +7 -0
- package/docs/component-contract.md +5 -8
- package/docs/component-selection.md +63 -33
- package/docs/design/templates.md +5 -7
- package/docs/examples/component-catalog-extension-v2.json +3 -6
- package/docs/examples/component-catalog-extension.json +1 -1
- package/docs/layout.md +7 -9
- package/docs/recipes.md +8 -7
- package/docs/surface-scaffold.md +17 -0
- package/docs/type-contracts.md +6 -8
- package/docs/ui-analyzer.md +19 -1
- package/docs/ui-doctor.md +1 -1
- package/docs/ux-demo.md +6 -3
- package/docs/webawesome-theme.md +4 -1
- package/docs/workbench.md +49 -2
- package/doctor/eslint-diagnostics.d.mts +16 -0
- package/doctor/eslint-diagnostics.mjs +17 -0
- package/doctor/index.mjs +16 -1
- package/llms.txt +19 -9
- package/package.json +7 -7
- package/ux-demo/recipes/app-shell.tsx +36 -23
- package/ux-demo/recipes/collapsible-sidebar.tsx +22 -16
- package/ux-demo/recipes/composer-form.tsx +15 -6
- package/ux-demo/recipes/list-detail-dialog.tsx +31 -15
- package/ux-demo/recipes/list-workspace-states.tsx +16 -7
- package/ux-demo/recipes/loading-inspector.tsx +39 -18
- package/ux-demo/recipes/recipes.css +7 -2
- package/ux-demo/recipes/workspace-header.tsx +17 -7
- package/dist/browser/panel-header.js +0 -7
- package/dist/chunk-5VTB2BKP.js.map +0 -1
- package/dist/chunk-7XRDUG4Y.js +0 -58
- package/dist/chunk-7XRDUG4Y.js.map +0 -1
- package/dist/chunk-DPDBVKNA.js.map +0 -1
- package/dist/chunk-FEAMR7S4.js.map +0 -1
- package/dist/chunk-M7JBER5U.js.map +0 -1
- package/dist/chunk-NENBUYX5.js +0 -79
- package/dist/chunk-NENBUYX5.js.map +0 -1
- package/dist/chunk-NWSEP5RT.js.map +0 -1
- package/dist/chunk-OJWWHFH3.js.map +0 -1
- package/dist/chunk-PSKN344N.js.map +0 -1
- package/dist/chunk-UFZKLBCF.js.map +0 -1
- package/dist/chunk-Y45PPBDV.js.map +0 -1
- package/dist/panel-header.d.ts +0 -42
- package/dist/panel-header.js +0 -7
- package/dist/panel-header.js.map +0 -1
- package/dist/styles/panel-header.css +0 -64
- package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-actions.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
- package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
- package/docs/design/templates/panel-header/no-icon.svg +0 -1
- package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
- package/docs/design/templates/panel-header/page-heading.svg +0 -1
- package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
- package/docs/design/templates/panel-header/title-only.svg +0 -1
- package/docs/design/templates/panel-header-dark.svg +0 -1
- package/docs/design/templates/panel-header.svg +0 -1
|
@@ -75,42 +75,55 @@ an upstream component or recipe request.
|
|
|
75
75
|
|
|
76
76
|
## Problem-to-component matrix
|
|
77
77
|
|
|
78
|
-
| Interface need | Use when | Do not use when; nearest alternative
|
|
79
|
-
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
80
|
-
| 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`.
|
|
81
|
-
| 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.
|
|
82
|
-
| Application toolbar — `Toolbar`
|
|
83
|
-
| Toolbar control cluster — `ToolbarControlGroup` | Related toolbar controls need contained,
|
|
84
|
-
| 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.
|
|
85
|
-
| 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
|
|
86
|
-
| 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.
|
|
87
|
-
| 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.
|
|
88
|
-
| 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.
|
|
89
|
-
| 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 `
|
|
90
|
-
| 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.
|
|
91
|
-
| 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.
|
|
92
|
-
| 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.
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
|
|
|
98
|
-
|
|
|
99
|
-
|
|
|
100
|
-
|
|
|
101
|
-
|
|
|
102
|
-
|
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
|
|
|
106
|
-
|
|
|
78
|
+
| Interface need | Use when | Do not use when; nearest alternative | Required wiring | Application owns | Import | Recipe |
|
|
79
|
+
| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
80
|
+
| 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) |
|
|
81
|
+
| 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) |
|
|
82
|
+
| 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) |
|
|
83
|
+
| 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 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 `SegmentedControl` for an exclusive choice. | Actions, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
84
|
+
| 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) |
|
|
85
|
+
| 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) |
|
|
86
|
+
| 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) |
|
|
87
|
+
| 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. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
88
|
+
| 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) |
|
|
89
|
+
| 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) |
|
|
90
|
+
| 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) |
|
|
91
|
+
| 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) |
|
|
92
|
+
| 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`, provide optional fixed header/footer slots around its primary vertical content, and 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) |
|
|
93
|
+
| 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, import its CSS explicitly, and call `wireNavStack` for back delegation, transitions, and focus restoration. | View keys/content/titles, push and pop actions, focus targets, and optional bottom toolbar. | `@kerfjs/ui/nav-stack` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
94
|
+
| 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) |
|
|
95
|
+
| 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) |
|
|
96
|
+
| 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) |
|
|
97
|
+
| 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) |
|
|
98
|
+
| 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) |
|
|
99
|
+
| 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) |
|
|
100
|
+
| 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) |
|
|
101
|
+
| 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) |
|
|
102
|
+
| 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) |
|
|
103
|
+
| 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) |
|
|
104
|
+
| 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 for covered patterns. | Wrap one `wa-dialog` or `wa-dropdown`; choose the typed geometry while retaining native labeling, open state, focus, dismissal, and menu semantics. | State, focus lifecycle, dismissal, labels, content, and outer placement. | `@kerfjs/ui/surface-scaffold` | [Surface scaffolds](./surface-scaffold.md) |
|
|
105
|
+
| 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) |
|
|
106
|
+
| 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) |
|
|
107
|
+
| 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) |
|
|
108
|
+
| 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; listen for standard input/change events. 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) |
|
|
109
|
+
| 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) |
|
|
110
|
+
| 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) |
|
|
111
|
+
| Persistent inline status — `StateBanner` | A neutral, info, success, warning, or danger message belongs next to the affected work. | Do not use it 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) |
|
|
112
|
+
| 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) |
|
|
107
113
|
|
|
108
114
|
## Ambiguous choices
|
|
109
115
|
|
|
110
|
-
- `Toolbar`
|
|
116
|
+
- `Toolbar` serves persistent app chrome and headings; the zone contents and accessible naming distinguish the purpose.
|
|
111
117
|
- `TabBar` changes tabpanels and supports overflow/reorder; `SegmentedControl` chooses among a few compact views; `Select` handles a longer value list.
|
|
112
118
|
- `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.
|
|
113
119
|
- `ResizableRegion` is an interactive controlled pane. CSS grid is the right answer when columns do not need a user-operable separator.
|
|
120
|
+
- Configure application panels through the shared `separator`, `collapseMotion`,
|
|
121
|
+
`contentOverflow`, `presentation`, `restoreControl`, and `restorePosition`
|
|
122
|
+
props on `ResizableRegion`, `Workbench` panels, and `CollapsiblePanel`. These
|
|
123
|
+
cover separator suppression, one-reflow collapse with composited motion,
|
|
124
|
+
bottom-drawer popups, compact overlays or replacements, and safe-area restore
|
|
125
|
+
placement without descendant `.kui-*` overrides. `wireSidebar` also accepts a
|
|
126
|
+
hidden compact replacement and keeps compact overlays exclusive by default.
|
|
114
127
|
- `TokenSearchField` is a structured editor. A native input or `wa-input` is the right answer for ordinary text.
|
|
115
128
|
|
|
116
129
|
## Toolbar composition
|
|
@@ -122,9 +135,11 @@ controls). Do not drop bare buttons, inputs, links, or arbitrary markup straight
|
|
|
122
135
|
into a zone; wrap controls in a `ToolbarControlGroup` so they get the shared
|
|
123
136
|
toolbar geometry, hover/pressed treatment, and grouping. `SegmentedControl`,
|
|
124
137
|
`Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live
|
|
125
|
-
**inside** a `ToolbarControlGroup`, not loose in the zone.
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
**inside** a `ToolbarControlGroup`, not loose in the zone. For a page, panel, or
|
|
139
|
+
dialog heading, put an extra-large `ToolbarText` directly in the leading zone,
|
|
140
|
+
optionally preceded by a grouped icon, and group trailing actions. Keep supporting
|
|
141
|
+
copy below as app-owned content. A bottom divider is enabled by default. Set
|
|
142
|
+
`dividerSides=""` for none, or
|
|
128
143
|
use the canonical physical-edge combinations (`t`, `r`, `b`, `l`, in that
|
|
129
144
|
order—for example `tr` or `trbl`) when the toolbar owns other separator edges.
|
|
130
145
|
|
|
@@ -158,6 +173,21 @@ own DOM.
|
|
|
158
173
|
</ToolbarControlGroup>
|
|
159
174
|
```
|
|
160
175
|
|
|
176
|
+
## Configuring recurring list rows
|
|
177
|
+
|
|
178
|
+
Configure the List family instead of selecting its descendant classes. Use
|
|
179
|
+
`density="compact"` for result-heavy panes, `description` for the secondary
|
|
180
|
+
label line, `status` for dormant state text, and `busy` for known progress that
|
|
181
|
+
keeps current content visible. `divider` marks group boundaries without an
|
|
182
|
+
app-owned separator rule. `ListHeader.indicatorTone` gives count, badge, or
|
|
183
|
+
status content neutral, accent, or danger attention.
|
|
184
|
+
|
|
185
|
+
When a row needs a context action, use `ListActionRow`; its two native buttons
|
|
186
|
+
remain siblings. `trailingActionVisibility="interaction"` keeps the action
|
|
187
|
+
available on hover and keyboard focus and automatically leaves it visible on
|
|
188
|
+
non-hover devices. These props own presentation only—the application still
|
|
189
|
+
owns labels, status meaning, action policy, selection, and domain metadata.
|
|
190
|
+
|
|
161
191
|
## Correct composition and duplicated-markup trap
|
|
162
192
|
|
|
163
193
|
Correct: let the pane stay unpadded while its children own the shared 8/1/8
|
package/docs/design/templates.md
CHANGED
|
@@ -9,7 +9,7 @@ component picture without running the app.
|
|
|
9
9
|
|
|
10
10
|
## Coverage
|
|
11
11
|
|
|
12
|
-
Templated components (each with light + dark variants):
|
|
12
|
+
Templated components (each with light + dark variants):
|
|
13
13
|
`ToolbarControlGroup`, `Toolbar`, `ToolbarText`, `List`, `ListItem`, `ListHeader`,
|
|
14
14
|
`ListActionRow`, `ValueTable`, `StateBanner`, `EmptyState`, `Skeleton`,
|
|
15
15
|
`SegmentedControl`, `TabBar`/`AppTab`, and `TokenSearchField`.
|
|
@@ -27,11 +27,9 @@ catalog and the app-layouts docs cover those.
|
|
|
27
27
|
|
|
28
28
|
```
|
|
29
29
|
docs/design/templates/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
icon-summary-actions.svg ← one self-contained variant (light)
|
|
34
|
-
icon-summary-actions-dark.svg ← the same variant, dark theme
|
|
30
|
+
toolbar.svg ← library: every variant, composed (light)
|
|
31
|
+
toolbar-dark.svg ← library: dark theme
|
|
32
|
+
toolbar/
|
|
35
33
|
icon-actions.svg
|
|
36
34
|
icon-actions-dark.svg
|
|
37
35
|
…
|
|
@@ -74,7 +72,7 @@ not have to interpret nested `<svg>` elements.
|
|
|
74
72
|
|
|
75
73
|
**Keep the templates current as components change.** The variants live in the
|
|
76
74
|
`COMPONENTS` manifest in `scripts/build-design-templates.mjs` — when a component
|
|
77
|
-
gains or changes a presentation combination (e.g. a new `
|
|
75
|
+
gains or changes a presentation combination (e.g. a new `Toolbar` slot), add
|
|
78
76
|
or adjust its variant there and re-run the build. Cover the common cases: if a
|
|
79
77
|
component can render with or without an icon, include both.
|
|
80
78
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"zones": [
|
|
20
20
|
{
|
|
21
21
|
"id": "header",
|
|
22
|
-
"accepts": ["@kerfjs/ui:
|
|
22
|
+
"accepts": ["@kerfjs/ui:toolbar"],
|
|
23
23
|
"cardinality": { "min": 1, "max": 1 },
|
|
24
24
|
"exclusiveWith": []
|
|
25
25
|
},
|
|
@@ -32,11 +32,8 @@
|
|
|
32
32
|
],
|
|
33
33
|
"children": {
|
|
34
34
|
"mode": "listed",
|
|
35
|
-
"concepts": ["@kerfjs/ui:
|
|
36
|
-
"requiredConcepts": [
|
|
37
|
-
"@kerfjs/ui:panel-header",
|
|
38
|
-
"@kerfjs/ui:value-table"
|
|
39
|
-
]
|
|
35
|
+
"concepts": ["@kerfjs/ui:toolbar", "@kerfjs/ui:value-table"],
|
|
36
|
+
"requiredConcepts": ["@kerfjs/ui:toolbar", "@kerfjs/ui:value-table"]
|
|
40
37
|
},
|
|
41
38
|
"state": [
|
|
42
39
|
{ "id": "selected-record", "owner": "application", "required": true }
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"border": "child",
|
|
37
37
|
"padding": "child",
|
|
38
38
|
"notes": [
|
|
39
|
-
"The embedding pane positions the inspector;
|
|
39
|
+
"The embedding pane positions the inspector; Toolbar, ValueTable, and action groups retain their own geometry."
|
|
40
40
|
]
|
|
41
41
|
},
|
|
42
42
|
"documentation": "docs/inspector.md"
|
package/docs/layout.md
CHANGED
|
@@ -56,7 +56,7 @@ control border and 1px control padding, so its default rounded-rectangle radius
|
|
|
56
56
|
is 10px inside the control's 12px radius.
|
|
57
57
|
|
|
58
58
|
A visible parent surface does not make every child another visible card. The
|
|
59
|
-
composer recipe keeps its form as the single surface, uses `
|
|
59
|
+
composer recipe keeps its form as the single surface, uses a heading `Toolbar` for
|
|
60
60
|
its task hierarchy, and places field and action control edges on the shared 8px
|
|
61
61
|
inline gutter instead of nesting them inside another padded content item. A
|
|
62
62
|
conditional `StateBanner` remains visibly distinct because it communicates
|
|
@@ -77,7 +77,7 @@ semantic status.
|
|
|
77
77
|
| Explicit scroll owner outside a pane | `.kui-scroll-owner` | `overflow: auto` |
|
|
78
78
|
|
|
79
79
|
The component layer applies the same contract to `Toolbar`, `ListHeader`,
|
|
80
|
-
`ListItem`, `
|
|
80
|
+
`ListItem`, `Toolbar`, `StateBanner`, `ValueTable`,
|
|
81
81
|
`ValueTableRow`, tabs, and form controls. A value-table row separator starts at
|
|
82
82
|
the row's 8px content inset, or at 40px when the row contains its 24px leading
|
|
83
83
|
icon and 8px gap, and always ends 8px from the right edge. Each value-table row
|
|
@@ -85,13 +85,11 @@ also keeps 8px of root-scaled block padding independently of its semantic inline
|
|
|
85
85
|
inset. Most interactive rows and toolbar groups are 44px tall.
|
|
86
86
|
Toolbar groups reserve a real 1px outer border around a 42px inner area, even
|
|
87
87
|
when their border and background are transparent.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
no icon is passed. The optional subtitle is a separate row below the toolbar, its
|
|
94
|
-
text left-aligned with the title text.
|
|
88
|
+
Panel, dialog, and page headings are plain `Toolbar` compositions. The leading
|
|
89
|
+
zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
|
|
90
|
+
`ToolbarText`; actions belong in a trailing group. Omit empty groups. Supporting
|
|
91
|
+
copy is app-owned content below the toolbar and aligns with the intended content
|
|
92
|
+
edge.
|
|
95
93
|
|
|
96
94
|
## Spacing scale
|
|
97
95
|
|
package/docs/recipes.md
CHANGED
|
@@ -56,7 +56,7 @@ no custom `actionIcon` is needed; ordinary navigation rows stay chevron-free.
|
|
|
56
56
|
|
|
57
57
|
[Open the recipe](../ux-demo/?component=recipe-workspace-header) · [TSX source](../ux-demo/recipes/workspace-header.tsx)
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
The page heading is a direct `Toolbar`/`ToolbarText` composition while one control cluster holds secondary,
|
|
60
60
|
overflow, and primary actions. The app owns authorization and command policy;
|
|
61
61
|
controls relocate without changing focus order.
|
|
62
62
|
|
|
@@ -66,10 +66,10 @@ controls relocate without changing focus order.
|
|
|
66
66
|
|
|
67
67
|
The production Web Awesome dialog owns modal focus and Escape; the thin recipe
|
|
68
68
|
adapter restores the invoking control consistently after the hide event.
|
|
69
|
-
`
|
|
69
|
+
`Toolbar`, `ListHeader`, `ListItem`, and `ValueTable` own their included
|
|
70
70
|
anatomy. The application owns open state, selection, dismissal policy, and
|
|
71
|
-
record actions. `
|
|
72
|
-
|
|
71
|
+
record actions. A `ToolbarControlGroup` places the app's trailing controls in
|
|
72
|
+
the top toolbar's trailing zone.
|
|
73
73
|
The header sits on the dialog edge while retaining its internal control inset;
|
|
74
74
|
the selected title receives the full content gutter, the metadata table fills
|
|
75
75
|
the available detail width between the usual outer margins, and the action
|
|
@@ -80,8 +80,9 @@ Do not rebuild the dialog or reach into private shadow parts.
|
|
|
80
80
|
|
|
81
81
|
[Open the recipe](../ux-demo/?component=recipe-composer-form) · [TSX source](../ux-demo/recipes/composer-form.tsx)
|
|
82
82
|
|
|
83
|
-
`
|
|
84
|
-
by the form. Production fields own labels, help,
|
|
83
|
+
A direct `ToolbarText` supplies the task title, with app-owned supporting copy
|
|
84
|
+
below; their ids are referenced by the form. Production fields own labels, help,
|
|
85
|
+
and native focus. The field
|
|
85
86
|
and footer control edges sit directly on the shared 8px inline gutter rather
|
|
86
87
|
than acquiring a second content-item padding inset; major children remain 24px
|
|
87
88
|
apart and related controls use 8px gaps. The app owns
|
|
@@ -126,7 +127,7 @@ settles the chrome (reduced motion collapses the slide to instant). A live
|
|
|
126
127
|
[Open the recipe](../ux-demo/?component=recipe-loading-inspector) · [TSX source](../ux-demo/recipes/loading-inspector.tsx)
|
|
127
128
|
|
|
128
129
|
A record inspector whose per-record values load asynchronously. Every
|
|
129
|
-
value-bearing component (`
|
|
130
|
+
value-bearing component (`ToolbarText`, `ValueTable`/`ValueTableRow`, `Select`,
|
|
130
131
|
`SegmentedControl`, `ListItem`, `StateBanner`) takes its `placeholder` from one
|
|
131
132
|
loading flag, so the same real chrome renders a faithful loading state and then
|
|
132
133
|
the populated record — no separate skeleton markup. The composition is the point;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Dialog and popup surface scaffolds
|
|
2
|
+
|
|
3
|
+
`DialogSurface` and `PopupSurface` configure recurring Web Awesome surface
|
|
4
|
+
geometry without application `::part()` overrides. They do not replace Web
|
|
5
|
+
Awesome behavior: the application still owns open state, focus lifecycle,
|
|
6
|
+
dismissal policy, ids, labels, and content.
|
|
7
|
+
|
|
8
|
+
Wrap one `wa-dialog` with `DialogSurface`. Choose `size` (`small`, `medium`, or
|
|
9
|
+
`large`), `presentation` (`modal`, `side-sheet`, or `fullscreen`), and independent
|
|
10
|
+
`bodyInset` / `footerInset` (`none`, `compact`, or `comfortable`). The defaults
|
|
11
|
+
match Kerf's medium modal, 8px body, and 16px footer rhythm.
|
|
12
|
+
|
|
13
|
+
Wrap one `wa-dropdown` with `PopupSurface`. `inset="list-zero"` removes menu
|
|
14
|
+
padding for a child that already owns row insets, `compact` uses 4px, and
|
|
15
|
+
`standard` uses the shared 8px surface inset. Keep the dropdown trigger named and
|
|
16
|
+
preserve `data-morph-skip-children` when its upgraded light-DOM items must retain
|
|
17
|
+
identity across Kerf rerenders.
|