@kerfjs/ui 5.0.0-beta.78 → 5.0.0-beta.79
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 +8 -6
- package/ai/application-ui-diagnostic-ids-v1.json +1 -0
- package/ai/compile-time-contracts-v1.json +3 -3
- package/ai/component-catalog.json +31 -22
- package/ai/component-composition-rules.json +6 -14
- package/ai/component-composition.json +21 -23
- package/ai/components/README.md +1 -1
- package/ai/components/document-baseline.md +1 -1
- package/ai/components/nav-stack.md +3 -3
- package/ai/components/pane.md +3 -1
- package/ai/components/{tab-scaffold.md → tab-navigator.md} +14 -14
- package/ai/components/token-search-field.md +1 -0
- package/ai/components/toolbar.md +4 -8
- package/ai/public-api-signatures-v1.md +20 -20
- package/ai/skill.md +7 -6
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/browser/tab-navigator.js +4 -0
- package/dist/{chunk-QYXKMLHO.js → chunk-3CXRQAYT.js} +2 -2
- package/dist/chunk-3CXRQAYT.js.map +1 -0
- package/dist/{chunk-G4VKQP7B.js → chunk-3SXWV2IR.js} +5 -1
- package/dist/chunk-3SXWV2IR.js.map +1 -0
- package/dist/{chunk-VLPE6OPN.js → chunk-62VMNBV2.js} +6 -2
- package/dist/chunk-62VMNBV2.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/styles/components/actions/toolbar/toolbar.css +7 -14
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +3 -0
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +1 -0
- package/dist/styles/components/forms/token-search-field/token-search-field.css +12 -1
- package/dist/styles/components/layout/pane/pane.css +13 -3
- package/dist/styles/components/navigation/tab-scaffold/tab-scaffold.css +1 -1
- package/dist/styles/pane.css +13 -3
- package/dist/styles/{tab-scaffold.css → tab-navigator.css} +1 -1
- package/dist/styles/token-search-field.css +12 -1
- package/dist/styles/toolbar-control-group.css +3 -0
- package/dist/styles/toolbar-text.css +1 -0
- package/dist/styles/toolbar.css +7 -14
- package/dist/{tab-scaffold.d.ts → tab-navigator.d.ts} +10 -10
- package/dist/{tab-scaffold.js → tab-navigator.js} +3 -3
- package/dist/tab-navigator.js.map +1 -0
- package/dist/token-search-field.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-scroll-dividers.d.ts +3 -3
- package/dist/wire-scroll-dividers.js +1 -1
- package/dist/wire-tab-navigator.d.ts +11 -0
- package/dist/{wire-tab-scaffold.js → wire-tab-navigator.js} +3 -3
- package/dist/wire-tab-navigator.js.map +1 -0
- package/dist/wire-token-search-fields.js +1 -1
- package/docs/app-layouts.md +44 -11
- package/docs/component-contract.md +1 -1
- package/docs/component-selection.md +16 -14
- package/docs/design/templates/token-search-field/empty-dark.svg +1 -1
- package/docs/design/templates/token-search-field/empty.svg +1 -1
- package/docs/design/templates/token-search-field-dark.svg +1 -1
- package/docs/design/templates/token-search-field.svg +1 -1
- package/docs/design/templates.md +1 -1
- package/docs/examples/application-ui-profile.json +4 -4
- package/docs/layout.md +11 -8
- package/docs/recipes.md +1 -1
- package/docs/{tab-scaffold.md → tab-navigator.md} +32 -17
- package/docs/type-contracts.md +3 -3
- package/docs/ui-analyzer.md +5 -0
- package/docs/ui-doctor.md +18 -8
- package/doctor/component-style-checks.mjs +253 -20
- package/doctor/index.mjs +1 -0
- package/llms.txt +10 -8
- package/package.json +10 -10
- package/dist/browser/tab-scaffold.js +0 -4
- package/dist/chunk-G4VKQP7B.js.map +0 -1
- package/dist/chunk-QYXKMLHO.js.map +0 -1
- package/dist/chunk-VLPE6OPN.js.map +0 -1
- package/dist/tab-scaffold.js.map +0 -1
- package/dist/wire-tab-scaffold.d.ts +0 -11
- package/dist/wire-tab-scaffold.js.map +0 -1
package/dist/wire-catalog.js
CHANGED
|
@@ -28,7 +28,7 @@ interface WireScrollDividersOptions {
|
|
|
28
28
|
/**
|
|
29
29
|
* App-owned scroll arrangements to pair beyond the ones found by structure
|
|
30
30
|
* (every `Pane`'s header and footer around its content, every `NavStack`'s
|
|
31
|
-
* and `
|
|
31
|
+
* and `TabNavigator`'s chrome around its active region, and every `TabBar`
|
|
32
32
|
* strip).
|
|
33
33
|
*/
|
|
34
34
|
targets?: readonly ScrollDividerTarget[];
|
|
@@ -48,11 +48,11 @@ type Root = HTMLElement | Document;
|
|
|
48
48
|
* - every `Pane` with a header or footer: its header shows a bottom divider and
|
|
49
49
|
* its footer a top divider (drawn by the Pane, per its `chromeDividers`);
|
|
50
50
|
* - every `NavStack`'s top chrome and bottom toolbar around its active view,
|
|
51
|
-
* and every `
|
|
51
|
+
* and every `TabNavigator`'s bar under its active scene: the chrome shows a
|
|
52
52
|
* bottom (top chrome) or top (bottom toolbar, bar) divider. The scroller is
|
|
53
53
|
* whichever element actually scrolls there: the view or scene itself, or,
|
|
54
54
|
* through a sole child with no chrome of its own on that edge, a `Pane`'s
|
|
55
|
-
* content or a nested `NavStack` / `
|
|
55
|
+
* content or a nested `NavStack` / `TabNavigator` region (a Pane's own header
|
|
56
56
|
* or footer draws that boundary instead);
|
|
57
57
|
* - every `TabBar` strip: the bar draws a divider on each side of the strip
|
|
58
58
|
* whose tabs are scrolled out of view;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface WireTabNavigatorOptions {
|
|
2
|
+
/** Invoked with the selected tab id when a bottom-bar tab is activated. */
|
|
3
|
+
onSelect: (tabId: string) => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Wire a `TabNavigator`'s bottom tab bar: clicking a tab calls `onSelect` with its
|
|
7
|
+
* id (the app then updates its controlled `active`). Returns a disposer.
|
|
8
|
+
*/
|
|
9
|
+
declare function wireTabNavigator(root: Element, options: WireTabNavigatorOptions): () => void;
|
|
10
|
+
|
|
11
|
+
export { type WireTabNavigatorOptions, wireTabNavigator };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { delegate } from 'kerfjs';
|
|
2
2
|
|
|
3
3
|
// src/components/navigation/tab-scaffold/wiring/wire-tab-scaffold.ts
|
|
4
|
-
function
|
|
4
|
+
function wireTabNavigator(root, options) {
|
|
5
5
|
const section = root.matches('[data-component="tab-scaffold"]') ? root : root.querySelector('[data-component="tab-scaffold"]');
|
|
6
6
|
if (!(section instanceof HTMLElement)) return () => {
|
|
7
7
|
};
|
|
@@ -16,6 +16,6 @@ function wireTabScaffold(root, options) {
|
|
|
16
16
|
);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export {
|
|
19
|
+
export { wireTabNavigator };
|
|
20
20
|
|
|
21
|
-
//# sourceMappingURL=wire-tab-
|
|
21
|
+
//# sourceMappingURL=wire-tab-navigator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/navigation/tab-scaffold/wiring/wire-tab-scaffold.ts"],"names":[],"mappings":";;;AAWO,SAAS,gBAAA,CACd,MACA,OAAA,EACY;AACZ,EAAA,MAAM,OAAA,GAAU,KAAK,OAAA,CAAQ,iCAAiC,IAC1D,IAAA,GACA,IAAA,CAAK,cAAc,iCAAiC,CAAA;AACxD,EAAA,IAAI,EAAE,OAAA,YAAmB,WAAA,CAAA,EAAc,OAAO,MAAM;AAAA,EAAC,CAAA;AACrD,EAAA,OAAO,QAAA;AAAA,IACL,OAAA;AAAA,IACA,OAAA;AAAA,IACA,yBAAA;AAAA,IACA,CAAC,QAAQ,MAAA,KAAW;AAClB,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,YAAA,CAAa,uBAAuB,CAAA;AACzD,MAAA,IAAI,KAAA,EAAO,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA;AAAA,IACnC;AAAA,GACF;AACF","file":"wire-tab-navigator.js","sourcesContent":["import { delegate } from 'kerfjs';\n\nexport interface WireTabNavigatorOptions {\n /** Invoked with the selected tab id when a bottom-bar tab is activated. */\n onSelect: (tabId: string) => void;\n}\n\n/**\n * Wire a `TabNavigator`'s bottom tab bar: clicking a tab calls `onSelect` with its\n * id (the app then updates its controlled `active`). Returns a disposer.\n */\nexport function wireTabNavigator(\n root: Element,\n options: WireTabNavigatorOptions,\n): () => void {\n const section = root.matches('[data-component=\"tab-scaffold\"]')\n ? root\n : root.querySelector('[data-component=\"tab-scaffold\"]');\n if (!(section instanceof HTMLElement)) return () => {};\n return delegate(\n section,\n 'click',\n '[data-tab-scaffold-tab]',\n (_event, target) => {\n const tabId = target.getAttribute('data-tab-scaffold-tab');\n if (tabId) options.onSelect(tabId);\n },\n );\n}\n"]}
|
package/docs/app-layouts.md
CHANGED
|
@@ -9,7 +9,7 @@ changes. The layouts:
|
|
|
9
9
|
- [`NavStack`](nav-stack.md) — push/pop navigation (a single pane is a one-entry stack).
|
|
10
10
|
- [`SplitView`](split-view.md) — list-detail (two panes, collapsing to a stack).
|
|
11
11
|
- [`Workbench`](workbench.md) — the Xcode-like collapsible rails + drawer.
|
|
12
|
-
- [`
|
|
12
|
+
- [`TabNavigator`](tab-navigator.md) — the iOS bottom tab bar (each tab a stack).
|
|
13
13
|
- [`CollapsiblePanel` + `wireSidebar`](collapsible-panel.md) — a standalone
|
|
14
14
|
collapsible rail or bottom drawer (with `CollapsiblePanelToggle`), outside a full
|
|
15
15
|
shell: the standard collapse animation, icon convention, and `wireSidebar`
|
|
@@ -45,7 +45,7 @@ the layouts handle the insets for you. There is nothing to configure:
|
|
|
45
45
|
- **No double inset.** Whichever region applies an inset clears it for its
|
|
46
46
|
descendants. A layout region whose only child is a `Pane` or another layout
|
|
47
47
|
lets that child own the insets. That child fills the region — a `Workbench`
|
|
48
|
-
area or panel, a `NavStack` view, a `
|
|
48
|
+
area or panel, a `NavStack` view, a `TabNavigator` scene — so a sole `Pane`'s
|
|
49
49
|
header stays pinned while its own content scrolls. A `Pane` header or footer whose only child is
|
|
50
50
|
a `Toolbar` hands the inline insets to the toolbar, so the toolbar's dividers
|
|
51
51
|
still reach the edge.
|
|
@@ -96,15 +96,48 @@ The device insets come from `--kui-safe-area-block-start`, `-block-end`,
|
|
|
96
96
|
Override them on `:root` to reserve room for app-owned chrome or to simulate a
|
|
97
97
|
device in tests.
|
|
98
98
|
|
|
99
|
+
### Edge-to-edge content inside a Pane
|
|
100
|
+
|
|
101
|
+
The Pane's scrolling slot publishes its resolved horizontal padding as
|
|
102
|
+
`--kui-pane-content-inset-inline-start` and
|
|
103
|
+
`--kui-pane-content-inset-inline-end`. Both inherited values include the safe
|
|
104
|
+
area on the corresponding side, plus the extra 8px when `deepInset` is true.
|
|
105
|
+
An app component can use them to let a row background or divider reach the
|
|
106
|
+
Pane edge while its text stays on the ordinary content axis:
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
.orders-table {
|
|
110
|
+
margin-inline-start: calc(-1 * var(--kui-pane-content-inset-inline-start));
|
|
111
|
+
margin-inline-end: calc(-1 * var(--kui-pane-content-inset-inline-end));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.orders-table th:first-child,
|
|
115
|
+
.orders-table td:first-child {
|
|
116
|
+
padding-inline-start: calc(var(--kui-pane-content-inset-inline-start) + 17px);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.orders-table th:last-child,
|
|
120
|
+
.orders-table td:last-child {
|
|
121
|
+
padding-inline-end: calc(var(--kui-pane-content-inset-inline-end) + 17px);
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Here 17px is the app's chosen text offset from the content slot: a default
|
|
126
|
+
`ContentItem` uses 8px outer margin, 1px border, and 8px inner padding. Adjust
|
|
127
|
+
that offset to match the neighboring content. Keep the table inside the Pane's
|
|
128
|
+
single scrolling slot; the negative margins change only its inline reach. The
|
|
129
|
+
[`Pane` UX catalog example](../ux-demo/demos/pane.tsx) shows both `deepInset`
|
|
130
|
+
states with the same table component.
|
|
131
|
+
|
|
99
132
|
## Decision matrix
|
|
100
133
|
|
|
101
|
-
| Situation | Layout
|
|
102
|
-
| ---------------------------------------------------------------------------- |
|
|
103
|
-
| Simple app, a few flat sections | `NavStack` with one entry (single pane); add `
|
|
104
|
-
| Drill-down browsing (list → item → sub-item) | `NavStack`; upgrade to `SplitView` once list + detail fit together
|
|
105
|
-
| Two related panes, selecting on the left updates the right | `SplitView`
|
|
106
|
-
| Complex tool / editor with peripheral panels (navigator, inspector, console) | `Workbench`
|
|
107
|
-
| Mobile app with 2–5 top-level destinations, each its own drill-down | `
|
|
134
|
+
| Situation | Layout | Device threshold |
|
|
135
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
136
|
+
| Simple app, a few flat sections | `NavStack` with one entry (single pane); add `TabNavigator` for 2–5 co-equal sections on handset | `TabNavigator` on `compact`; promote its tabs to a `Workbench` rail / sidebar `atLeast('desktop')` |
|
|
137
|
+
| Drill-down browsing (list → item → sub-item) | `NavStack`; upgrade to `SplitView` once list + detail fit together | `SplitView` two-pane `atLeast('tablet')` landscape / non-`compact`; `NavStack` form on `compact` |
|
|
138
|
+
| Two related panes, selecting on the left updates the right | `SplitView` | two panes when not `compact`; collapses to `NavStack` (list → detail) on `compact` |
|
|
139
|
+
| Complex tool / editor with peripheral panels (navigator, inspector, console) | `Workbench` | full three-panel `atLeast('desktop')`; on smaller classes present the rails via `NavStack` / overlay drawers, not a shrunken shell |
|
|
140
|
+
| Mobile app with 2–5 top-level destinations, each its own drill-down | `TabNavigator`, each tab a `NavStack` | bottom bar on `compact`; promote to a rail / sidebar `atLeast('desktop')` |
|
|
108
141
|
|
|
109
142
|
### Worked examples
|
|
110
143
|
|
|
@@ -129,13 +162,13 @@ device in tests.
|
|
|
129
162
|
default) and shrink in proportion when the window narrows; the bottom drawer
|
|
130
163
|
leaves it `mainMinHeight` (120px by default) and shrinks when the window gets
|
|
131
164
|
shorter.
|
|
132
|
-
- **Social app (tabbed):** `
|
|
165
|
+
- **Social app (tabbed):** `TabNavigator` with Home / Search / Profile tabs, each
|
|
133
166
|
`content` a `NavStack`. On a tablet/desktop, render the same sections as a
|
|
134
167
|
`Workbench` left rail instead of a bottom bar.
|
|
135
168
|
|
|
136
169
|
Whatever the layout, call `wireScrollDividers(appRoot)` from
|
|
137
170
|
`@kerfjs/ui/wire-scroll-dividers` once: every `Pane` a layout renders, every
|
|
138
|
-
`NavStack`'s top chrome and bottom toolbar, and every `
|
|
171
|
+
`NavStack`'s top chrome and bottom toolbar, and every `TabNavigator` bar then
|
|
139
172
|
draw the line between the pinned chrome and the scrolling content only while
|
|
140
173
|
content is scrolled beneath them, and toolbars need no divider of their own. See [Scroll dividers](layout.md#scroll-dividers).
|
|
141
174
|
|
|
@@ -713,7 +713,7 @@ helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
|
|
|
713
713
|
transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
|
|
714
714
|
apps kept reimplementing inconsistently, so the helper owns it. Everywhere else the
|
|
715
715
|
app's state is **domain or persisted, not transient chrome, and stays app-owned**: a
|
|
716
|
-
`NavStack`'s view stack is navigation history, a `TabBar`/`
|
|
716
|
+
`NavStack`'s view stack is navigation history, a `TabBar`/`TabNavigator`'s selection
|
|
717
717
|
and tab order are data, a `ResizableRegion`'s committed size and a
|
|
718
718
|
`Workbench`/`SplitView` rail's `collapsed` flag are persisted layout preferences.
|
|
719
719
|
Each helper already owns only the _ephemeral mechanics_ around that state —
|
|
@@ -171,10 +171,10 @@ beside a `ContentItem` value, and connect its id to the preview group's
|
|
|
171
171
|
| 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 `sides="rl"` 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) |
|
|
172
172
|
| Self-contained content child — `ContentItem` | An ordinary surface-like child of a `Pane` or `.kui-content` stack needs the shared 8px margin / 1px border / 8px padding geometry; pass `frame="framed"` only when it marks a real distinction, `appearance="surface"` or a semantic appearance for coordinated surface colors, and `shape="pill"` for the 22px radius. | Do not wrap a component that already owns content-item geometry (`ListItem`, `ListHeader`, `StateBanner`, `Toolbar`, `ValueTable`) or pad around it — that double-insets. Do not frame an item only to make it look contained. Use `SunkenPanel` for a lowered inset stack and `ListInsetText` for bare text that only needs to align. | Pass the item content as children; choose `appearance` (`transparent` default, `surface`, or a semantic status), `frame`, and `shape` instead of writing CSS. Put safe `data-*` metadata in `rootAttributes`; `ariaLabel` names a distinct region and `focusTarget` makes it a programmatic focus target. | The content, surface or status appearance, and whether it marks a distinction worth a visible frame. | `@kerfjs/ui/content-item` | [Content items](./layout.md#content-items) |
|
|
173
173
|
| 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 `ContentItem` children 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) |
|
|
174
|
-
| Scroll dividers — `wireScrollDividers` | Pinned chrome (a `Pane` header or footer, a `NavStack` top chrome or bottom toolbar, a `
|
|
175
|
-
| 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 `
|
|
174
|
+
| Scroll dividers — `wireScrollDividers` | Pinned chrome (a `Pane` header or footer, a `NavStack` top chrome or bottom toolbar, a `TabNavigator` bar, the sides of a `TabBar` strip, or app-owned chrome around a scroller) needs a divider only while content is scrolled away beneath it. | Do not keep a static toolbar divider to fake it or write a border onto another component; each component draws its own line from the wiring's state. | Call `wireScrollDividers` once at the app root and retain the disposer; it covers every `Pane`, `NavStack`, `TabNavigator`, and `TabBar` below it. Name app-owned arrangements in `targets` by id; a `Toolbar` or `List` named as chrome draws its facing side. Configure a pane with `chromeDividers` (`scroll` default, `always`, `none`). | Which panes follow the scroll, app-owned targets, and the disposer. | `@kerfjs/ui/wire-scroll-dividers` | [Scroll dividers](./layout.md#scroll-dividers) |
|
|
175
|
+
| 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 `TabNavigator` 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) |
|
|
176
176
|
| 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) |
|
|
177
|
-
| Compact top-level destinations — `
|
|
177
|
+
| Compact top-level destinations — `TabNavigator` | 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 `wireTabNavigator`; commonly place one `NavStack` in each tab scene. | Destination definitions, active id, routing, persistence, and roomy-device replacement. | `@kerfjs/ui/tab-navigator` | [App-layout decision matrix](./app-layouts.md#decision-matrix) |
|
|
178
178
|
| 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. Opt a panel into drag/keyboard resizing with `resizable` and call `wireWorkbench` with its size signal. | Panel presence/content, collapsed states, sizes, persistence, responsive replacement, and controls. | `@kerfjs/ui/workbench` | [Workbench](./workbench.md) |
|
|
179
179
|
| 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) |
|
|
180
180
|
| 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) |
|
|
@@ -405,22 +405,24 @@ A `FloatingToolbar` accepts `ToolbarControlGroup` directly as its children in
|
|
|
405
405
|
both floating and inline placement. Name the toolbar with `label`; group its
|
|
406
406
|
controls as you would in a `Toolbar` zone.
|
|
407
407
|
|
|
408
|
-
A `Toolbar` has three zones — `leading`, `center`, and `trailing`.
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
408
|
+
A `Toolbar` has three zones — `leading`, `center`, and `trailing`. Each accepts
|
|
409
|
+
`KerfUiContent` directly, including a status `Chip`, a native control, or
|
|
410
|
+
application markup. `ToolbarText` is the standard identity/title; use
|
|
411
|
+
`ToolbarControlGroup` when related controls should share its chrome, sizing,
|
|
412
|
+
hover treatment, or overflow behavior. A standalone primary `wa-button` keeps
|
|
413
|
+
its own Web Awesome chrome and fits naturally in the trailing zone. Bare
|
|
414
|
+
controls retain their own styling and accessibility responsibilities; the
|
|
415
|
+
toolbar only positions them within the zone.
|
|
414
416
|
For a title that opens an editor, set `action` on a direct `ToolbarText`: it
|
|
415
417
|
renders a native button that keeps its content width when possible and
|
|
416
418
|
ellipsizes before an adjacent status chip when the leading zone narrows. The
|
|
417
419
|
application handles the delegated action and replaces it with its own input
|
|
418
420
|
while editing. Use a separate heading landmark if the view needs one.
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
421
|
+
For a search or cluster that needs shared toolbar geometry, place
|
|
422
|
+
`SegmentedControl`, `Select`, or `TokenSearchField` inside a
|
|
423
|
+
`ToolbarControlGroup`. The ToolbarText catalog's actionable-title example
|
|
424
|
+
places its status `Chip` directly beside the title while the search uses a
|
|
425
|
+
group. For a page, panel, or
|
|
424
426
|
dialog heading, put an extra-large `ToolbarText` directly in the leading zone,
|
|
425
427
|
optionally preceded by a grouped icon, and group trailing actions. Keep supporting
|
|
426
428
|
copy below as app-owned content. Size the title to its track: a narrow
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 100" width="560" height="100"><defs><clipPath id="cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 100" width="560" height="100"><defs><clipPath id="cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments" role="img" aria-label="Search tickets"><g/><g transform="translate(53 46.547)"><text x="0" y="0" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(174, 174, 178)">Search tickets</text></g></g><g clip-path="url(#cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 100" width="560" height="100"><defs><clipPath id="cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g clip-path="url(#cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 560 100" width="560" height="100"><defs><clipPath id="cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments" role="img" aria-label="Search tickets"><g/><g transform="translate(53 46.547)"><text x="0" y="0" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(110, 110, 115)">Search tickets</text></g></g><g clip-path="url(#cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 592 292" width="592" height="292"><defs><clipPath id="cp0"><rect x="16" y="38" width="560" height="100"/></clipPath><clipPath id="cp1"><rect x="16" y="176" width="560" height="100"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="560" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="560" height="100" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="154" width="560" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="176" width="560" height="100" rx="0"/></clipPath></defs><rect x="0" y="0" width="592" height="292" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Text with atomic tokens</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="560" height="100"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34" width="16" height="16"/></clipPath><clipPath id="svgimg4ct2"><rect x="53" y="32.5" width="66.8" height="17"/></clipPath><clipPath id="svgimg4ct3"><rect x="129" y="33.9" width="41.1" height="18"/></clipPath><clipPath id="svgimg4cp4"><rect x="175" y="37" width="11.3" height="11.5"/></clipPath><clipPath id="svgimg4ct6"><rect x="191.7" y="32.5" width="50.7" height="17"/></clipPath><clipPath id="svgimg4cp7"><rect x="512" y="35" width="14" height="14"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="53" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(245,245,247)">payments </text><rect x="121.8" y="33.9" width="67.9" height="18" rx="9" fill="rgb(40,57,66)"/><text x="129" y="46.86" font-family="system-ui, "-apple-system", sans-serif" font-size="12" fill="rgb(138,203,255)">is:open</text><g clip-path="url(#svgimg4cp4)"><g color="rgb(138, 203, 255)"><clipPath id="svgimg4svgic5"><rect x="175.1" y="37.3" width="11.2" height="11.2"/></clipPath><g clip-path="url(#svgimg4svgic5)"><g transform="translate(175.094 37.266)scale(.46615)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="191.69" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(245,245,247)">is:open </text><g clip-path="url(#svgimg4cp7)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic8"><rect x="512.2" y="35.2" width="13.6" height="13.6"/></clipPath><g clip-path="url(#svgimg4svgic8)"><g transform="translate(512.203 35.203)scale(.5664)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g><text x="16" y="166" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Empty, expanded</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="176" width="560" height="100"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 176)"><defs><clipPath id="svgimg7cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g clip-path="url(#svgimg7cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg7svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 592 292" width="592" height="292"><defs><clipPath id="cp0"><rect x="16" y="38" width="560" height="100"/></clipPath><clipPath id="cp1"><rect x="16" y="176" width="560" height="100"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="560" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="560" height="100" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="154" width="560" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="176" width="560" height="100" rx="0"/></clipPath></defs><rect x="0" y="0" width="592" height="292" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Text with atomic tokens</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="560" height="100"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34" width="16" height="16"/></clipPath><clipPath id="svgimg4ct2"><rect x="53" y="32.5" width="66.8" height="17"/></clipPath><clipPath id="svgimg4ct3"><rect x="129" y="33.9" width="41.1" height="18"/></clipPath><clipPath id="svgimg4cp4"><rect x="175" y="37" width="11.3" height="11.5"/></clipPath><clipPath id="svgimg4ct6"><rect x="191.7" y="32.5" width="50.7" height="17"/></clipPath><clipPath id="svgimg4cp7"><rect x="512" y="35" width="14" height="14"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="53" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(245,245,247)">payments </text><rect x="121.8" y="33.9" width="67.9" height="18" rx="9" fill="rgb(40,57,66)"/><text x="129" y="46.86" font-family="system-ui, "-apple-system", sans-serif" font-size="12" fill="rgb(138,203,255)">is:open</text><g clip-path="url(#svgimg4cp4)"><g color="rgb(138, 203, 255)"><clipPath id="svgimg4svgic5"><rect x="175.1" y="37.3" width="11.2" height="11.2"/></clipPath><g clip-path="url(#svgimg4svgic5)"><g transform="translate(175.094 37.266)scale(.46615)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(138, 203, 255)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="191.69" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(245,245,247)">is:open </text><g clip-path="url(#svgimg4cp7)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg4svgic8"><rect x="512.2" y="35.2" width="13.6" height="13.6"/></clipPath><g clip-path="url(#svgimg4svgic8)"><g transform="translate(512.203 35.203)scale(.5664)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g><text x="16" y="166" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Empty, expanded</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="176" width="560" height="100"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 176)"><defs><clipPath id="svgimg7cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(28,28,30)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(253,253,255,0.196)" stroke-width="1"/><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments" role="img" aria-label="Search tickets"><g/><g transform="translate(53 46.547)"><text x="0" y="0" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(174, 174, 178)">Search tickets</text></g></g><g clip-path="url(#svgimg7cp0)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg7svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 592 292" width="592" height="292"><defs><clipPath id="cp0"><rect x="16" y="38" width="560" height="100"/></clipPath><clipPath id="cp1"><rect x="16" y="176" width="560" height="100"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="560" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="560" height="100" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="154" width="560" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="176" width="560" height="100" rx="0"/></clipPath></defs><rect x="0" y="0" width="592" height="292" rx="0" fill="rgb(255,255,255)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Text with atomic tokens</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="560" height="100"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34" width="16" height="16"/></clipPath><clipPath id="svgimg4ct2"><rect x="53" y="32.5" width="66.8" height="17"/></clipPath><clipPath id="svgimg4ct3"><rect x="129" y="33.9" width="41.1" height="18"/></clipPath><clipPath id="svgimg4cp4"><rect x="175" y="37" width="11.3" height="11.5"/></clipPath><clipPath id="svgimg4ct6"><rect x="191.7" y="32.5" width="50.7" height="17"/></clipPath><clipPath id="svgimg4cp7"><rect x="512" y="35" width="14" height="14"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg4svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="53" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(29,29,31)">payments </text><rect x="121.8" y="33.9" width="67.9" height="18" rx="9" fill="rgb(214,233,249)"/><text x="129" y="46.86" font-family="system-ui, "-apple-system", sans-serif" font-size="12" fill="rgb(12,98,243)">is:open</text><g clip-path="url(#svgimg4cp4)"><g color="rgb(12, 98, 243)"><clipPath id="svgimg4svgic5"><rect x="175.1" y="37.3" width="11.2" height="11.2"/></clipPath><g clip-path="url(#svgimg4svgic5)"><g transform="translate(175.094 37.266)scale(.46615)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="191.69" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(29,29,31)">is:open </text><g clip-path="url(#svgimg4cp7)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg4svgic8"><rect x="512.2" y="35.2" width="13.6" height="13.6"/></clipPath><g clip-path="url(#svgimg4svgic8)"><g transform="translate(512.203 35.203)scale(.5664)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g><text x="16" y="166" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Empty, expanded</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="176" width="560" height="100"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 176)"><defs><clipPath id="svgimg7cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g clip-path="url(#svgimg7cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg7svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 592 292" width="592" height="292"><defs><clipPath id="cp0"><rect x="16" y="38" width="560" height="100"/></clipPath><clipPath id="cp1"><rect x="16" y="176" width="560" height="100"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="560" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="560" height="100" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="154" width="560" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="176" width="560" height="100" rx="0"/></clipPath></defs><rect x="0" y="0" width="592" height="292" rx="0" fill="rgb(255,255,255)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Text with atomic tokens</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="560" height="100"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34" width="16" height="16"/></clipPath><clipPath id="svgimg4ct2"><rect x="53" y="32.5" width="66.8" height="17"/></clipPath><clipPath id="svgimg4ct3"><rect x="129" y="33.9" width="41.1" height="18"/></clipPath><clipPath id="svgimg4cp4"><rect x="175" y="37" width="11.3" height="11.5"/></clipPath><clipPath id="svgimg4ct6"><rect x="191.7" y="32.5" width="50.7" height="17"/></clipPath><clipPath id="svgimg4cp7"><rect x="512" y="35" width="14" height="14"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg4svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg4svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="53" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(29,29,31)">payments </text><rect x="121.8" y="33.9" width="67.9" height="18" rx="9" fill="rgb(214,233,249)"/><text x="129" y="46.86" font-family="system-ui, "-apple-system", sans-serif" font-size="12" fill="rgb(12,98,243)">is:open</text><g clip-path="url(#svgimg4cp4)"><g color="rgb(12, 98, 243)"><clipPath id="svgimg4svgic5"><rect x="175.1" y="37.3" width="11.2" height="11.2"/></clipPath><g clip-path="url(#svgimg4svgic5)"><g transform="translate(175.094 37.266)scale(.46615)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(12, 98, 243)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><text x="191.69" y="46.55" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(29,29,31)">is:open </text><g clip-path="url(#svgimg4cp7)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg4svgic8"><rect x="512.2" y="35.2" width="13.6" height="13.6"/></clipPath><g clip-path="url(#svgimg4svgic8)"><g transform="translate(512.203 35.203)scale(.5664)"><path d="M18 6 6 18" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="m6 6 12 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g><text x="16" y="166" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(110,110,115)">Empty, expanded</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="176" width="560" height="100"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 176)"><defs><clipPath id="svgimg7cp0"><rect x="29" y="34" width="16" height="16"/></clipPath></defs><rect x="20" y="20" width="520" height="44" rx="22" fill="rgb(255,255,255)"/><rect x="20.5" y="20.5" width="519" height="43" rx="21.5" fill="none" stroke="rgba(0,0,28,0.18)" stroke-width="1"/><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments" role="img" aria-label="Search tickets"><g/><g transform="translate(53 46.547)"><text x="0" y="0" font-family="system-ui, "-apple-system", sans-serif" font-size="14" fill="rgb(110, 110, 115)">Search tickets</text></g></g><g clip-path="url(#svgimg7cp0)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg7svgic1"><rect x="29" y="34" width="16" height="16"/></clipPath><g clip-path="url(#svgimg7svgic1)"><g transform="translate(29 34)scale(.66667)"><path d="m21 21-4.3-4.3" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><circle cx="11" cy="11" r="8" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g></g></g></g></g></svg>
|
package/docs/design/templates.md
CHANGED
|
@@ -19,7 +19,7 @@ picture): `Select` renders a Web Awesome custom element that needs its runtime
|
|
|
19
19
|
registered, so it has no faithful static capture; `LucideIcon` and
|
|
20
20
|
`DisclosureArrow` are decorative primitives best seen inside the components that
|
|
21
21
|
use them; `ResizableRegion` and the whole-screen layouts (`NavStack`,
|
|
22
|
-
`SplitView`, `Workbench`, `
|
|
22
|
+
`SplitView`, `Workbench`, `TabNavigator`) and the `Catalog` shell are
|
|
23
23
|
interaction-/viewport-driven screens rather than component cards — the live UX
|
|
24
24
|
catalog and the app-layouts docs cover those.
|
|
25
25
|
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
},
|
|
52
52
|
"exceptions": [
|
|
53
53
|
{
|
|
54
|
-
"id": "legacy-
|
|
55
|
-
"rules": ["KUI-
|
|
56
|
-
"target": "src/features/legacy-report/report-
|
|
57
|
-
"rationale": "The
|
|
54
|
+
"id": "legacy-list-header",
|
|
55
|
+
"rules": ["KUI-C103"],
|
|
56
|
+
"target": "src/features/legacy-report/report-list-header.tsx",
|
|
57
|
+
"rationale": "The legacy report adapter owns disclosure content and its expanded state."
|
|
58
58
|
}
|
|
59
59
|
]
|
|
60
60
|
}
|
package/docs/layout.md
CHANGED
|
@@ -80,7 +80,7 @@ on the Pane; it defaults to `--kui-color-surface`.
|
|
|
80
80
|
`PaneConfig.appearance` forwards through Workbench `mainPane`, panel `pane`,
|
|
81
81
|
and CollapsiblePanel `pane`. Workbench also applies that choice to its main or
|
|
82
82
|
panel region when it renders no Pane chrome. Set `appearance: "sunken"` on a
|
|
83
|
-
`NavStackView` or `
|
|
83
|
+
`NavStackView` or `TabNavigatorTab` when its view or scene owns scrolling.
|
|
84
84
|
For a `SplitView`, put a `Pane` in the list or detail region and set its
|
|
85
85
|
appearance; SplitView only arranges the regions and does not own their scroll.
|
|
86
86
|
Choose the innermost owner when composing layouts.
|
|
@@ -122,7 +122,7 @@ and the footer's top line, whatever the chrome holds — a `Toolbar`, a
|
|
|
122
122
|
whose tabs are scrolled out of view). That includes the panes a `Workbench`,
|
|
123
123
|
`CollapsiblePanel`, or `Catalog` renders; `wireCatalog` installs it for its
|
|
124
124
|
own root. It also covers every `NavStack` (the top chrome's bottom line and the
|
|
125
|
-
bottom toolbar's top line, around the active view) and every `
|
|
125
|
+
bottom toolbar's top line, around the active view) and every `TabNavigator`
|
|
126
126
|
(the bar's top line, over the active scene). The layout keys on whichever
|
|
127
127
|
element actually scrolls there: the view or scene itself, or, through a sole
|
|
128
128
|
child with no chrome of its own on that edge, a `Pane`'s content or a nested
|
|
@@ -140,7 +140,7 @@ for a root already has scroll dividers there and does not need another call.
|
|
|
140
140
|
The wiring only reports state; every component draws its own line. It writes
|
|
141
141
|
`data-scroll-overflow` (the edges with content hidden beyond them, in canonical
|
|
142
142
|
`t`/`r`/`b`/`l` order) on each scroller and `data-scroll-divider` (the sides to
|
|
143
|
-
draw) on each piece of chrome, and the Pane, NavStack,
|
|
143
|
+
draw) on each piece of chrome, and the Pane, NavStack, TabNavigator, TabBar,
|
|
144
144
|
Toolbar, and List stylesheets draw from those. The line is an inset shadow or a pseudo-element
|
|
145
145
|
inside the component, so no state ever moves the chrome, the content, or a tab.
|
|
146
146
|
Never write a border onto a component to show one.
|
|
@@ -150,7 +150,7 @@ the scroll state and draws nothing until the wiring runs; `always` (the sunken
|
|
|
150
150
|
pane default) keeps both lines; `none` drops them. Explicit values override
|
|
151
151
|
either default. Layouts forward it through `PaneConfig`
|
|
152
152
|
(`mainPane.chromeDividers`, a panel's `pane.chromeDividers`). A `NavStack` and a
|
|
153
|
-
`
|
|
153
|
+
`TabNavigator` take the same `chromeDividers` for their own chrome (the stack's
|
|
154
154
|
top chrome and bottom toolbar, the scaffold's bar), and a `SplitView` forwards
|
|
155
155
|
it to its compact stack through `compactStack`.
|
|
156
156
|
|
|
@@ -315,10 +315,13 @@ inset. Most interactive rows and toolbar groups are 44px tall.
|
|
|
315
315
|
Toolbar groups reserve a real 1px outer border around a 42px inner area, even
|
|
316
316
|
when their border and background are transparent.
|
|
317
317
|
A `Toolbar` lays its zones out against one 44px control band at its top: an
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
318
|
+
ordinary `ToolbarText`, `ToolbarControlGroup`, or standalone trailing
|
|
319
|
+
`wa-button` no taller than the band is centered in it by its own size, and a
|
|
320
|
+
taller one (a wrapped title, a second trailing row) starts at the band's top
|
|
321
|
+
and grows down, so it never moves the other controls. A wrapped `ToolbarText`
|
|
322
|
+
centers its first line in the band. Other direct zone content centers against
|
|
323
|
+
the zone's full height by default, including when a sibling makes that zone
|
|
324
|
+
taller than the control band.
|
|
322
325
|
The leading zone clips a shrinking title but reserves 4px of paint overflow
|
|
323
326
|
for the focus outline of a control at its edge. Focus rings in all three zones
|
|
324
327
|
remain visible at narrow and wide widths.
|
package/docs/recipes.md
CHANGED
|
@@ -150,7 +150,7 @@ pushes/pops it, `NavStack` renders it, and `wireNavStack` slides the content and
|
|
|
150
150
|
settles the chrome (reduced motion collapses the slide to instant). See the
|
|
151
151
|
layout guide
|
|
152
152
|
[`app-layouts.md`](app-layouts.md) for choosing among `NavStack`, `SplitView`,
|
|
153
|
-
`Workbench`, and `
|
|
153
|
+
`Workbench`, and `TabNavigator`.
|
|
154
154
|
|
|
155
155
|
## Loading inspector
|
|
156
156
|
|