@kerfjs/ui 5.0.0-beta.62 → 5.0.0-beta.63
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 +8 -2
- package/ai/component-composition.json +9 -2
- package/ai/components/list-item.md +1 -1
- package/ai/components/workbench.md +3 -2
- package/ai/public-api-signatures-v1.md +136 -38
- 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 +1 -1
- 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-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-7AKGPBCC.js +76 -0
- package/dist/chunk-7AKGPBCC.js.map +1 -0
- 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-X6ADHJNI.js → chunk-KFYANKJI.js} +25 -6
- package/dist/chunk-KFYANKJI.js.map +1 -0
- package/dist/chunk-MOSIE4Z2.js +51 -0
- package/dist/chunk-MOSIE4Z2.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-NNMLEDMD.js → chunk-OBAFAH5B.js} +36 -8
- package/dist/chunk-OBAFAH5B.js.map +1 -0
- package/dist/{chunk-A3CKOW2R.js → chunk-R75GGNWY.js} +123 -20
- package/dist/chunk-R75GGNWY.js.map +1 -0
- package/dist/chunk-RGS4WX2M.js +44 -0
- package/dist/chunk-RGS4WX2M.js.map +1 -0
- package/dist/{chunk-RRB26JRJ.js → chunk-RTJNJTG3.js} +2 -2
- package/dist/{chunk-RRB26JRJ.js.map → chunk-RTJNJTG3.js.map} +1 -1
- package/dist/{chunk-EAC4CDY7.js → chunk-SMZGAPCU.js} +15 -2
- package/dist/chunk-SMZGAPCU.js.map +1 -0
- package/dist/{chunk-6ZXOQEAN.js → chunk-WF75U3V4.js} +7 -1
- package/dist/chunk-WF75U3V4.js.map +1 -0
- package/dist/{chunk-VCBTX62E.js → chunk-ZRWXFDDS.js} +2 -2
- package/dist/chunk-ZRWXFDDS.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 +36 -5
- package/dist/content-item.js +1 -1
- package/dist/disclosure-arrow.js +2 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -19
- 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 +38 -1
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.d.ts +2 -2
- 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/chip.css +14 -0
- package/dist/styles/content-item.css +36 -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 +15 -10
- 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 +29 -6
- package/dist/styles/toolbar-control-group.css +35 -0
- package/dist/styles/workbench.css +148 -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.js +2 -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 +62 -0
- package/dist/wire-content-items.js.map +1 -0
- 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 +21 -5
- package/docs/catalog.md +36 -0
- package/docs/collapsible-panel.md +8 -1
- package/docs/component-contract.md +10 -4
- package/docs/component-selection.md +39 -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 +30 -3
- package/docs/sunken-panel.md +22 -0
- package/docs/ui-analyzer.md +4 -0
- package/docs/workbench.md +38 -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-VCBTX62E.js.map +0 -1
- package/dist/chunk-X6ADHJNI.js.map +0 -1
package/docs/catalog.md
CHANGED
|
@@ -215,6 +215,42 @@ border, and padding. Catalogs for downstream components should conform to the
|
|
|
215
215
|
contract and can start from the checked
|
|
216
216
|
[`component-catalog-extension.json`](./examples/component-catalog-extension.json)
|
|
217
217
|
example; provide those entries beside Kerf's shipped catalog to AI tools.
|
|
218
|
+
An extension entry may declare `uses` with direct Kerf or extension entry ids,
|
|
219
|
+
plus repository-relative `source` and `demoSource` paths. Keep the ids unique
|
|
220
|
+
and resolvable across both catalogs; paths use `/` separators and cannot
|
|
221
|
+
traverse outside the repository. These fields let consumer demos derive source
|
|
222
|
+
links and composition relationships from the catalog.
|
|
223
|
+
|
|
224
|
+
For a consumer UX demo, `@kerfjs/ui/catalog-projection` exports
|
|
225
|
+
`projectConsumerCatalog(extension, kerfCatalog, options)` and
|
|
226
|
+
`projectCatalogEntries(entries, options)`. The projection maps `purpose` to
|
|
227
|
+
`description`, `uses` to related-entry ids, `source` to `componentSource`, and
|
|
228
|
+
`demoSource` to the demo source link. It defaults the source identity to
|
|
229
|
+
`consumer` and category to `Application`. Explicit paths in an extension entry
|
|
230
|
+
take precedence over templates. Template placeholders are `{id}`, `{name}`,
|
|
231
|
+
`{kind}`, and `{package}`. Design templates are omitted unless configured.
|
|
232
|
+
|
|
233
|
+
The package also ships `kerf-catalog-demo` for a committed TypeScript module:
|
|
234
|
+
|
|
235
|
+
```sh
|
|
236
|
+
kerf-catalog-demo --extension ai/component-catalog-extension.json \
|
|
237
|
+
--out ux-demo/catalog.generated.ts \
|
|
238
|
+
--repo-base https://github.com/acme/app/blob/main/ \
|
|
239
|
+
--source-template 'src/{id}.tsx' \
|
|
240
|
+
--demo-template 'ux-demo/demos/{id}.tsx' --write
|
|
241
|
+
kerf-catalog-demo --extension ai/component-catalog-extension.json \
|
|
242
|
+
--out ux-demo/catalog.generated.ts \
|
|
243
|
+
--repo-base https://github.com/acme/app/blob/main/ \
|
|
244
|
+
--source-template 'src/{id}.tsx' \
|
|
245
|
+
--demo-template 'ux-demo/demos/{id}.tsx' --check
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The command uses the Kerf catalog shipped with the package to resolve `uses`;
|
|
249
|
+
`--kerf-catalog` selects another catalog file. `--category`,
|
|
250
|
+
`--documentation-template`, and `--design-template` configure optional row
|
|
251
|
+
fields. `--check` fails if the generated file is missing or stale. The output
|
|
252
|
+
exports `generatedConsumerCatalog` and `catalogRepositoryBlobUrl`; the latter
|
|
253
|
+
is normalized to a trailing slash for source and documentation links.
|
|
218
254
|
|
|
219
255
|
### Automated conformance and reviewed exceptions
|
|
220
256
|
|
|
@@ -134,7 +134,7 @@ and that of the components it renders (`Pane`, `Toolbar`, `ToolbarControlGroup`,
|
|
|
134
134
|
|
|
135
135
|
Give a panel a `toolbar` (the same roles as a
|
|
136
136
|
[Workbench panel toolbar](workbench.md#panel-toolbars)) and it composes its own
|
|
137
|
-
top toolbar over a `Pane
|
|
137
|
+
top toolbar over a `Pane`:
|
|
138
138
|
|
|
139
139
|
- `title` precedes the `leading` zone; `leading`, `center`, and `trailing`
|
|
140
140
|
place groups wherever the open panel needs them;
|
|
@@ -142,6 +142,13 @@ top toolbar over a `Pane`, with an optional `footer` below its content:
|
|
|
142
142
|
work area when the panel closes; the standard `toggle: { action, name,
|
|
143
143
|
showLabel?, hideLabel? }` is always the final group.
|
|
144
144
|
|
|
145
|
+
The panel can also take `header` under its toolbar, `footer` below its content,
|
|
146
|
+
`bottomToolbar` below that, `headerList` / `footerList` for those fixed content
|
|
147
|
+
stacks, and `headerPlacement` / `footerPlacement` (`fixed`, `scroll`, or `auto`).
|
|
148
|
+
These slots share the panel's one `Pane` scroll owner; the bottom toolbar uses
|
|
149
|
+
footer semantics. With no `toolbar`, the panel renders its children directly
|
|
150
|
+
and ignores the chrome slots.
|
|
151
|
+
|
|
145
152
|
The toolbar also takes the `Toolbar`'s configuration (`dividerSides`,
|
|
146
153
|
`centerAlign`, `responsive`, `responsiveAt`, `safeAreaEdges`); it draws no
|
|
147
154
|
divider of its own unless `dividerSides` says so. The `Pane` under it draws
|
|
@@ -243,6 +243,9 @@ example. Keep app and Kerf entries as package-qualified inputs, then let people
|
|
|
243
243
|
or AI tools search their combined entries and compare `geometry` before adding
|
|
244
244
|
wrappers or insets. Do not add app-owned entries to Kerf's canonical catalog or
|
|
245
245
|
claim Kerf delivery paths for them.
|
|
246
|
+
Extension entries may add `uses` for direct composition dependencies and
|
|
247
|
+
repository-relative `source` and `demoSource` files. Resolve each dependency
|
|
248
|
+
against the combined Kerf and consumer catalogs; do not duplicate a Kerf id.
|
|
246
249
|
|
|
247
250
|
- Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks.
|
|
248
251
|
- Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
|
|
@@ -504,9 +507,10 @@ without application `::part(menu)` CSS; the default `standard` keeps each menu's
|
|
|
504
507
|
own inset (8px for a raw `wa-dropdown`, the Select listbox's 4px for a
|
|
505
508
|
`PopupMenu`), while `compact` and `list-zero` apply to every nested menu. A
|
|
506
509
|
`PopupMenu` and a `Select` draw one popup: the same caret that turns to face the
|
|
507
|
-
open popup, fade-in surface, surface inset, row height and padding,
|
|
508
|
-
|
|
509
|
-
|
|
510
|
+
open popup, fade-in surface, surface inset, row height and padding, current-row
|
|
511
|
+
fill, and group titles, all read from one private popup-choice contract in
|
|
512
|
+
`foundation.css`. Checkbox items reserve a check column; plain commands start
|
|
513
|
+
at the checkmark's leading edge. Compact mixed controls retain the standard
|
|
510
514
|
item padding, omit an internal separator, and let the raised selected item paint
|
|
511
515
|
over the outer border instead of shrinking to an inset highlight. The Web
|
|
512
516
|
Awesome trigger's shadow base owns max-content sizing, so icons, localized text,
|
|
@@ -578,7 +582,9 @@ by default it also owns the collapsible field's transient expand/collapse/focus
|
|
|
578
582
|
state in a signal it exposes on the returned handle. An app reads that signal in
|
|
579
583
|
render, hands in its own via `collapsible.signals`, drives it through
|
|
580
584
|
`handle.open`/`handle.close`, or disables any individual behavior — so transient
|
|
581
|
-
UI is consistent by default without every app reinventing it.
|
|
585
|
+
UI is consistent by default without every app reinventing it. A collapsed
|
|
586
|
+
field may reveal its editor after the current microtask; the helper keeps a
|
|
587
|
+
bounded render-frame focus handoff for that reveal and cancels it on disposal.
|
|
582
588
|
|
|
583
589
|
A public subpath that exposes several visual components is a folder-backed
|
|
584
590
|
surface. Put each component in its own source file and give each visual
|
|
@@ -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
|
|
@@ -357,8 +363,18 @@ example `b`, `tr`, or `trbl`) only when the toolbar owns a permanent separator
|
|
|
357
363
|
edge. Dividers earn their place: never fake one with a border or pad below one
|
|
358
364
|
to make it look right.
|
|
359
365
|
|
|
366
|
+
`Toolbar` renders a semantic `header` by default. Set `position="footer"`
|
|
367
|
+
for a toolbar at the bottom of a pane or page; Workbench's
|
|
368
|
+
`mainBottomToolbar` and the catalog resource bar apply this automatically.
|
|
369
|
+
The position changes the HTML element without changing zones or geometry.
|
|
370
|
+
|
|
360
371
|
Common toolbar patterns:
|
|
361
372
|
|
|
373
|
+
For a long-running icon action, set `busy` on its single-control
|
|
374
|
+
`ToolbarControlGroup` and supply a descriptive `busyLabel`. The group preserves
|
|
375
|
+
the control's dimensions, shows `LoadingSpinner` in its icon slot, sets
|
|
376
|
+
`aria-busy`, and makes the control inert until the app clears `busy`.
|
|
377
|
+
|
|
362
378
|
| Want | Put in the zone | Notes |
|
|
363
379
|
| ----------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
|
364
380
|
| 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 +434,12 @@ items shape covers single-line and batch actions; compute each batch child's
|
|
|
418
434
|
```
|
|
419
435
|
|
|
420
436
|
For a flat command menu with persistent sort choices, group commands under
|
|
421
|
-
`heading` entries and set `
|
|
422
|
-
|
|
423
|
-
|
|
437
|
+
`heading` entries and set `checked` explicitly on each choice. Checked rows
|
|
438
|
+
show a checkmark; the background marks the current keyboard row, as in `Select`.
|
|
439
|
+
Only items with `checked: true` or `checked: false` reserve checkmark space.
|
|
440
|
+
Omit `checked` for a plain command, including one beside checkbox items.
|
|
441
|
+
Commands still dispatch their own `data-action` once on pointer and keyboard
|
|
442
|
+
selection.
|
|
424
443
|
|
|
425
444
|
For a row opened by right-click, render `PopupMenu` with `context`, `label`,
|
|
426
445
|
and a stable root `data-*` marker. Its trigger is an invisible anchor removed
|
|
@@ -469,6 +488,12 @@ geometry and 44px targets.
|
|
|
469
488
|
</Pane>
|
|
470
489
|
```
|
|
471
490
|
|
|
491
|
+
When that child is a selectable card, configure `ContentItem` with
|
|
492
|
+
`interactive`, `action`, `itemId`, and a `selectionMode`; wire
|
|
493
|
+
`wireContentItems` once for Enter and Space. The component owns selection,
|
|
494
|
+
hover, focus, and disabled paint in its reserved 1px frame (see
|
|
495
|
+
[Content items](./layout.md#content-items)).
|
|
496
|
+
|
|
472
497
|
Incorrect: duplicating component-like rows and compensating for nested padding
|
|
473
498
|
forks the package anatomy and spacing contract.
|
|
474
499
|
|
|
@@ -489,6 +514,12 @@ The application updates its tag list after the action. `size="compact"` uses a
|
|
|
489
514
|
20px chip with a 16px remove button, and `disabled` disables removal. Tone,
|
|
490
515
|
appearance, and shape use the same semantic choices as `Badge`; use `Badge`
|
|
491
516
|
when no removal is needed and the content is status or count metadata.
|
|
517
|
+
Pass an unsized, decorative `LucideIcon` through `icon` for a leading glyph;
|
|
518
|
+
Chip sizes it to its own type scale and aligns it beside the label. For a long
|
|
519
|
+
plain-text label, set `truncate`: the chip can shrink within a `Row`, its label
|
|
520
|
+
gets a one-line ellipsis, and the full string is the label's native `title`.
|
|
521
|
+
Keep a price or other unbreakable sibling in `Text wrap="nowrap"`. `truncate`
|
|
522
|
+
requires a string label so the title cannot lose text hidden inside markup.
|
|
492
523
|
|
|
493
524
|
```tsx
|
|
494
525
|
<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
|
|
@@ -200,6 +204,18 @@ region (`role="region"`), and `focusTarget` to make the item a programmatic
|
|
|
200
204
|
focus target (`tabindex="-1"`), for example a NavStack view's `data-nav-focus`
|
|
201
205
|
target.
|
|
202
206
|
|
|
207
|
+
For a selectable card, set `interactive`, a delegated `action`, and an optional
|
|
208
|
+
`itemId`. Wire `wireContentItems(root)` once on the containing app root; it
|
|
209
|
+
activates focused cards with Enter or Space and forwards the resulting click to
|
|
210
|
+
the app's ordinary `data-action` handler. `selectionMode="toggle"` maps
|
|
211
|
+
`selected` to a button's `aria-pressed`; `selectionMode="single"` maps it to an
|
|
212
|
+
option's `aria-selected` and belongs in an app-owned `role="listbox"` container.
|
|
213
|
+
An interactive card is a Tab stop, and `disabled` removes its action and Tab
|
|
214
|
+
stop while exposing `aria-disabled`. Keep interactive descendants outside a
|
|
215
|
+
card; a card is one action target. Hover, pressed, focus, and selected paints
|
|
216
|
+
reuse the reserved border without changing geometry. `rootAttributes` still
|
|
217
|
+
accepts safe app `data-*` metadata, while the card owns its interaction data.
|
|
218
|
+
|
|
203
219
|
The rendered classes — `.kui-content-item`, `.kui-content-item--framed`, and
|
|
204
220
|
`.kui-content-item--pill` — stay public for the rare element that must carry the
|
|
205
221
|
geometry itself (for example a `<ul>` list or a `Text` paragraph in an
|
|
@@ -322,6 +338,14 @@ display copy, and `font="monospace"` for code or identifiers (the
|
|
|
322
338
|
finite props compose with each other and with every semantic `variant`; omit
|
|
323
339
|
them to inherit the surrounding color, size, and font.
|
|
324
340
|
|
|
341
|
+
Control long copy with `wrap`: `normal` (default) restores ordinary wrapping,
|
|
342
|
+
`anywhere` breaks long unbroken strings, `nowrap` holds one line, and
|
|
343
|
+
`truncate` holds one line with an ellipsis. `truncate` sets `min-width: 0`, so
|
|
344
|
+
Text can shrink beside a fixed-size sibling in a `Row`; the sibling keeps its
|
|
345
|
+
width. On `normal` or `anywhere`, set a positive integer `maxLines` to clamp
|
|
346
|
+
wrapped text with an ellipsis. Omit `maxLines` for unlimited lines. The cap is
|
|
347
|
+
incompatible with `nowrap` and `truncate`.
|
|
348
|
+
|
|
325
349
|
```tsx
|
|
326
350
|
import { Text } from "@kerfjs/ui/text";
|
|
327
351
|
|
|
@@ -333,6 +357,9 @@ import { Text } from "@kerfjs/ui/text";
|
|
|
333
357
|
<Text variant="h2" size="xlarge">A display-sized section title</Text>;
|
|
334
358
|
<strong>Inbox<Text variant="span" tone="quiet" size="compact"> · 3 msg</Text></strong>;
|
|
335
359
|
<Text tone="danger" font="monospace">ERR_INVALID_ID</Text>;
|
|
360
|
+
<Text wrap="anywhere">A-very-long-unbroken-identifier</Text>;
|
|
361
|
+
<Text wrap="truncate" variant="span">Long vendor name</Text>;
|
|
362
|
+
<Text wrap="normal" maxLines={2}>A long summary capped at two lines.</Text>;
|
|
336
363
|
```
|
|
337
364
|
|
|
338
365
|
## Spacer
|
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/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/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,13 @@ 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
|
+
rest of an app switches by viewport width and its Workbench can be narrower
|
|
383
|
+
than the viewport, keep the app's viewport decision in
|
|
384
|
+
`presentation: "overlay"` and pass its `collapsed` signals to
|
|
385
|
+
`wireWorkbench`. On entering that mode, collapse the panels; after leaving,
|
|
386
|
+
restore their preferred inline state once the inline presentation has
|
|
387
|
+
rendered, so exclusive overlay handling cannot close a sibling rail.
|
|
359
388
|
- **Collapse:** `collapsed` never changes a size. A collapsed panel keeps its
|
|
360
389
|
size (its content slides out at that width), its separator leaves the tab
|
|
361
390
|
order, and expanding it returns it at the size it had.
|
|
@@ -402,7 +431,12 @@ presents as one, mirroring `wireSidebar`'s compact overlay:
|
|
|
402
431
|
- **Outside press:** a pointer press that starts and ends outside an open
|
|
403
432
|
overlay panel closes it. The app's own toggle still works: its click closes
|
|
404
433
|
the panel before the wiring looks, and the press that opens a panel never
|
|
405
|
-
closes it.
|
|
434
|
+
closes it. For a body-level menu, dialog, or other portal opened from a
|
|
435
|
+
panel, set that panel's `keepOpenOn: (target) => target === portalRoot` in
|
|
436
|
+
`wireWorkbench`. The predicate receives each node in the press's composed
|
|
437
|
+
path, so matching the portal root keeps the panel open when the press starts
|
|
438
|
+
or ends anywhere inside the portal. Escape and Tab inside that portal remain
|
|
439
|
+
with its own keyboard handler. Other outside presses still close the panel.
|
|
406
440
|
- **Focus:** when a panel closes with focus inside it — whatever closed it,
|
|
407
441
|
including the app's own control inside the panel — focus returns to the
|
|
408
442
|
control that had it when the panel opened (typically its toggle; one inside
|