@kerfjs/ui 5.0.0-beta.62 → 5.0.0-beta.64
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 +4 -0
- package/ai/component-catalog-extension.schema.json +13 -0
- package/ai/component-catalog.json +13 -2
- package/ai/component-composition.json +15 -2
- package/ai/components/list-item.md +1 -1
- package/ai/components/workbench.md +4 -2
- package/ai/public-api-signatures-v1.md +151 -44
- package/ai/skill.md +9 -5
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +3 -2
- package/catalog-projection-cli.mjs +96 -0
- package/catalog-projection.d.mts +55 -0
- package/catalog-projection.mjs +62 -0
- package/dist/browser/catalog.js +1 -1
- package/dist/browser/collapsible-panel.js +2 -0
- package/dist/browser/nav-stack.js +1 -0
- package/dist/browser/split-view.js +1 -0
- package/dist/browser/toolbar-control-group.js +1 -0
- package/dist/browser/workbench.js +1 -0
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +11 -10
- package/dist/catalog.js.map +1 -1
- package/dist/chip.d.ts +9 -3
- package/dist/chip.js +1 -1
- package/dist/{chunk-UCKKT6KO.js → chunk-2EKHENQK.js} +7 -1
- package/dist/chunk-2EKHENQK.js.map +1 -0
- package/dist/{chunk-OD2VXAPL.js → chunk-3BYFWTP3.js} +4 -3
- package/dist/chunk-3BYFWTP3.js.map +1 -0
- package/dist/{chunk-5Q3N6EV7.js → chunk-5IJ6UGNZ.js} +3 -3
- package/dist/{chunk-5Q3N6EV7.js.map → chunk-5IJ6UGNZ.js.map} +1 -1
- package/dist/{chunk-KROD7KZK.js → chunk-AUVG54KC.js} +2 -2
- package/dist/{chunk-KROD7KZK.js.map → chunk-AUVG54KC.js.map} +1 -1
- package/dist/{chunk-AUKT3KMG.js → chunk-CQHN45XR.js} +17 -2
- package/dist/chunk-CQHN45XR.js.map +1 -0
- package/dist/{chunk-SWVW56CV.js → chunk-EN4LDR5Y.js} +2 -2
- package/dist/{chunk-SWVW56CV.js.map → chunk-EN4LDR5Y.js.map} +1 -1
- package/dist/{chunk-4MG3KXJM.js → chunk-F7OCOBTG.js} +2 -2
- package/dist/{chunk-4MG3KXJM.js.map → chunk-F7OCOBTG.js.map} +1 -1
- package/dist/{chunk-KYDDCJXU.js → chunk-HXCMWANP.js} +4 -4
- package/dist/{chunk-KYDDCJXU.js.map → chunk-HXCMWANP.js.map} +1 -1
- package/dist/{chunk-ENGVYQPG.js → chunk-IA4D5XNT.js} +60 -10
- package/dist/chunk-IA4D5XNT.js.map +1 -0
- package/dist/{chunk-F4QMLOXJ.js → chunk-IAOAZUOO.js} +2 -2
- package/dist/{chunk-F4QMLOXJ.js.map → chunk-IAOAZUOO.js.map} +1 -1
- package/dist/{chunk-VCBTX62E.js → chunk-J3KGJ6P6.js} +2 -2
- package/dist/chunk-J3KGJ6P6.js.map +1 -0
- package/dist/{chunk-X6ADHJNI.js → chunk-KFYANKJI.js} +25 -6
- package/dist/chunk-KFYANKJI.js.map +1 -0
- package/dist/{chunk-A3CKOW2R.js → chunk-M5H2RMCH.js} +165 -26
- package/dist/chunk-M5H2RMCH.js.map +1 -0
- package/dist/chunk-MOSIE4Z2.js +51 -0
- package/dist/chunk-MOSIE4Z2.js.map +1 -0
- package/dist/{chunk-RRB26JRJ.js → chunk-NSVLUDUW.js} +19 -4
- package/dist/chunk-NSVLUDUW.js.map +1 -0
- package/dist/{chunk-7JUBXOIV.js → chunk-NXWE5S57.js} +25 -6
- package/dist/chunk-NXWE5S57.js.map +1 -0
- package/dist/chunk-RGS4WX2M.js +44 -0
- package/dist/chunk-RGS4WX2M.js.map +1 -0
- package/dist/chunk-SH6F3CCG.js +80 -0
- package/dist/chunk-SH6F3CCG.js.map +1 -0
- package/dist/{chunk-EAC4CDY7.js → chunk-SMZGAPCU.js} +15 -2
- package/dist/chunk-SMZGAPCU.js.map +1 -0
- package/dist/{chunk-NNMLEDMD.js → chunk-TJK44RQC.js} +64 -11
- package/dist/chunk-TJK44RQC.js.map +1 -0
- package/dist/{chunk-6ZXOQEAN.js → chunk-WF75U3V4.js} +7 -1
- package/dist/chunk-WF75U3V4.js.map +1 -0
- package/dist/collapsible-panel.d.ts +18 -7
- package/dist/collapsible-panel.js +19 -3
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/content-item.d.ts +40 -5
- package/dist/content-item.js +1 -1
- package/dist/disclosure-arrow.js +2 -1
- package/dist/grid.d.ts +5 -1
- package/dist/grid.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +20 -20
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/lucide-icon.d.ts +5 -2
- package/dist/lucide-icon.js +2 -1
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +2 -1
- package/dist/pane.js +1 -1
- package/dist/{panel-toolbar-DqwtBxQL.d.ts → panel-toolbar-DDKh4uKd.d.ts} +11 -2
- package/dist/popup-menu-register.js +216 -3
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.d.ts +4 -3
- package/dist/popup-menu.js +1 -1
- package/dist/select.js +1 -1
- package/dist/split-view.js +2 -1
- package/dist/split-view.js.map +1 -1
- package/dist/styles/catalog/components/catalog-example.css +4 -0
- package/dist/styles/chip.css +14 -0
- package/dist/styles/content-item.css +45 -0
- package/dist/styles/grid.css +7 -0
- package/dist/styles/list-action-row.css +4 -3
- package/dist/styles/list-header.css +4 -3
- package/dist/styles/list-item.css +21 -11
- package/dist/styles/lucide-icon.css +5 -0
- package/dist/styles/pane.css +3 -2
- package/dist/styles/popup-menu.css +24 -10
- package/dist/styles/segmented-control.css +3 -0
- package/dist/styles/select.css +11 -0
- package/dist/styles/sunken-panel.css +7 -0
- package/dist/styles/text.css +29 -0
- package/dist/styles/token-search-field.css +51 -11
- package/dist/styles/toolbar-control-group.css +49 -0
- package/dist/styles/workbench.css +130 -2
- package/dist/sunken-panel.d.ts +6 -1
- package/dist/sunken-panel.js +1 -1
- package/dist/text.d.ts +14 -3
- package/dist/text.js +1 -1
- package/dist/{token-search-field-DvgFLhLL.d.ts → token-search-field-Xk8jiw8Y.d.ts} +18 -4
- package/dist/token-search-field.d.ts +1 -1
- package/dist/token-search-field.js +2 -1
- package/dist/token-search-model.d.ts +1 -1
- package/dist/toolbar-control-group.d.ts +5 -1
- package/dist/toolbar-control-group.js +2 -1
- package/dist/toolbar.d.ts +5 -2
- package/dist/toolbar.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-content-items.d.ts +9 -0
- package/dist/wire-content-items.js +66 -0
- package/dist/wire-content-items.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/wire-token-search-fields.js +2 -1
- package/dist/wire-workbench.d.ts +7 -0
- package/dist/wire-workbench.js +1 -1
- package/dist/workbench.d.ts +24 -8
- package/dist/workbench.js +2 -1
- package/docs/accessibility.md +30 -6
- package/docs/catalog.md +42 -2
- package/docs/collapsible-panel.md +8 -1
- package/docs/component-contract.md +43 -5
- package/docs/component-selection.md +46 -8
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/examples/component-catalog-extension.json +6 -0
- package/docs/layout.md +56 -9
- package/docs/sunken-panel.md +22 -0
- package/docs/surface-scaffold.md +6 -3
- package/docs/ui-analyzer.md +4 -0
- package/docs/ux-demo.md +1 -0
- package/docs/workbench.md +42 -4
- package/llms.txt +9 -5
- package/package.json +16 -2
- package/scripts/component-catalog-extension-validation.mjs +28 -0
- package/dist/chunk-4R777DUZ.js +0 -34
- package/dist/chunk-4R777DUZ.js.map +0 -1
- package/dist/chunk-6ZXOQEAN.js.map +0 -1
- package/dist/chunk-7JUBXOIV.js.map +0 -1
- package/dist/chunk-A3CKOW2R.js.map +0 -1
- package/dist/chunk-AUKT3KMG.js.map +0 -1
- package/dist/chunk-EAC4CDY7.js.map +0 -1
- package/dist/chunk-ENGVYQPG.js.map +0 -1
- package/dist/chunk-MA73TA6D.js +0 -42
- package/dist/chunk-MA73TA6D.js.map +0 -1
- package/dist/chunk-N2DRU35S.js +0 -45
- package/dist/chunk-N2DRU35S.js.map +0 -1
- package/dist/chunk-NNMLEDMD.js.map +0 -1
- package/dist/chunk-OD2VXAPL.js.map +0 -1
- package/dist/chunk-RRB26JRJ.js.map +0 -1
- package/dist/chunk-UCKKT6KO.js.map +0 -1
- package/dist/chunk-VCBTX62E.js.map +0 -1
- package/dist/chunk-X6ADHJNI.js.map +0 -1
|
@@ -202,11 +202,16 @@ whole label. `divider` owns a before or after separator. Set
|
|
|
202
202
|
`--kui-list-item-*` tokens control its row, icon, label, and trailing geometry
|
|
203
203
|
and color. `ListHeader` exposes `--kui-list-header-min-height`, title padding,
|
|
204
204
|
title minimum height, and border-width tokens for section density.
|
|
205
|
+
Set `--kui-list-group-divider-color` on a containing `List` to give
|
|
206
|
+
`ListHeader`, `ListItem`, and `ListActionRow` the same before/after divider
|
|
207
|
+
color; each row otherwise uses the quiet neutral border tone.
|
|
205
208
|
For a filled command list, set `--kui-list-item-background` and
|
|
206
|
-
`--kui-list-item-border` on the list or row.
|
|
207
|
-
`--kui-list-item-hover-
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
`--kui-list-item-border` on the list or row. Scope `--kui-list-item-color`,
|
|
210
|
+
`--kui-list-item-hover-background`, `--kui-list-item-selected-color`, and
|
|
211
|
+
`--kui-list-item-selected-background` at the same boundary for text and state
|
|
212
|
+
fills. The matching `--kui-list-item-hover-border` and
|
|
213
|
+
`--kui-list-item-selected-border` tokens set state outlines without replacing
|
|
214
|
+
ListItem CSS or neutralizing global semantic border colors.
|
|
210
215
|
|
|
211
216
|
Use `ListItemLink` from `@kerfjs/ui/list-item` for a navigation row with a
|
|
212
217
|
real `href`. It shares `ListItem` content slots, density, selection, and row
|
|
@@ -276,7 +281,8 @@ For a compact `Select`, set `triggerWidth` to `"fit-content"`, `"max-content"`,
|
|
|
276
281
|
or `"fill"` and cap it with `--kui-select-trigger-max-width` when needed.
|
|
277
282
|
For a round icon-only toolbar trigger, set `selectedPresentation="icon-only"`
|
|
278
283
|
and `caret={false}`. The control keeps its accessible name, current choice help
|
|
279
|
-
tag, and keyboard-operated listbox; the
|
|
284
|
+
tag, and keyboard-operated listbox; the selected icon stays centered even when
|
|
285
|
+
`renderSelected` supplies it. The default keeps the visible caret.
|
|
280
286
|
Custom `renderSelected` text inherits the control color by default; the
|
|
281
287
|
`--kui-select-selected-color`, `--kui-select-selected-font-size`, and
|
|
282
288
|
`--kui-select-selected-font-weight` tokens configure its typography. Plain
|
|
@@ -327,6 +333,13 @@ For common structured search, use `createTokenSearchModel` from `@kerfjs/ui/toke
|
|
|
327
333
|
For a sibling date picker or other app helper, call `model.commit(value)` while a `name:` prefix is active. It parses and commits that value for the active rule even when it is absent from suggestions, replacing the unfinished prefix text. Invalid values and calls without an active prefix leave the query unchanged; `choose(value)` remains restricted to suggested tokens.
|
|
328
334
|
To apply a saved search or restore a query programmatically, call `model.replace({ query, tokens })`. It publishes parsed state and rebuilds the DOM-owned editor text even when no chip changed. For a field without a model, change the field's `revision` prop when setting `query` yourself.
|
|
329
335
|
When one root contains both kinds of field, a registered model enables chip keyboard behavior only for its own field. Other fields keep native editing unless the root opts into `keyboard` with an application removal callback.
|
|
336
|
+
For an icon action at the end of the field, pass `trailingAction` with `icon`,
|
|
337
|
+
accessible `label`, and delegated `action` (plus optional `id`). The component
|
|
338
|
+
renders a button that fills the trailing hit target. Reserve `trailing` for
|
|
339
|
+
passive content such as a shortcut hint.
|
|
340
|
+
Set `fill` on a collapsible `TokenSearchField` in a stretched Toolbar center to
|
|
341
|
+
use the available width when expanded; the field and its search group retain
|
|
342
|
+
their compact widths when collapsed.
|
|
330
343
|
|
|
331
344
|
## Toolbar composition
|
|
332
345
|
|
|
@@ -357,8 +370,18 @@ example `b`, `tr`, or `trbl`) only when the toolbar owns a permanent separator
|
|
|
357
370
|
edge. Dividers earn their place: never fake one with a border or pad below one
|
|
358
371
|
to make it look right.
|
|
359
372
|
|
|
373
|
+
`Toolbar` renders a semantic `header` by default. Set `position="footer"`
|
|
374
|
+
for a toolbar at the bottom of a pane or page; Workbench's
|
|
375
|
+
`mainBottomToolbar` and the catalog resource bar apply this automatically.
|
|
376
|
+
The position changes the HTML element without changing zones or geometry.
|
|
377
|
+
|
|
360
378
|
Common toolbar patterns:
|
|
361
379
|
|
|
380
|
+
For a long-running icon action, set `busy` on its single-control
|
|
381
|
+
`ToolbarControlGroup` and supply a descriptive `busyLabel`. The group preserves
|
|
382
|
+
the control's dimensions, shows `LoadingSpinner` in its icon slot, sets
|
|
383
|
+
`aria-busy`, and makes the control inert until the app clears `busy`.
|
|
384
|
+
|
|
362
385
|
| Want | Put in the zone | Notes |
|
|
363
386
|
| ----------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
364
387
|
| Identity or title text | `<ToolbarText text="…" size="large" />` (or `xlarge` for a page/panel title that fits) | Wrap in a `single` borderless group only when it must align with adjacent control pills |
|
|
@@ -418,9 +441,12 @@ items shape covers single-line and batch actions; compute each batch child's
|
|
|
418
441
|
```
|
|
419
442
|
|
|
420
443
|
For a flat command menu with persistent sort choices, group commands under
|
|
421
|
-
`heading` entries and set `
|
|
422
|
-
|
|
423
|
-
|
|
444
|
+
`heading` entries and set `checked` explicitly on each choice. Checked rows
|
|
445
|
+
show a checkmark; the background marks the current keyboard row, as in `Select`.
|
|
446
|
+
Only items with `checked: true` or `checked: false` reserve checkmark space.
|
|
447
|
+
Omit `checked` for a plain command, including one beside checkbox items.
|
|
448
|
+
Commands still dispatch their own `data-action` once on pointer and keyboard
|
|
449
|
+
selection.
|
|
424
450
|
|
|
425
451
|
For a row opened by right-click, render `PopupMenu` with `context`, `label`,
|
|
426
452
|
and a stable root `data-*` marker. Its trigger is an invisible anchor removed
|
|
@@ -469,6 +495,12 @@ geometry and 44px targets.
|
|
|
469
495
|
</Pane>
|
|
470
496
|
```
|
|
471
497
|
|
|
498
|
+
When that child is a selectable card, configure `ContentItem` with
|
|
499
|
+
`interactive`, `action`, `itemId`, and a `selectionMode`; wire
|
|
500
|
+
`wireContentItems` once for Enter and Space. The component owns selection,
|
|
501
|
+
hover, focus, and disabled paint in its reserved 1px frame (see
|
|
502
|
+
[Content items](./layout.md#content-items)).
|
|
503
|
+
|
|
472
504
|
Incorrect: duplicating component-like rows and compensating for nested padding
|
|
473
505
|
forks the package anatomy and spacing contract.
|
|
474
506
|
|
|
@@ -489,6 +521,12 @@ The application updates its tag list after the action. `size="compact"` uses a
|
|
|
489
521
|
20px chip with a 16px remove button, and `disabled` disables removal. Tone,
|
|
490
522
|
appearance, and shape use the same semantic choices as `Badge`; use `Badge`
|
|
491
523
|
when no removal is needed and the content is status or count metadata.
|
|
524
|
+
Pass an unsized, decorative `LucideIcon` through `icon` for a leading glyph;
|
|
525
|
+
Chip sizes it to its own type scale and aligns it beside the label. For a long
|
|
526
|
+
plain-text label, set `truncate`: the chip can shrink within a `Row`, its label
|
|
527
|
+
gets a one-line ellipsis, and the full string is the label's native `title`.
|
|
528
|
+
Keep a price or other unbreakable sibling in `Text wrap="nowrap"`. `truncate`
|
|
529
|
+
requires a string label so the title cannot lose text hidden inside markup.
|
|
492
530
|
|
|
493
531
|
```tsx
|
|
494
532
|
<Chip
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"/><g clip-path="url(#ov1)"><rect x="28.5" y="28.5" width="91" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="38" y="55.41" font-family=""ui-sans-serif", "-apple-system", "system-ui", "Segoe UI", sans-serif" font-size="16" font-weight="650" fill="rgb(174,174,178)">Northstar</text></g></g></g></g></g><rect x="488" y="28" width="124" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="488.5" y="28.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="490.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(174, 174, 178)"><clipPath id="svgic7"><rect x="502" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(502 42)scale(.66667)"><path d="M3 5z" 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="M3 12z" 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="M3 19z" 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="M8 5h13" 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="M8 12h13" 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="M8 19h13" 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><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(174, 174, 178)"><clipPath id="svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(542 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" 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="M9 3v18" 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="M15 3v18" 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><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp10)"><g color="rgb(174, 174, 178)"><clipPath id="svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" 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="12" cy="12" r="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"/></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 104" width="640" height="104"><defs><clipPath id="cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#cp0)"/><g clip-path="url(#ov1)"><rect x="28.5" y="28.5" width="91" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g clip-path="url(#ov3)"><g clip-path="url(#cp4)"><g clip-path="url(#ct5)"><text x="38" y="55.41" font-family=""ui-sans-serif", "-apple-system", "system-ui", "Segoe UI", sans-serif" font-size="16" font-weight="650" fill="rgb(110,110,115)">Northstar</text></g></g></g></g></g><rect x="488" y="28" width="124" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="488.5" y="28.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="490.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp6)"><g color="rgb(110, 110, 115)"><clipPath id="svgic7"><rect x="502" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic7)"><g transform="translate(502 42)scale(.66667)"><path d="M3 5z" 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="M3 12z" 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="M3 19z" 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="M8 5h13" 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="M8 12h13" 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="M8 19h13" 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><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp8)"><g color="rgb(110, 110, 115)"><clipPath id="svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic9)"><g transform="translate(542 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" 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="M9 3v18" 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="M15 3v18" 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><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp10)"><g color="rgb(110, 110, 115)"><clipPath id="svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" 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="12" cy="12" r="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"/></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#svgimg3cp0)"
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#svgimg3cp0)"/><g clip-path="url(#svgimg3ov1)"><rect x="28.5" y="28.5" width="91" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp2)"><g clip-path="url(#svgimg3ov3)"><g clip-path="url(#svgimg3cp4)"><g clip-path="url(#svgimg3ct5)"><text x="38" y="55.41" font-family=""ui-sans-serif", "-apple-system", "system-ui", "Segoe UI", sans-serif" font-size="16" font-weight="650" fill="rgb(174,174,178)">Northstar</text></g></g></g></g></g><rect x="488" y="28" width="124" height="44" rx="22" fill="rgb(58,58,60)"/><rect x="488.5" y="28.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(72,72,74)" stroke-width="1"/><rect x="490.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp6)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg3svgic7"><rect x="502" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic7)"><g transform="translate(502 42)scale(.66667)"><path d="M3 5z" 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="M3 12z" 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="M3 19z" 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="M8 5h13" 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="M8 12h13" 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="M8 19h13" 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><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp8)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg3svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic9)"><g transform="translate(542 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" 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="M9 3v18" 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="M15 3v18" 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><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp10)"><g color="rgb(174, 174, 178)"><clipPath id="svgimg3svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" 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="12" cy="12" r="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"/></g></g></g></g></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#svgimg3cp0)"
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 672 158" width="672" height="158"><defs><clipPath id="cp0"><rect x="16" y="38" width="640" height="104"/></clipPath><clipPath id="ct1"><rect x="16" y="16" width="640" height="22"/></clipPath><clipPath id="irc2"><rect x="16" y="38" width="640" height="104" rx="0"/></clipPath></defs><rect x="0" y="0" width="672" height="158" 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)">Title with a trailing group</text><g clip-path="url(#cp0)"><g clip-path="url(#irc2)"><clipPath id="svgimg3vclip"><rect x="16" y="38" width="640" height="104"/></clipPath><g clip-path="url(#svgimg3vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg3cp0"><rect x="28" y="28" width="452" height="44"/></clipPath><clipPath id="svgimg3ov1"><rect x="28" y="28" width="452" height="44" rx="0"/></clipPath><clipPath id="svgimg3cp2"><rect x="30" y="30" width="88.1" height="40"/></clipPath><clipPath id="svgimg3ov3"><rect x="30" y="30" width="88.1" height="40" rx="0"/></clipPath><clipPath id="svgimg3cp4"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3ct5"><rect x="38" y="40.4" width="72.1" height="19.2"/></clipPath><clipPath id="svgimg3cp6"><rect x="502" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp8"><rect x="542" y="42" width="16" height="16"/></clipPath><clipPath id="svgimg3cp10"><rect x="582" y="42" width="16" height="16"/></clipPath></defs><g clip-path="url(#svgimg3cp0)"/><g clip-path="url(#svgimg3ov1)"><rect x="28.5" y="28.5" width="91" height="43" rx="21.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp2)"><g clip-path="url(#svgimg3ov3)"><g clip-path="url(#svgimg3cp4)"><g clip-path="url(#svgimg3ct5)"><text x="38" y="55.41" font-family=""ui-sans-serif", "-apple-system", "system-ui", "Segoe UI", sans-serif" font-size="16" font-weight="650" fill="rgb(110,110,115)">Northstar</text></g></g></g></g></g><rect x="488" y="28" width="124" height="44" rx="22" fill="rgb(229,229,234)"/><rect x="488.5" y="28.5" width="123" height="43" rx="21.5" fill="none" stroke="rgb(209,209,214)" stroke-width="1"/><rect x="490.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp6)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic7"><rect x="502" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic7)"><g transform="translate(502 42)scale(.66667)"><path d="M3 5z" 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="M3 12z" 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="M3 19z" 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="M8 5h13" 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="M8 12h13" 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="M8 19h13" 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><rect x="530.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp8)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic9"><rect x="542" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic9)"><g transform="translate(542 42)scale(.66667)"><rect width="18" height="18" x="3" y="3" rx="2" 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="M9 3v18" 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="M15 3v18" 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><rect x="570.5" y="30.5" width="39" height="39" rx="19.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg3cp10)"><g color="rgb(110, 110, 115)"><clipPath id="svgimg3svgic11"><rect x="582" y="42" width="16" height="16"/></clipPath><g clip-path="url(#svgimg3svgic11)"><g transform="translate(582 42)scale(.66667)"><path d="M9.7 4.1a2.3 2.3 0 0 1 4.6 0 2.3 2.3 0 0 0 3.3 2 2.3 2.3 0 0 1 2.4 4 2.3 2.3 0 0 0 0 3.8 2.3 2.3 0 0 1-2.4 4 2.3 2.3 0 0 0-3.3 2 2.3 2.3 0 0 1-4.6 0 2.3 2.3 0 0 0-3.3-2A2.3 2.3 0 0 1 4 14a2.3 2.3 0 0 0 0-3.8 2.3 2.3 0 0 1 2.3-4 2.3 2.3 0 0 0 3.4-2" 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="12" cy="12" r="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"/></g></g></g></g></g></g></g></g></svg>
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"publicClasses": ["acme-filter-chip"],
|
|
19
19
|
"publicTokens": ["--acme-filter-chip-accent"],
|
|
20
|
+
"uses": ["chip"],
|
|
21
|
+
"source": "src/filter-chip.tsx",
|
|
22
|
+
"demoSource": "ux-demo/demos/filter-chip.tsx",
|
|
20
23
|
"geometry": {
|
|
21
24
|
"margin": "none",
|
|
22
25
|
"border": "self",
|
|
@@ -31,6 +34,9 @@
|
|
|
31
34
|
"purpose": "An application inspector composed from Kerf panel, content, and value primitives.",
|
|
32
35
|
"useWhen": ["A selected record needs a titled fact-and-action region."],
|
|
33
36
|
"avoidWhen": ["A ValueTable alone expresses the complete interaction."],
|
|
37
|
+
"uses": ["acme-filter-chip", "toolbar", "value-table"],
|
|
38
|
+
"source": "src/inspector.tsx",
|
|
39
|
+
"demoSource": "ux-demo/demos/inspector.tsx",
|
|
34
40
|
"geometry": {
|
|
35
41
|
"margin": "parent",
|
|
36
42
|
"border": "child",
|
package/docs/layout.md
CHANGED
|
@@ -45,6 +45,9 @@ content scroller; with `chromePlacement="auto"`, the Pane root paints the
|
|
|
45
45
|
surface because it becomes the scroller in a short viewport. Header and footer
|
|
46
46
|
chrome stay on the normal surface. No second scroll container or
|
|
47
47
|
`SunkenPanel` wrapper is needed.
|
|
48
|
+
Sunken panes draw their header/footer dividers by default, even when short
|
|
49
|
+
content does not scroll. Pass `chromeDividers="scroll"` to restore scroll-state
|
|
50
|
+
dividers or `"none"` to hide them.
|
|
48
51
|
For custom chrome colors in auto mode, set `--kui-pane-chrome-background`
|
|
49
52
|
on the Pane; it defaults to `--kui-color-surface`.
|
|
50
53
|
|
|
@@ -116,9 +119,10 @@ Toolbar, and List stylesheets draw from those. The line is an inset shadow or a
|
|
|
116
119
|
inside the component, so no state ever moves the chrome, the content, or a tab.
|
|
117
120
|
Never write a border onto a component to show one.
|
|
118
121
|
|
|
119
|
-
Configure a pane with `chromeDividers`: `scroll` (the default) follows
|
|
120
|
-
scroll state and draws nothing until the wiring runs; `always`
|
|
121
|
-
`none` drops them.
|
|
122
|
+
Configure a pane with `chromeDividers`: `scroll` (the plain-pane default) follows
|
|
123
|
+
the scroll state and draws nothing until the wiring runs; `always` (the sunken
|
|
124
|
+
pane default) keeps both lines; `none` drops them. Explicit values override
|
|
125
|
+
either default. Layouts forward it through `PaneConfig`
|
|
122
126
|
(`mainPane.chromeDividers`, a panel's `pane.chromeDividers`). A `NavStack` and a
|
|
123
127
|
`TabScaffold` take the same `chromeDividers` for their own chrome (the stack's
|
|
124
128
|
top chrome and bottom toolbar, the scaffold's bar), and a `SplitView` forwards
|
|
@@ -184,6 +188,7 @@ import { ContentItem } from "@kerfjs/ui/content-item";
|
|
|
184
188
|
<Pane label="Inspector">
|
|
185
189
|
<ContentItem>{details}</ContentItem>
|
|
186
190
|
<ContentItem frame="framed">{pendingChanges}</ContentItem>
|
|
191
|
+
<ContentItem flush>{markdownPreview}</ContentItem>
|
|
187
192
|
<ContentItem shape="pill">{summary}</ContentItem>
|
|
188
193
|
</Pane>;
|
|
189
194
|
```
|
|
@@ -198,10 +203,31 @@ needs to align with neighboring items is `ListInsetText`. Safe `data-*`
|
|
|
198
203
|
metadata goes in `rootAttributes`. Pass `ariaLabel` only for a distinct named
|
|
199
204
|
region (`role="region"`), and `focusTarget` to make the item a programmatic
|
|
200
205
|
focus target (`tabindex="-1"`), for example a NavStack view's `data-nav-focus`
|
|
201
|
-
target.
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
206
|
+
target. `flush` removes block padding and both block borders while retaining
|
|
207
|
+
the inline margin, padding, and border. Use it for content such as a markdown
|
|
208
|
+
preview that must reach the item's top and bottom edges. `title` passes through
|
|
209
|
+
to the root element as a native tooltip.
|
|
210
|
+
|
|
211
|
+
For a selectable card, set `interactive`, a delegated `action`, and an optional
|
|
212
|
+
`itemId`. Wire `wireContentItems(root)` once on the containing app root; it
|
|
213
|
+
activates focused cards with Enter or Space and forwards the resulting click to
|
|
214
|
+
the app's ordinary `data-action` handler. `selectionMode="toggle"` maps
|
|
215
|
+
`selected` to a button's `aria-pressed`; `selectionMode="single"` maps it to an
|
|
216
|
+
option's `aria-selected` and belongs in an app-owned `role="listbox"` container.
|
|
217
|
+
An interactive card is a Tab stop, and `disabled` removes its action and Tab
|
|
218
|
+
stop while exposing `aria-disabled`. Hover uses the normal neutral fill so it
|
|
219
|
+
remains visible on a lowered surface; hover, pressed, focus, and selected paints
|
|
220
|
+
do not change geometry. A single-action card has no interactive descendants.
|
|
221
|
+
For a rich card with a primary and secondary action, render a static
|
|
222
|
+
`ContentItem` with sibling buttons inside it. Each button then has its own
|
|
223
|
+
focus stop and action without nesting controls inside an interactive card.
|
|
224
|
+
`ListActionRow` already packages this pattern for a simple two-action row.
|
|
225
|
+
`rootAttributes` still accepts safe app `data-*` metadata, while the card owns
|
|
226
|
+
its interaction data.
|
|
227
|
+
|
|
228
|
+
The rendered classes — `.kui-content-item`, `.kui-content-item--framed`,
|
|
229
|
+
`.kui-content-item--pill`, and `.kui-content-item--flush` — stay public for the
|
|
230
|
+
rare element that must carry the
|
|
205
231
|
geometry itself (for example a `<ul>` list or a `Text` paragraph in an
|
|
206
232
|
application-owned adapter). Prefer `ContentItem` everywhere else so the framing
|
|
207
233
|
choice is typed. A plain `<div class="kui-content-item">` is exactly what
|
|
@@ -322,6 +348,14 @@ display copy, and `font="monospace"` for code or identifiers (the
|
|
|
322
348
|
finite props compose with each other and with every semantic `variant`; omit
|
|
323
349
|
them to inherit the surrounding color, size, and font.
|
|
324
350
|
|
|
351
|
+
Control long copy with `wrap`: `normal` (default) restores ordinary wrapping,
|
|
352
|
+
`anywhere` breaks long unbroken strings, `nowrap` holds one line, and
|
|
353
|
+
`truncate` holds one line with an ellipsis. `truncate` sets `min-width: 0`, so
|
|
354
|
+
Text can shrink beside a fixed-size sibling in a `Row`; the sibling keeps its
|
|
355
|
+
width. On `normal` or `anywhere`, set a positive integer `maxLines` to clamp
|
|
356
|
+
wrapped text with an ellipsis. Omit `maxLines` for unlimited lines. The cap is
|
|
357
|
+
incompatible with `nowrap` and `truncate`.
|
|
358
|
+
|
|
325
359
|
```tsx
|
|
326
360
|
import { Text } from "@kerfjs/ui/text";
|
|
327
361
|
|
|
@@ -333,6 +367,9 @@ import { Text } from "@kerfjs/ui/text";
|
|
|
333
367
|
<Text variant="h2" size="xlarge">A display-sized section title</Text>;
|
|
334
368
|
<strong>Inbox<Text variant="span" tone="quiet" size="compact"> · 3 msg</Text></strong>;
|
|
335
369
|
<Text tone="danger" font="monospace">ERR_INVALID_ID</Text>;
|
|
370
|
+
<Text wrap="anywhere">A-very-long-unbroken-identifier</Text>;
|
|
371
|
+
<Text wrap="truncate" variant="span">Long vendor name</Text>;
|
|
372
|
+
<Text wrap="normal" maxLines={2}>A long summary capped at two lines.</Text>;
|
|
336
373
|
```
|
|
337
374
|
|
|
338
375
|
## Spacer
|
|
@@ -383,14 +420,24 @@ import { px } from "@kerfjs/ui/css-values";
|
|
|
383
420
|
<label>Provider <input /></label>
|
|
384
421
|
<label>Endpoint <input /></label>
|
|
385
422
|
</Grid>;
|
|
423
|
+
|
|
424
|
+
<Grid minColumnWidth={px(160)} autoFill gap="m">
|
|
425
|
+
<DocumentTile />
|
|
426
|
+
</Grid>;
|
|
386
427
|
```
|
|
387
428
|
|
|
388
429
|
`columns` must be a positive safe integer; invalid counts throw instead of
|
|
389
430
|
silently producing invalid CSS. Import `px` from `@kerfjs/ui/css-values` for a
|
|
390
431
|
pixel minimum. `columns` and `minColumnWidth` are mutually exclusive. In the
|
|
391
432
|
responsive mode, the container width decides how many equal tracks fit; constrain
|
|
392
|
-
the Grid's outer width when the form should have a maximum count.
|
|
393
|
-
|
|
433
|
+
the Grid's outer width when the form should have a maximum count.
|
|
434
|
+
`autoFill` keeps the unoccupied responsive tracks so one or two tiles retain
|
|
435
|
+
their shared track width rather than expanding across an otherwise empty row.
|
|
436
|
+
It requires `minColumnWidth`; the default `auto-fit` keeps the existing form
|
|
437
|
+
behavior. When Grid is a direct child of a flex-owned `ListInsetControl`, pass
|
|
438
|
+
`flex` so the Grid takes the available row width instead of shrink-wrapping.
|
|
439
|
+
Grid is layout-only and adds no ARIA grid role. The application owns child
|
|
440
|
+
semantics.
|
|
394
441
|
Use application-owned CSS grid for intrinsic, asymmetric, spanning, or masonry
|
|
395
442
|
tracks, and use `ResizableRegion` when people must adjust a boundary.
|
|
396
443
|
|
package/docs/sunken-panel.md
CHANGED
|
@@ -23,6 +23,28 @@ The default `shape="rounded"` uses the shared rounded-rectangle radius. Choose
|
|
|
23
23
|
</SunkenPanel>
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
## Filling a work area
|
|
27
|
+
|
|
28
|
+
Set `fill` when the panel is the direct layout root of a parent with a definite
|
|
29
|
+
height. Inside a flex column, use `flex` so it takes the remaining space and
|
|
30
|
+
can shrink with its parent. Like `Grid`, `flex` accepts `true` (equivalent to
|
|
31
|
+
`1 1 auto`), a CSS flex keyword, or a typed `CssFlex` value. The panel keeps
|
|
32
|
+
`min-height: 0`, allowing its parent to own scrolling.
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<List fill>
|
|
36
|
+
<Toolbar label="Work area" />
|
|
37
|
+
<SunkenPanel flex>
|
|
38
|
+
<WorkArea />
|
|
39
|
+
</SunkenPanel>
|
|
40
|
+
</List>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Inside a `Pane`, the Pane's content remains the scroll owner. Place a
|
|
44
|
+
`SunkenPanel fill` in a definite-height Pane content region when the surface
|
|
45
|
+
itself needs to cover empty space, or use `flex` when a flex parent allocates
|
|
46
|
+
the remaining space. The panel does not add another scroller.
|
|
47
|
+
|
|
26
48
|
## Ownership
|
|
27
49
|
|
|
28
50
|
The root owns its lowered background, 8px padding, and 8px vertical gap.
|
package/docs/surface-scaffold.md
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
`DialogSurface` and `PopupSurface` configure recurring Web Awesome surface
|
|
4
4
|
geometry without application `::part()` overrides. They do not replace Web
|
|
5
|
-
Awesome behavior: the application still owns open state,
|
|
6
|
-
|
|
5
|
+
Awesome behavior: the application still owns open state, dismissal policy, ids,
|
|
6
|
+
labels, and content. With `@kerfjs/ui/popup-menu/register` imported, a dropdown
|
|
7
|
+
inside `PopupSurface` also keeps keyboard item navigation made during its show
|
|
8
|
+
animation when Web Awesome completes its initial focus handoff.
|
|
7
9
|
|
|
8
10
|
Wrap one `wa-dialog` with `DialogSurface`. Choose `size` (`small`, `medium`, or
|
|
9
11
|
`large`), `presentation` (`modal`, `side-sheet`, or `fullscreen`), and independent
|
|
@@ -22,4 +24,5 @@ Wrap one `PopupMenu` (or another single `wa-dropdown`) with `PopupSurface`. `ins
|
|
|
22
24
|
padding for a child that already owns row insets, `compact` uses 4px, and
|
|
23
25
|
`standard` uses the shared 8px surface inset. Keep the dropdown trigger named and
|
|
24
26
|
preserve `data-morph-skip-children` when its upgraded light-DOM items must retain
|
|
25
|
-
identity across Kerf rerenders.
|
|
27
|
+
identity across Kerf rerenders. Import `@kerfjs/ui/popup-menu/register` once for
|
|
28
|
+
the focus handoff fix when wrapping a raw `wa-dropdown`.
|
package/docs/ui-analyzer.md
CHANGED
|
@@ -80,6 +80,10 @@ policy, or analysis inputs to the containing application.
|
|
|
80
80
|
| `KUI-L021` | error | CSS overrides a component token that a typed prop sets. |
|
|
81
81
|
| `KUI-L022` | error | A class placed on a component's root is styled by the application (a hook class). |
|
|
82
82
|
|
|
83
|
+
For `KUI-L004` and `KUI-L007`, scroll and inset declarations belong to the
|
|
84
|
+
subject of each CSS selector. An ancestor class used only to qualify a
|
|
85
|
+
descendant selector is not treated as a scroll owner or inset source.
|
|
86
|
+
|
|
83
87
|
Errors are provable contract violations and make the command exit 1. Review
|
|
84
88
|
findings are deliberately heuristic and do not fail by default; pass
|
|
85
89
|
`--fail-on-review` when a project has reviewed its baseline and wants them to
|
package/docs/ux-demo.md
CHANGED
|
@@ -22,6 +22,7 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
22
22
|
|
|
23
23
|
- It imports public component subpaths, exercising their browser-selected reachable CSS rather than a catalog-only style path.
|
|
24
24
|
- The `ListActionRow` route demonstrates sibling primary/trailing native controls, independent disabled states, controlled selection, first-line leading-icon alignment for wrapped labels, and an application-owned native popover relationship without nesting controls. The `ListItem` route demonstrates the same multiline leading-icon anchor alongside its single-control navigation contract.
|
|
25
|
+
- The `PopupMenu` route's context example opens one app-owned menu either at the row's right-click point or below its adjacent, keyboard-operable Demand actions button. Its interactive row/button composition opts out of the catalog geometry overlay so the overlay's border and margin highlights do not masquerade as a row inset during activation. The Nested decisions example shows the automatic phone-width submenu placement above or below its parent list, with native ArrowLeft return, Escape dismissal, and child selection.
|
|
25
26
|
- The `AppTab` and `TabBar` routes are focused component specimens: AppTab shows its selected, compact, segmented, icon-only, truncation, placeholder, pending, metadata, and close-icon axes inside the required tablist context; TabBar shows its rail, segmented, inspector, allocation, placement, and accessory-zone axes, including an adjacent action plus a separately pinned end action whose tabs overflow at narrow widths, without application readouts. The separate `Application tabs` composition route demonstrates controlled selection, matching panel content, overflow, adding (a new tab opens `pending` with a spinner and stays selectable while its panel shows a `Skeleton` heading until a simulated load completes), closing, keyboard/pointer reordering, and application-owned ordering. The `ResizableRegion` route likewise replaces only the decorative handle glyph while retaining separator semantics and shared wiring.
|
|
26
27
|
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu, and feedback scenarios remain addressable alongside their subcomponents; the root opens the first Kerf component. The former aggregate Web Awesome theme specimen is intentionally omitted because its component families are covered by those focused routes.
|
|
27
28
|
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, recommendation, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Functional groups follow their authored importance order; components precede compositions inside each group, equal-importance entries use alphabetical order, and the Recipes group comes last. Composition names stay concise and project a visible `Composition` sidebar tag. Non-supported Web Awesome recommendations project to a visible `Discouraged` tag, with Popup as the deliberate conditional exception. Demo paths resolve to the matching `ui/ux-demo/demos/<id>.tsx` or `ui/ux-demo/recipes/*.tsx` file, or to `ui/ux-demo/webawesome-demos.tsx` for Web Awesome entries. `ui/ux-demo/main.tsx` owns only the catalog shell, shared state, routing, and interaction wiring. First-party component entries additionally derive `ui/src/<public-subpath>.tsx` from their canonical `delivery.browserImport` or opt-in `delivery.moduleImport`.
|
package/docs/workbench.md
CHANGED
|
@@ -89,10 +89,20 @@ an optional `label`. Common shell behavior is configured rather than restyled:
|
|
|
89
89
|
each exactly at its configured size (its separator border included, as in
|
|
90
90
|
flow) up to the viewport-relative overlay maximum; the content fills the
|
|
91
91
|
panel inside its border, so it is clamped with it;
|
|
92
|
-
- `
|
|
92
|
+
- `overlayBackdrop` on the Workbench opts in to a `--kui-color-scrim` backdrop
|
|
93
|
+
whenever a static or responsive rail/drawer overlay is open. It sits below
|
|
94
|
+
the panel and above the work area, absorbs an outside press, and lets
|
|
95
|
+
`wireWorkbench` close the overlay without activating the control underneath.
|
|
96
|
+
It is off by default; without it, the compact rail's dismiss strip remains
|
|
97
|
+
transparent. Pair it with `wireWorkbench` for outside-press dismissal;
|
|
98
|
+
- `responsiveOverlayAt: "narrow" | "compact" | "never" | number` presents a rail or the
|
|
93
99
|
bottom drawer as an overlay below a Workbench container breakpoint — 704px
|
|
94
100
|
or less for `narrow`, 448px or less for `compact`, the breakpoints of
|
|
95
|
-
`ResizableRegion`'s `responsiveFillAt` — and inline above it.
|
|
101
|
+
`ResizableRegion`'s `responsiveFillAt` — and inline above it. A positive
|
|
102
|
+
number such as `1024` uses that many CSS pixels of Workbench width. Numeric
|
|
103
|
+
thresholds require `wireWorkbench` with that panel's `collapsed` signal;
|
|
104
|
+
its resize observer applies the overlay layout and the collapse/restore
|
|
105
|
+
transition together. **Rails
|
|
96
106
|
default to `narrow`**, so on a small screen a sidebar covers the work area
|
|
97
107
|
(and an open drawer) instead of squeezing it; pass `never` to keep a rail
|
|
98
108
|
inline. The drawer stays inline unless it opts in. On a compact (448px or
|
|
@@ -219,6 +229,17 @@ it pinned while the work area is tall enough and lets it scroll with `main`
|
|
|
219
229
|
when the work area is short (the Pane's `chromePlacement="auto"`; it applies to
|
|
220
230
|
the pinned header and footer together).
|
|
221
231
|
|
|
232
|
+
A toolbar panel has the same fixed chrome sequence: `toolbar`, optional
|
|
233
|
+
`header`, scrolling `content`, optional `footer`, and optional
|
|
234
|
+
`bottomToolbar`. `header` sits below the panel toolbar, so an inspector can
|
|
235
|
+
keep its title, notices, and section tabs visible while its detail content
|
|
236
|
+
scrolls in the one `Pane` scroll owner. `headerList` and `footerList` configure
|
|
237
|
+
their `List` wrappers. `headerPlacement` and `footerPlacement` accept
|
|
238
|
+
`"fixed"` (default), `"scroll"`, or `"auto"` with the same behavior as the
|
|
239
|
+
work area's placement props. The panel's bottom toolbar renders a semantic
|
|
240
|
+
`footer`. These panel slots apply only when the panel has a `toolbar`; a panel
|
|
241
|
+
without one continues to render `content` as supplied.
|
|
242
|
+
|
|
222
243
|
Every toolbar the Workbench composes — `mainToolbar`, `mainBottomToolbar`, and
|
|
223
244
|
each panel's `toolbar` — takes the `Toolbar`'s configuration (`ToolbarConfig`):
|
|
224
245
|
`dividerSides`, `centerAlign`, `responsive`, `responsiveAt`, and
|
|
@@ -245,7 +266,8 @@ configurable the same way:
|
|
|
245
266
|
in — for example `{ contentElement: "nav", contentLabel: "Files" }` for a
|
|
246
267
|
navigator rail. Without a toolbar, `appearance: "sunken"` paints the panel
|
|
247
268
|
scroll region;
|
|
248
|
-
- `mainHeaderList` / `mainFooterList`
|
|
269
|
+
- `mainHeaderList` / `mainFooterList` and a panel's `headerList` /
|
|
270
|
+
`footerList` (`ListConfig`: `gap`, `hAlign`,
|
|
249
271
|
`vAlign`, `dividerSides`, `textInsets`, `controlInsets`) configure the
|
|
250
272
|
`List`s holding `mainHeader` / `mainFooter`.
|
|
251
273
|
|
|
@@ -356,6 +378,17 @@ const stop = wireWorkbench(root, {
|
|
|
356
378
|
`"compact"` (448px or less) instead: below that breakpoint it presents as a
|
|
357
379
|
full-size overlay over the work area rather than squeezing beside it (see
|
|
358
380
|
the catalog's resizable and responsive-drawer Workbench examples).
|
|
381
|
+
A numeric value measures the Workbench container, not the viewport. If the
|
|
382
|
+
app has no numeric Workbench breakpoint, the overlay wiring does not measure
|
|
383
|
+
the Workbench on ordinary panel updates. For numeric breakpoints the wiring
|
|
384
|
+
mirrors the active panel state onto the Workbench root, keeping work-area
|
|
385
|
+
styles local to actual overlay transitions. If the rest of an app switches
|
|
386
|
+
by viewport width and its Workbench can be narrower
|
|
387
|
+
than the viewport, keep the app's viewport decision in
|
|
388
|
+
`presentation: "overlay"` and pass its `collapsed` signals to
|
|
389
|
+
`wireWorkbench`. On entering that mode, collapse the panels; after leaving,
|
|
390
|
+
restore their preferred inline state once the inline presentation has
|
|
391
|
+
rendered, so exclusive overlay handling cannot close a sibling rail.
|
|
359
392
|
- **Collapse:** `collapsed` never changes a size. A collapsed panel keeps its
|
|
360
393
|
size (its content slides out at that width), its separator leaves the tab
|
|
361
394
|
order, and expanding it returns it at the size it had.
|
|
@@ -402,7 +435,12 @@ presents as one, mirroring `wireSidebar`'s compact overlay:
|
|
|
402
435
|
- **Outside press:** a pointer press that starts and ends outside an open
|
|
403
436
|
overlay panel closes it. The app's own toggle still works: its click closes
|
|
404
437
|
the panel before the wiring looks, and the press that opens a panel never
|
|
405
|
-
closes it.
|
|
438
|
+
closes it. For a body-level menu, dialog, or other portal opened from a
|
|
439
|
+
panel, set that panel's `keepOpenOn: (target) => target === portalRoot` in
|
|
440
|
+
`wireWorkbench`. The predicate receives each node in the press's composed
|
|
441
|
+
path, so matching the portal root keeps the panel open when the press starts
|
|
442
|
+
or ends anywhere inside the portal. Escape and Tab inside that portal remain
|
|
443
|
+
with its own keyboard handler. Other outside presses still close the panel.
|
|
406
444
|
- **Focus:** when a panel closes with focus inside it — whatever closed it,
|
|
407
445
|
including the app's own control inside the panel — focus returns to the
|
|
408
446
|
control that had it when the panel opened (typically its toggle; one inside
|