@kerfjs/ui 5.0.0-beta.59 → 5.0.0-beta.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/component-catalog.json +99 -10
- package/ai/component-composition.json +78 -6
- package/ai/components/README.md +1 -1
- package/ai/components/floating-toolbar.md +3 -1
- package/ai/components/list-header.md +1 -1
- package/ai/components/list-item.md +4 -1
- package/ai/components/resize.md +6 -1
- package/ai/components/select.md +5 -3
- package/ai/components/state-banner.md +3 -1
- package/ai/components/tab-bar.md +1 -1
- package/ai/components/tabs.md +2 -1
- package/ai/components/text.md +2 -1
- package/ai/components/token-search-field.md +1 -1
- package/ai/components/toolbar-text.md +4 -2
- package/ai/components/toolbar.md +2 -1
- package/ai/components/value-table.md +2 -1
- package/ai/public-api-signatures-v1.md +55 -18
- package/ai/skill.md +18 -6
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/app-tab.d.ts +4 -1
- package/dist/app-tab.js +1 -1
- package/dist/catalog.js +6 -6
- package/dist/{chunk-2CCMJTVY.js → chunk-2OXQHM7I.js} +5 -5
- package/dist/{chunk-2CCMJTVY.js.map → chunk-2OXQHM7I.js.map} +1 -1
- package/dist/{chunk-XDKAYSVD.js → chunk-3SXMEK3B.js} +1 -1
- package/dist/chunk-3SXMEK3B.js.map +1 -0
- package/dist/{chunk-QOWG4ZCL.js → chunk-5I7OHCIP.js} +5 -2
- package/dist/chunk-5I7OHCIP.js.map +1 -0
- package/dist/{chunk-W4XKTST6.js → chunk-5PESG2VP.js} +3 -3
- package/dist/{chunk-W4XKTST6.js.map → chunk-5PESG2VP.js.map} +1 -1
- package/dist/{chunk-UX2VVXZ3.js → chunk-5Q3N6EV7.js} +2 -2
- package/dist/{chunk-UX2VVXZ3.js.map → chunk-5Q3N6EV7.js.map} +1 -1
- package/dist/{chunk-UFYZHYWU.js → chunk-A3CKOW2R.js} +4 -3
- package/dist/chunk-A3CKOW2R.js.map +1 -0
- package/dist/{chunk-UXT7TE6B.js → chunk-AUKT3KMG.js} +5 -1
- package/dist/chunk-AUKT3KMG.js.map +1 -0
- package/dist/{chunk-EVYKTVBQ.js → chunk-GLDWRCAM.js} +5 -1
- package/dist/chunk-GLDWRCAM.js.map +1 -0
- package/dist/{chunk-M7QV3IHH.js → chunk-I3Q7KKYM.js} +5 -1
- package/dist/chunk-I3Q7KKYM.js.map +1 -0
- package/dist/{chunk-3CGQ7ZNO.js → chunk-IA7TMD4Y.js} +2 -2
- package/dist/{chunk-3CGQ7ZNO.js.map → chunk-IA7TMD4Y.js.map} +1 -1
- package/dist/{chunk-VHADGP3B.js → chunk-KLJKU6ZL.js} +5 -1
- package/dist/chunk-KLJKU6ZL.js.map +1 -0
- package/dist/{chunk-6YFHCLHG.js → chunk-MERWRTBG.js} +1 -1
- package/dist/chunk-MERWRTBG.js.map +1 -0
- package/dist/{chunk-KH6VUGHU.js → chunk-NNMLEDMD.js} +2 -2
- package/dist/{chunk-KH6VUGHU.js.map → chunk-NNMLEDMD.js.map} +1 -1
- package/dist/{chunk-6CINWX2E.js → chunk-P7D3EMXM.js} +3 -1
- package/dist/chunk-P7D3EMXM.js.map +1 -0
- package/dist/{chunk-QPUPLNNB.js → chunk-T57AXDFM.js} +2 -2
- package/dist/{chunk-QPUPLNNB.js.map → chunk-T57AXDFM.js.map} +1 -1
- package/dist/{chunk-WOUF7YXM.js → chunk-T66UNBXL.js} +5 -2
- package/dist/chunk-T66UNBXL.js.map +1 -0
- package/dist/{chunk-XQV2B4IL.js → chunk-UIDKY4UB.js} +2 -2
- package/dist/{chunk-XQV2B4IL.js.map → chunk-UIDKY4UB.js.map} +1 -1
- package/dist/{chunk-OUK6QRDR.js → chunk-WPLIO5WJ.js} +5 -2
- package/dist/chunk-WPLIO5WJ.js.map +1 -0
- package/dist/collapsible-panel.d.ts +1 -0
- package/dist/collapsible-panel.js +2 -2
- package/dist/floating-toolbar.d.ts +8 -2
- package/dist/floating-toolbar.js +1 -1
- package/dist/index.js +13 -13
- package/dist/list-header.js +1 -1
- package/dist/list-item.d.ts +5 -2
- package/dist/list-item.js +1 -1
- package/dist/nav-stack.js +1 -1
- package/dist/resizable-region.d.ts +8 -3
- package/dist/resizable-region.js +1 -1
- package/dist/select.d.ts +4 -1
- package/dist/select.js +1 -1
- package/dist/split-view.d.ts +1 -0
- package/dist/split-view.js +2 -2
- package/dist/state-banner.d.ts +8 -2
- package/dist/state-banner.js +1 -1
- package/dist/styles/app-tab.css +3 -0
- package/dist/styles/floating-toolbar.css +56 -4
- package/dist/styles/list-header.css +15 -7
- package/dist/styles/list-item.css +60 -18
- package/dist/styles/resizable-region.css +33 -1
- package/dist/styles/select.css +26 -0
- package/dist/styles/state-banner.css +37 -0
- package/dist/styles/tab-bar.css +25 -10
- package/dist/styles/text.css +9 -0
- package/dist/styles/token-search-field.css +1 -1
- package/dist/styles/toolbar-text.css +4 -0
- package/dist/styles/toolbar.css +83 -1
- package/dist/styles/value-table.css +16 -3
- package/dist/text.d.ts +7 -2
- package/dist/text.js +1 -1
- package/dist/toolbar-text.d.ts +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +4 -2
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +3 -1
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.js +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/wire-workbench.js +1 -1
- package/dist/workbench.js +1 -1
- package/docs/collapsible-panel.md +7 -1
- package/docs/component-selection.md +61 -0
- package/docs/document-baseline.md +3 -0
- package/llms.txt +32 -0
- package/package.json +1 -1
- package/dist/chunk-6CINWX2E.js.map +0 -1
- package/dist/chunk-6YFHCLHG.js.map +0 -1
- package/dist/chunk-EVYKTVBQ.js.map +0 -1
- package/dist/chunk-M7QV3IHH.js.map +0 -1
- package/dist/chunk-OUK6QRDR.js.map +0 -1
- package/dist/chunk-QOWG4ZCL.js.map +0 -1
- package/dist/chunk-UFYZHYWU.js.map +0 -1
- package/dist/chunk-UXT7TE6B.js.map +0 -1
- package/dist/chunk-VHADGP3B.js.map +0 -1
- package/dist/chunk-WOUF7YXM.js.map +0 -1
- package/dist/chunk-XDKAYSVD.js.map +0 -1
package/ai/components/text.md
CHANGED
|
@@ -38,6 +38,7 @@ Exact prop names and types: [`@kerfjs/ui/text`](../public-api-signatures-v1.md#k
|
|
|
38
38
|
- default, quiet, or danger tone
|
|
39
39
|
- compact, default, large, or xlarge size
|
|
40
40
|
- default or monospace font
|
|
41
|
+
- flush item geometry and tight line height
|
|
41
42
|
|
|
42
43
|
## Composition
|
|
43
44
|
|
|
@@ -55,7 +56,7 @@ No wiring helper.
|
|
|
55
56
|
|
|
56
57
|
Margin: none · border: self · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
|
|
57
58
|
|
|
58
|
-
- Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding;
|
|
59
|
+
- Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding; flush removes the border and padding. Tight line height is available for compact copy. Span has no margin, border, or padding.
|
|
59
60
|
|
|
60
61
|
## Accessibility
|
|
61
62
|
|
|
@@ -88,7 +88,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
88
88
|
|
|
89
89
|
Never put `kui-token-search`, `kui-token-search__clear`, `kui-token-search__editor`, `kui-token-search__expand`, `kui-token-search__leading`, `kui-token-search__token`, `kui-token-search__token-edit`, `kui-token-search__token-remove`, `kui-token-search__suggestions`, `kui-token-search__suggestion`, `kui-token-search__trailing` on an element you write; render `TokenSearchField` instead (`KUI-L103`).
|
|
90
90
|
|
|
91
|
-
Public tokens it reads: `--kui-color-brand-fill-normal`, `--kui-color-brand-on-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-text-link`, `--kui-color-surface`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-focus-ring`, `--kui-font-s`, `--kui-font-xs`, `--kui-radius-pill`, `--kui-token-search-background`, `--kui-token-search-border`, `--kui-token-search-line-size`, `--kui-token-search-token-background`, `--kui-token-search-token-foreground`, `--kui-token-search-expanded-width`. Set a token only where its public contract allows; prefer a prop.
|
|
91
|
+
Public tokens it reads: `--kui-color-brand-fill-normal`, `--kui-color-brand-on-quiet`, `--kui-color-neutral-border-normal`, `--kui-color-text-link`, `--kui-color-surface`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-focus-ring`, `--kui-font-s`, `--kui-font-xs`, `--kui-radius-pill`, `--kui-token-search-background`, `--kui-token-search-border`, `--kui-token-search-editor-min-width`, `--kui-token-search-line-size`, `--kui-token-search-token-background`, `--kui-token-search-token-foreground`, `--kui-token-search-expanded-width`. Set a token only where its public contract allows; prefer a prop.
|
|
92
92
|
|
|
93
93
|
Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
|
|
94
94
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## When to use
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Extra-large through extra-small toolbar identity text.
|
|
10
10
|
|
|
11
11
|
- Render toolbar identity or heading text at a supported hierarchy size; pass headingLevel for heading semantics.
|
|
12
12
|
|
|
@@ -32,9 +32,11 @@ Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures
|
|
|
32
32
|
|
|
33
33
|
**Variants (configure, do not restyle):**
|
|
34
34
|
|
|
35
|
+
- xlarge
|
|
35
36
|
- large
|
|
36
37
|
- default
|
|
37
38
|
- small
|
|
39
|
+
- xsmall
|
|
38
40
|
- placeholder (loading)
|
|
39
41
|
|
|
40
42
|
## Composition
|
|
@@ -65,7 +67,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
65
67
|
|
|
66
68
|
Never put `kui-toolbar-text` on an element you write; render `ToolbarText` instead (`KUI-L103`).
|
|
67
69
|
|
|
68
|
-
Public tokens it reads: `--kui-color-neutral-on-quiet`, `--kui-color-text`, `--kui-font-2xl`, `--kui-font-l`, `--kui-font-m`, `--kui-font-s`, `--kui-font-xs`. Set a token only where its public contract allows; prefer a prop.
|
|
70
|
+
Public tokens it reads: `--kui-color-neutral-on-quiet`, `--kui-color-text`, `--kui-font-2xs`, `--kui-font-2xl`, `--kui-font-l`, `--kui-font-m`, `--kui-font-s`, `--kui-font-xs`. Set a token only where its public contract allows; prefer a prop.
|
|
69
71
|
|
|
70
72
|
Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
|
|
71
73
|
|
package/ai/components/toolbar.md
CHANGED
|
@@ -34,6 +34,7 @@ Exact prop names and types: [`@kerfjs/ui/toolbar`](../public-api-signatures-v1.m
|
|
|
34
34
|
- stacked zones at compact or narrow widths
|
|
35
35
|
- content-driven wrap that keeps a heading title whole
|
|
36
36
|
- center priority for an expanded center control
|
|
37
|
+
- trailing priority for an expanded trailing control at compact or narrow widths
|
|
37
38
|
- trailing groups wrap instead of clipping
|
|
38
39
|
- app bar or bottom bar claiming its screen edges (safeAreaEdges)
|
|
39
40
|
|
|
@@ -80,7 +81,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
80
81
|
|
|
81
82
|
Never put `kui-toolbar`, `kui-toolbar__center`, `kui-toolbar__leading`, `kui-toolbar__trailing` on an element you write; render `Toolbar` instead (`KUI-L103`).
|
|
82
83
|
|
|
83
|
-
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-font-sans`, `--kui-toolbar-divider-color`. Set a token only where its public contract allows; prefer a prop.
|
|
84
|
+
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-font-sans`, `--kui-toolbar-center-padding-inline`, `--kui-toolbar-divider-color`, `--kui-toolbar-leading-min-width`, `--kui-toolbar-leading-padding-inline`, `--kui-toolbar-trailing-gap`, `--kui-toolbar-trailing-justify`, `--kui-toolbar-trailing-justify-self`, `--kui-toolbar-trailing-padding-inline`, `--kui-toolbar-zone-padding-inline`. Set a token only where its public contract allows; prefer a prop.
|
|
84
85
|
|
|
85
86
|
Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
|
|
86
87
|
|
|
@@ -30,6 +30,7 @@ Exact prop names and types: [`@kerfjs/ui/value-table`](../public-api-signatures-
|
|
|
30
30
|
|
|
31
31
|
- icon rows
|
|
32
32
|
- iconless rows
|
|
33
|
+
- compact density
|
|
33
34
|
- placeholder (loading)
|
|
34
35
|
|
|
35
36
|
## Composition
|
|
@@ -61,7 +62,7 @@ Public class hooks (select for layout placement only, never to change the compon
|
|
|
61
62
|
|
|
62
63
|
Never put `kui-value-table`, `kui-value-table__row`, `kui-value-table__icon`, `kui-value-table__label` on an element you write; render `ValueTable` instead (`KUI-L103`).
|
|
63
64
|
|
|
64
|
-
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-color-surface-lowered`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-font-weight-semibold`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-space-2xs`, `--kui-value-table-background`, `--kui-value-table-border`, `--kui-value-table-icon-size`. Set a token only where its public contract allows; prefer a prop.
|
|
65
|
+
Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-color-surface-lowered`, `--kui-color-text`, `--kui-color-text-quiet`, `--kui-font-weight-semibold`, `--kui-layout-inline-margin`, `--kui-layout-item-gap`, `--kui-layout-item-padding`, `--kui-space-2xs`, `--kui-value-table-background`, `--kui-value-table-border`, `--kui-value-table-icon-size`, `--kui-value-table-row-columns`, `--kui-value-table-row-padding-block`, `--kui-value-table-row-gap`. Set a token only where its public contract allows; prefer a prop.
|
|
65
66
|
|
|
66
67
|
Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
|
|
67
68
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Public API signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.60` and `kerfjs@5.0.0-beta.60`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
|
|
4
4
|
|
|
5
5
|
## `@kerfjs/ui/css-values`
|
|
6
6
|
|
|
@@ -174,9 +174,11 @@ interface ToolbarProps {
|
|
|
174
174
|
* - `wrap` keeps one row while every zone fits at its natural width, and
|
|
175
175
|
* otherwise moves the trailing zone below a whole leading identity.
|
|
176
176
|
* - `center-priority` gives an expanded center control the full row.
|
|
177
|
+
* - `trailing-priority` moves an expanded trailing control to a full row
|
|
178
|
+
* below the leading identity at `responsiveAt`.
|
|
177
179
|
*/
|
|
178
|
-
responsive?: 'none' | 'stack' | 'wrap' | 'center-priority';
|
|
179
|
-
/** Container width at which `
|
|
180
|
+
responsive?: 'none' | 'stack' | 'wrap' | 'center-priority' | 'trailing-priority';
|
|
181
|
+
/** Container width at which `stack` or `trailing-priority` activates. */
|
|
180
182
|
responsiveAt?: 'compact' | 'narrow';
|
|
181
183
|
/**
|
|
182
184
|
* Screen edges this toolbar claims for device safe-area compensation, for an
|
|
@@ -208,7 +210,7 @@ export { Sides, Toolbar, type ToolbarConfig, type ToolbarProps };
|
|
|
208
210
|
```ts
|
|
209
211
|
import * as kerfjs from 'kerfjs';
|
|
210
212
|
|
|
211
|
-
type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small';
|
|
213
|
+
type ToolbarTextSize = 'xlarge' | 'large' | 'default' | 'small' | 'xsmall';
|
|
212
214
|
/** ARIA heading level for a title exposed as a heading landmark. */
|
|
213
215
|
type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
214
216
|
interface ToolbarTextBaseProps {
|
|
@@ -351,6 +353,8 @@ interface FloatingToolbarProps {
|
|
|
351
353
|
* Default: `'bottom-end'`.
|
|
352
354
|
*/
|
|
353
355
|
position?: FloatingToolbarPosition;
|
|
356
|
+
/** Keep the toolbar in normal document flow instead of floating over content. */
|
|
357
|
+
placement?: 'floating' | 'inline';
|
|
354
358
|
/**
|
|
355
359
|
* Distance from the container edges named by `position`. Default:
|
|
356
360
|
* `space('m')` (16px, 8px past a top toolbar's own inset). Omit it inside a
|
|
@@ -358,6 +362,8 @@ interface FloatingToolbarProps {
|
|
|
358
362
|
* corner owns the inset there and sets it to zero.
|
|
359
363
|
*/
|
|
360
364
|
inset?: CssLength;
|
|
365
|
+
/** Add device or layout-routed safe-area insets to the positioned edges. */
|
|
366
|
+
safeAreaInsets?: boolean;
|
|
361
367
|
className?: string;
|
|
362
368
|
/** Native named-slot assignment when composed inside a web component. */
|
|
363
369
|
slot?: string;
|
|
@@ -375,9 +381,11 @@ interface FloatingToolbarProps {
|
|
|
375
381
|
* `wireSidebar` compact overlay, an overlay `CollapsiblePanel` or horizontal
|
|
376
382
|
* `ResizableRegion`), the toolbar is hidden — unfocusable and out of the
|
|
377
383
|
* accessibility tree — until the overlay closes. The app owns the controls
|
|
378
|
-
* and their behavior — wire them with `delegate()` as usual.
|
|
384
|
+
* and their behavior — wire them with `delegate()` as usual. Set
|
|
385
|
+
* `placement="inline"` for normal flow when an owner already positions the
|
|
386
|
+
* control; floating placement can add safe-area insets to its per-edge tokens.
|
|
379
387
|
*/
|
|
380
|
-
declare function FloatingToolbar({ children, label, position, inset, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
|
|
388
|
+
declare function FloatingToolbar({ children, label, position, placement, inset, safeAreaInsets, className, slot, }: FloatingToolbarProps): kerfjs.SafeHtml;
|
|
381
389
|
|
|
382
390
|
export { FloatingToolbar, type FloatingToolbarPosition, type FloatingToolbarProps };
|
|
383
391
|
```
|
|
@@ -741,6 +749,7 @@ type ListItemRootAttributes = Readonly<Record<`data-${string}`, string | undefin
|
|
|
741
749
|
'data-busy'?: never;
|
|
742
750
|
'data-state'?: never;
|
|
743
751
|
'data-kui-disabled'?: never;
|
|
752
|
+
'data-icon-align'?: never;
|
|
744
753
|
}>;
|
|
745
754
|
interface ListItemProps {
|
|
746
755
|
label: string | SafeHtml;
|
|
@@ -753,7 +762,7 @@ interface ListItemProps {
|
|
|
753
762
|
status?: string | SafeHtml;
|
|
754
763
|
/** Show a progress indicator and expose the row as busy without replacing its content; a placeholder keeps the indicator. */
|
|
755
764
|
busy?: boolean;
|
|
756
|
-
density?: 'standard' | 'compact';
|
|
765
|
+
density?: 'standard' | 'compact' | 'spacious';
|
|
757
766
|
divider?: 'none' | 'before' | 'after' | 'both';
|
|
758
767
|
selected?: boolean;
|
|
759
768
|
action: string;
|
|
@@ -763,6 +772,8 @@ interface ListItemProps {
|
|
|
763
772
|
accessibleLabel?: string;
|
|
764
773
|
title?: string;
|
|
765
774
|
multiline?: boolean;
|
|
775
|
+
/** Alignment of an icon beside a wrapped label. Defaults to its first line. */
|
|
776
|
+
multilineIconAlign?: 'first-line' | 'center';
|
|
766
777
|
state?: string;
|
|
767
778
|
disabled?: boolean;
|
|
768
779
|
tabIndex?: number;
|
|
@@ -772,7 +783,7 @@ interface ListItemProps {
|
|
|
772
783
|
/** Native named-slot assignment when composed inside a web component. */
|
|
773
784
|
slot?: string;
|
|
774
785
|
}
|
|
775
|
-
declare function ListItem({ label, description, icon, trailing, status, busy, density, divider, selected, action, itemId, className, pressed, accessibleLabel, title, multiline, state, disabled, tabIndex, placeholder, rootAttributes, slot, }: ListItemProps): SafeHtml;
|
|
786
|
+
declare function ListItem({ label, description, icon, trailing, status, busy, density, divider, selected, action, itemId, className, pressed, accessibleLabel, title, multiline, multilineIconAlign, state, disabled, tabIndex, placeholder, rootAttributes, slot, }: ListItemProps): SafeHtml;
|
|
776
787
|
|
|
777
788
|
export { ListItem, type ListItemProps };
|
|
778
789
|
```
|
|
@@ -911,12 +922,14 @@ declare function ValueTableRow({ label, value, icon, className, placeholder, slo
|
|
|
911
922
|
|
|
912
923
|
interface ValueTableProps {
|
|
913
924
|
label: string;
|
|
925
|
+
/** Compact row spacing for metadata-dense surfaces. */
|
|
926
|
+
density?: 'default' | 'compact';
|
|
914
927
|
className?: string;
|
|
915
928
|
children: KerfUiContent;
|
|
916
929
|
/** Native named-slot assignment when composed inside a web component. */
|
|
917
930
|
slot?: string;
|
|
918
931
|
}
|
|
919
|
-
declare function ValueTable({ label, className, children, slot, }: ValueTableProps): kerfjs.SafeHtml;
|
|
932
|
+
declare function ValueTable({ label, density, className, children, slot, }: ValueTableProps): kerfjs.SafeHtml;
|
|
920
933
|
|
|
921
934
|
export { ValueTable, type ValueTableProps, ValueTableRow, type ValueTableRowProps };
|
|
922
935
|
```
|
|
@@ -934,6 +947,7 @@ type AppTabRootAttributes = Readonly<Record<`data-${string}`, string | undefined
|
|
|
934
947
|
'data-selected'?: never;
|
|
935
948
|
'data-tab-dragging'?: never;
|
|
936
949
|
'data-tab-drop-position'?: never;
|
|
950
|
+
'data-attention'?: never;
|
|
937
951
|
}>;
|
|
938
952
|
type AppTabPresentation = 'pill' | 'segmented' | 'icon-only';
|
|
939
953
|
type AppTabSize = 'default' | 'compact';
|
|
@@ -941,6 +955,8 @@ interface AppTabProps {
|
|
|
941
955
|
id: string;
|
|
942
956
|
name: string;
|
|
943
957
|
selected?: boolean;
|
|
958
|
+
/** Emphasize the visible tab name with the attention color token. */
|
|
959
|
+
attention?: boolean;
|
|
944
960
|
closable?: boolean;
|
|
945
961
|
draggable?: boolean;
|
|
946
962
|
leading?: KerfUiContent;
|
|
@@ -973,7 +989,7 @@ interface AppTabProps {
|
|
|
973
989
|
/** Native named-slot assignment when composed inside a web component. */
|
|
974
990
|
slot?: string;
|
|
975
991
|
}
|
|
976
|
-
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
992
|
+
declare function AppTab({ id, name, selected, attention, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
977
993
|
|
|
978
994
|
export { AppTab, type AppTabPresentation, type AppTabProps, type AppTabSize };
|
|
979
995
|
```
|
|
@@ -1262,6 +1278,7 @@ import './toolbar.js';
|
|
|
1262
1278
|
import './pane.js';
|
|
1263
1279
|
import './sides-BPSWde0A.js';
|
|
1264
1280
|
import './toolbar-text.js';
|
|
1281
|
+
import './css-values.js';
|
|
1265
1282
|
|
|
1266
1283
|
/**
|
|
1267
1284
|
* The roomy list pane's `ResizableRegion`: its committed `size` and `min` /
|
|
@@ -1812,6 +1829,7 @@ import './lucide-icon.js';
|
|
|
1812
1829
|
import 'lucide';
|
|
1813
1830
|
import './toolbar.js';
|
|
1814
1831
|
import './sides-BPSWde0A.js';
|
|
1832
|
+
import './css-values.js';
|
|
1815
1833
|
|
|
1816
1834
|
/** Which edge a {@link CollapsiblePanel} docks to. */
|
|
1817
1835
|
type CollapsiblePanelSide = PanelSide;
|
|
@@ -2095,6 +2113,7 @@ export { type WireTabScaffoldOptions, wireTabScaffold };
|
|
|
2095
2113
|
|
|
2096
2114
|
```ts
|
|
2097
2115
|
import { SafeHtml } from 'kerfjs';
|
|
2116
|
+
import { CssLength } from './css-values.js';
|
|
2098
2117
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
2099
2118
|
|
|
2100
2119
|
type ResizableRegionAxis = 'horizontal' | 'vertical';
|
|
@@ -2103,7 +2122,7 @@ type ResizableRegionSeparator = 'auto' | 'hidden';
|
|
|
2103
2122
|
type ResizableRegionCollapseMotion = 'none' | 'slide' | 'fade-slide';
|
|
2104
2123
|
type ResizableRegionContentOverflow = 'clip' | 'auto' | 'visible';
|
|
2105
2124
|
type ResizableRegionPresentation = 'inline' | 'overlay' | 'hidden';
|
|
2106
|
-
type ResizableRegionRestorePosition = 'bottom-start' | 'bottom-end';
|
|
2125
|
+
type ResizableRegionRestorePosition = 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end';
|
|
2107
2126
|
type ResizableRegionResponsiveFillAt = 'compact' | 'narrow';
|
|
2108
2127
|
interface ResizableRegionProps {
|
|
2109
2128
|
id: string;
|
|
@@ -2122,7 +2141,7 @@ interface ResizableRegionProps {
|
|
|
2122
2141
|
separator?: ResizableRegionSeparator;
|
|
2123
2142
|
/** Keep the track change instant while optionally sliding the fixed-size content. */
|
|
2124
2143
|
collapseMotion?: ResizableRegionCollapseMotion;
|
|
2125
|
-
/**
|
|
2144
|
+
/** Use `visible` while an anchored popup must escape the content box; it raises the region to the popup layer. */
|
|
2126
2145
|
contentOverflow?: ResizableRegionContentOverflow;
|
|
2127
2146
|
/** Inline layout, an edge overlay, or a responsive replacement that removes the region. */
|
|
2128
2147
|
presentation?: ResizableRegionPresentation;
|
|
@@ -2130,6 +2149,10 @@ interface ResizableRegionProps {
|
|
|
2130
2149
|
restoreControl?: SafeHtml;
|
|
2131
2150
|
/** Safe-area-aware corner of the region's container (not the viewport) for `restoreControl`. */
|
|
2132
2151
|
restorePosition?: ResizableRegionRestorePosition;
|
|
2152
|
+
/** Position a restore control in its container corner or leave it in normal flow. */
|
|
2153
|
+
restorePlacement?: 'corner' | 'inline';
|
|
2154
|
+
/** Corner distance before the container's safe-area inset. */
|
|
2155
|
+
restoreInset?: CssLength;
|
|
2133
2156
|
/** Fill the available inline track and hide the separator below a container breakpoint. */
|
|
2134
2157
|
responsiveFillAt?: ResizableRegionResponsiveFillAt;
|
|
2135
2158
|
/** Decorative dormant content for the separator handle. Must not contain interactive descendants. */
|
|
@@ -2138,7 +2161,7 @@ interface ResizableRegionProps {
|
|
|
2138
2161
|
}
|
|
2139
2162
|
declare const clampRegionSize: (size: number, min: number, max: number) => number;
|
|
2140
2163
|
declare const resizeRegionFromPointer: (startSize: number, delta: number, edge: ResizableRegionEdge) => number;
|
|
2141
|
-
declare function ResizableRegion({ id, label, size, min, max, axis, edge, collapsed, transitioning, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, responsiveFillAt, handleIcon, children, }: ResizableRegionProps): SafeHtml;
|
|
2164
|
+
declare function ResizableRegion({ id, label, size, min, max, axis, edge, collapsed, transitioning, separator, collapseMotion, contentOverflow, presentation, restoreControl, restorePosition, restorePlacement, restoreInset, responsiveFillAt, handleIcon, children, }: ResizableRegionProps): SafeHtml;
|
|
2142
2165
|
|
|
2143
2166
|
export { ResizableRegion, type ResizableRegionAxis, type ResizableRegionCollapseMotion, type ResizableRegionContentOverflow, type ResizableRegionEdge, type ResizableRegionPresentation, type ResizableRegionProps, type ResizableRegionResponsiveFillAt, type ResizableRegionRestorePosition, type ResizableRegionSeparator, clampRegionSize, resizeRegionFromPointer };
|
|
2144
2167
|
```
|
|
@@ -2543,6 +2566,7 @@ type SelectPresentation = 'form' | 'toolbar-borderless' | 'navigation';
|
|
|
2543
2566
|
type SelectSize = 'default' | 'compact';
|
|
2544
2567
|
type SelectSelectedPresentation = 'label' | 'icon-only';
|
|
2545
2568
|
type SelectFocusRingOwner = 'select' | 'group';
|
|
2569
|
+
type SelectTriggerWidth = 'fit-content' | 'max-content' | 'fill';
|
|
2546
2570
|
interface SelectBaseProps<Value extends string = string> {
|
|
2547
2571
|
name: string;
|
|
2548
2572
|
choices: readonly SelectChoice<Value>[];
|
|
@@ -2558,6 +2582,8 @@ interface SelectBaseProps<Value extends string = string> {
|
|
|
2558
2582
|
/** Form (default), borderless toolbar, or intrinsic navigation chrome. */
|
|
2559
2583
|
presentation?: SelectPresentation;
|
|
2560
2584
|
size?: SelectSize;
|
|
2585
|
+
/** Closed trigger width; omit to keep the presentation's default. */
|
|
2586
|
+
triggerWidth?: SelectTriggerWidth;
|
|
2561
2587
|
/** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
|
|
2562
2588
|
focusRingOwner?: SelectFocusRingOwner;
|
|
2563
2589
|
/** Maximum closed-control label width in CSS pixels before ellipsis. */
|
|
@@ -2608,7 +2634,7 @@ type SelectMultipleValueProps<Value extends string = string> = SelectMultipleLab
|
|
|
2608
2634
|
type SelectProps<Value extends string = string> = SelectBaseProps<Value> & SelectAccessibleName & (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);
|
|
2609
2635
|
declare function Select<Value extends string>(props: SelectProps<Value>): SafeHtml;
|
|
2610
2636
|
|
|
2611
|
-
export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectMultipleIconProps, type SelectMultipleLabelProps, type SelectMultipleValueProps, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSingleValueProps, type SelectSize };
|
|
2637
|
+
export { Select, type SelectChoice, type SelectFocusRingOwner, type SelectMultipleIconProps, type SelectMultipleLabelProps, type SelectMultipleValueProps, type SelectPresentation, type SelectProps, type SelectSelectedPresentation, type SelectSingleValueProps, type SelectSize, type SelectTriggerWidth };
|
|
2612
2638
|
```
|
|
2613
2639
|
|
|
2614
2640
|
## `@kerfjs/ui/state-banner`
|
|
@@ -2619,6 +2645,8 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
|
2619
2645
|
|
|
2620
2646
|
type StateBannerTone = 'neutral' | 'info' | 'pop' | 'success' | 'warning' | 'danger';
|
|
2621
2647
|
type StateBannerUrgency = 'status' | 'alert';
|
|
2648
|
+
type StateBannerCopyLayout = 'inline' | 'stacked';
|
|
2649
|
+
type StateBannerActionPlacement = 'trailing' | 'below';
|
|
2622
2650
|
interface StateBannerProps {
|
|
2623
2651
|
title: string;
|
|
2624
2652
|
detail?: string;
|
|
@@ -2628,15 +2656,19 @@ interface StateBannerProps {
|
|
|
2628
2656
|
action?: KerfUiContent;
|
|
2629
2657
|
tone?: StateBannerTone;
|
|
2630
2658
|
urgency?: StateBannerUrgency;
|
|
2659
|
+
/** Keep the detail beside the title, or give it its own line. */
|
|
2660
|
+
copyLayout?: StateBannerCopyLayout;
|
|
2661
|
+
/** Place the action beside the copy or on a separate trailing row. */
|
|
2662
|
+
actionPlacement?: StateBannerActionPlacement;
|
|
2631
2663
|
className?: string;
|
|
2632
2664
|
/** Render the title, badge, and detail as unanimated loading skeletons, keeping the icon and tone. The detail line appears only when `detail` is set, as in the live banner. */
|
|
2633
2665
|
placeholder?: boolean;
|
|
2634
2666
|
/** Native named-slot assignment when composed inside a web component. */
|
|
2635
2667
|
slot?: string;
|
|
2636
2668
|
}
|
|
2637
|
-
declare function StateBanner({ title, detail, badge, icon, action, tone, urgency, className, placeholder, slot, }: StateBannerProps): SafeHtml;
|
|
2669
|
+
declare function StateBanner({ title, detail, badge, icon, action, tone, urgency, copyLayout, actionPlacement, className, placeholder, slot, }: StateBannerProps): SafeHtml;
|
|
2638
2670
|
|
|
2639
|
-
export { StateBanner, type StateBannerProps, type StateBannerTone, type StateBannerUrgency };
|
|
2671
|
+
export { StateBanner, type StateBannerActionPlacement, type StateBannerCopyLayout, type StateBannerProps, type StateBannerTone, type StateBannerUrgency };
|
|
2640
2672
|
```
|
|
2641
2673
|
|
|
2642
2674
|
## `@kerfjs/ui/empty-state`
|
|
@@ -3070,6 +3102,7 @@ type TextTone = 'default' | 'quiet' | 'danger';
|
|
|
3070
3102
|
type TextSize = 'compact' | 'default' | 'large' | 'xlarge';
|
|
3071
3103
|
type TextFont = 'default' | 'monospace';
|
|
3072
3104
|
type TextBorder = 'transparent' | 'none';
|
|
3105
|
+
type TextLineHeight = 'default' | 'tight';
|
|
3073
3106
|
type TextContent = KerfUiContent | string | number | readonly TextContent[];
|
|
3074
3107
|
type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
|
|
3075
3108
|
/** Native heading, paragraph, or inline span element to render. Defaults to `p`. */
|
|
@@ -3082,6 +3115,10 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
|
|
|
3082
3115
|
font?: TextFont;
|
|
3083
3116
|
/** Transparent alignment border or no border when embedded in owner chrome. */
|
|
3084
3117
|
border?: TextBorder;
|
|
3118
|
+
/** Remove the block variant's item padding and border in compact content. */
|
|
3119
|
+
flush?: boolean;
|
|
3120
|
+
/** Use compact leading for short dialog or metadata copy. */
|
|
3121
|
+
lineHeight?: TextLineHeight;
|
|
3085
3122
|
children: TextContent;
|
|
3086
3123
|
class?: string;
|
|
3087
3124
|
className?: string;
|
|
@@ -3091,9 +3128,9 @@ type TextProps = Omit<KerfBaseAttrs, 'children' | 'class' | 'className'> & {
|
|
|
3091
3128
|
* content-item padding; `span` adds no box geometry.
|
|
3092
3129
|
* All ordinary native heading/paragraph attributes pass through to the element.
|
|
3093
3130
|
*/
|
|
3094
|
-
declare function Text({ variant: Variant, tone, size, font, border, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
|
|
3131
|
+
declare function Text({ variant: Variant, tone, size, font, border, flush, lineHeight, children, class: classValue, className, ...attributes }: TextProps): kerfjs.SafeHtml;
|
|
3095
3132
|
|
|
3096
|
-
export { Text, type TextBorder, type TextContent, type TextFont, type TextProps, type TextSize, type TextTone, type TextVariant };
|
|
3133
|
+
export { Text, type TextBorder, type TextContent, type TextFont, type TextLineHeight, type TextProps, type TextSize, type TextTone, type TextVariant };
|
|
3097
3134
|
```
|
|
3098
3135
|
|
|
3099
3136
|
## `@kerfjs/ui/row`
|
package/ai/skill.md
CHANGED
|
@@ -203,12 +203,24 @@ Hard rules:
|
|
|
203
203
|
16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
|
|
204
204
|
16a. Dividers between pinned chrome and scrolling content are scroll state, not decoration: a `Toolbar` draws none by default (`dividerSides` is for a permanent edge only). Call `wireScrollDividers(appRoot)` from `@kerfjs/ui/wire-scroll-dividers` once and retain its disposer; every `Pane` then draws the line under its header only while content is scrolled beneath it and over its footer only while more content lies below (never when the content fits), every `NavStack`'s top chrome and bottom toolbar and every `TabScaffold` bar do the same around the active view or scene (keyed on whatever actually scrolls there, including a sole `Pane`'s content), and every `TabBar` marks each side of its strip with tabs scrolled out of view. Configure a pane with `chromeDividers` (`scroll` default, `always`, `none`, also via `PaneConfig`), and a `NavStack` or `TabScaffold` with its own `chromeDividers` (same values: `always` draws the chrome lines without the wiring, `none` never, even when wired; a `SplitView` forwards it through `compactStack`); a `toolbarConfig.dividerSides` edge stays the Toolbar's own. Name app-owned chrome by id in `targets`. The wiring writes only `data-scroll-overflow` / `data-scroll-divider` state; never write a border onto a component to show a divider.
|
|
205
205
|
17. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. Put identity/title text directly in the zone as `ToolbarText`; wrap interactive controls and icon tiles in `ToolbarControlGroup`. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a group. Configure zone behavior with `Toolbar.centerAlign` and its `responsive` / `responsiveAt` policy instead of selecting toolbar zone classes. No policy clips an action: trailing (and stacked center) zones wrap whole groups onto another row, and the center zone never compresses below its content (a leading title too long for the row truncates with an ellipsis instead), so never hide or shrink a toolbar control to make it fit; use `responsive="wrap"` for a heading whose title must stay whole, and move genuinely lower-priority commands into an app-owned "More" popup menu. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature. A popup menu in a toolbar is a `PopupMenu` (`@kerfjs/ui/popup-menu`, registered once via `@kerfjs/ui/popup-menu/register`) in a `single` group with `nestedDropdown` and a `menuInset`: give it typed `items` (commands with `action`s, `heading`s, `divider`s) and a trigger `icon` plus visible `text` or an accessible `label`; never hand-write `wa-dropdown` / `wa-dropdown-item` markup for a menu. Let the group size that trigger from its icon, localized text, and caret; do not force a width on the menu or button. Nothing wraps inside a group: an icon sits beside its label on one row and a group's controls never break onto a second line — the group sizes to its content, so if it does not fit, the toolbar's `responsive` policy relocates whole groups. A `ToolbarText` is one line ending in an ellipsis by default; opt into `wrap` (capped by `maxLines`) or `ellipsis={false}` deliberately. Inside a group, a `Select` or `PopupMenu` trigger drops its focus ring while its popup is open (the open popup and its current row show where focus is) and the ring returns when the popup closes; a ring follows the control's shape (a pill for an icon-and-caret trigger, a circle for a compact icon button) — set `focusRingOwner="group"` on a Select whose group paints the composed ring, and never add CSS to show, hide, or reshape a ring. For a compact mixed group, keep the standard item padding and raised selected chrome; the selected item paints over the outer border without an internal separator. For an avatar control, set `content="avatar"` and `avatarImage` on the group instead of inserting an `img`: a lone control paints the contained image on the outer group and a multi-button group paints it only on the pressed selection highlight. Compose panel/dialog/page headings with a direct extra-large `ToolbarText`, optional grouped icon, grouped trailing controls, and app-owned supporting copy below. A non-interactive heading icon is an icon tile: put the `LucideIcon` directly in its `ToolbarControlGroup` (it takes an icon button's 40px slot and centers), never inside a `<button>` that does nothing. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Each zone item sits in the toolbar's top 44px control band, centered by its own size; a taller item (a wrapped title, a second trailing row) starts at the band's top and grows down without moving the others, so a wrapped `ToolbarText` keeps trailing controls beside its first line — do not add alignment CSS for this. Split dormant and interactive regions: `ListHeader` fills the available inline width by default; set `width="content"` to shrink-wrap while retaining its normal geometry, or `inline` when it belongs in surrounding text without outer margin, border, or padding. It keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square whose transparent hit layer keeps the pointer target at least 44px (44px wide by the 36px row in `density="compact"`); never shrink the target to match the visual, and never force the button to 44px. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets. Dividers are chrome and earn their place: a `Toolbar` draws none by default, and the line between pinned chrome and scrolling content comes from scroll state (rule 16a), so never add a border, a permanent `dividerSides`, or a margin to fake or adjust one.
|
|
206
|
-
18. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, toolbar title/supporting-copy ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
206
|
+
18. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, toolbar title/supporting-copy ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. For multi-line banner copy use `copyLayout="stacked"`; use `actionPlacement="below"` for an action on its own trailing row. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
|
|
207
|
+
|
|
208
|
+
For compact `Select` triggers, set `triggerWidth` to `fit-content`, `max-content`,
|
|
209
|
+
or `fill` and use `--kui-select-trigger-max-width` for a cap. Style custom
|
|
210
|
+
selected content with the public selected color, font-size, and font-weight
|
|
211
|
+
tokens; plain text ellipsizes in a narrow trigger.
|
|
212
|
+
|
|
213
|
+
19. Compose `ValueTable` from typed `ValueTableRow` entries instead of handwritten `dt`/`dd` wrappers. Pass `icon` for the optional 24px leading visual; the row owns 8px of root-scaled top and bottom padding, the 8px iconless or 40px icon-bearing separator start, and the common 8px right inset. 20. Use the standard direct `Toolbar` composition for a panel, dialog, or page heading, not a private wrapper or custom heading row. Put an optional icon in a `ToolbarControlGroup`, the title directly in the leading zone as extra-large `ToolbarText`, and actions in a trailing group. Set `headingLevel` for page/section landmarks. Supporting copy stays below the toolbar as app-owned content. The app owns modal behavior, focus, dismissal, command policy, ids, and action handling. 21. Space with the official five-step scale, picked by how connected two elements are — not by eye. `0` `--kui-space-none` = no separation (one unit); `4px` `--kui-space-2xs` = very minor air on a connected cluster; `8px` `--kui-space-xs` = standard, between elements within a group; `16px` `--kui-space-m` = minor, between homogeneous groups; `24px` `--kui-space-l` = major, between heterogeneous groups (the `.kui-content` rhythm). The 8px-vs-24px distinction is inside-a-group vs between-major-differing-regions. `--kui-space-s` (12px) and `--kui-space-xl` (32px) are off-scale exceptions. For `Row.gap`, `Grid.gap`, or `List.gap`, pass a finite shorthand such as `gap="xs"` or `gap="m"`; use `Spacer` for one intentional typed empty width/height or a flexible main-axis gap. When one token is insufficient, import typed builders from the CSS-free `@kerfjs/ui/css-values` subpath. Preserve property grammar: lengths for gap/Spacer/Skeleton geometry, `flex()` for Row/Grid/List flex, and a foreground color for choice icons: `uiColor()` with a `*-on-*` or text token (`success-on-quiet`, `text-quiet`) or `foregroundColorVar()`. Fill tokens (`*-fill-*`) are backgrounds, not foregrounds, and `SelectChoice.color` rejects them. Never cast between brands or emit raw row `style` declarations. `plus` is not standalone and must be wrapped in `calc`; `remify()` remains source-CSS syntax and is never a runtime prop value. See `docs/layout.md` "Spacing scale". 22. Pick a whole-screen layout from the opt-in, tree-shakeable subpaths by data + interaction + device, and derive responsiveness from `@kerfjs/ui/device-class`'s `deviceClass()` (`compact` = handset or portrait tablet = one pane at a time). Simple/flat → `NavStack` with one entry (single pane), plus `TabScaffold` (`@kerfjs/ui/tab-scaffold`, iOS bottom tabs, each tab its own `NavStack`) for 2–5 co-equal sections on `compact`; show an unread count on a tab with its `badge` (a number or short string, rendered as the top-trailing danger `Badge` on the icon) plus a localized `badgeLabel` ("3 unread", folded into the tab's name as "Inbox, 3 unread"), never by concatenating the count into `label` or restyling the badge; for new content without a count pass `badge: true` (the text-free dot) with its required `badgeLabel` ("New activity"). Drill-down → `NavStack` (`@kerfjs/ui/nav-stack`), upgrading to `SplitView` (`@kerfjs/ui/split-view`, list-detail) once both panes fit (`atLeast('tablet')` landscape); `SplitView` collapses to a `NavStack` on `compact`. Keep each stack's ordered views controlled; put view-specific bottom chrome on `NavStackView.bottomToolbar` (or use the component-level persistent fallback), then call `wireNavStack` so content slides while the active view's top and bottom chrome cross-fade and focus moves into the new top view/restores on pop. Mark a preferred initial heading or control with `data-nav-focus` when DOM order is not sufficient. The stack's top chrome is a real `Toolbar`: put a view's groups on `NavStackView.leading` / `center` / `toolbar` (trailing), and configure the bar through `toolbarConfig` (`ToolbarConfig` plus `label`, `titleSize`, `headingLevel`) and `backIcon` / `backText`, never with CSS. `SplitView` forwards both of its inner components: `resizable` takes the list `ResizableRegion`'s `separator`, `handleIcon`, `contentOverflow`, and collapse props (`collapsed`, `transitioning`, `collapseMotion`, `restoreControl`, `restorePosition`), and `compactStack` takes the compact stack's `toolbarConfig`, `backIcon`, `backText`, `hideToolbar`, `bottomToolbar`, plus `list` / `detail` view toolbars (`leading`, `center`, `toolbar`, `bottomToolbar`). Complex tool with peripheral panels → `Workbench` (`@kerfjs/ui/workbench`, collapsible rails + drawer) `atLeast('desktop')`, degrading to `NavStack`/overlays below. Workbench panels are fixed-size unless a panel opts in with `resizable` (`true` or `{ min, max }`); then render `size={sizeSignal.value}` and call `wireWorkbench(root, { id, panels: { leftRail: { size: sizeSignal, storageKey? } }, deviceClass })` from `@kerfjs/ui/wire-workbench` for pointer drags, arrow/Shift+arrow/Home/End on the separator, persistence, and no resizing on `compact` classes. Inline rails, fixed or resizable, leave the work area `mainMinSize` px of width (a `Workbench` prop, default 320, `0` off), and an inline bottom drawer leaves it `mainMinHeight` px of height (default 120, `0` off): resizable panels stop growing there, rails shrink in proportion when the Workbench narrows and the drawer when it gets shorter, so do not add your own main-area `min-width` / `min-height`. Rails present as overlays below the `narrow` Workbench container breakpoint (704px) by default — `responsiveOverlayAt: "compact"` moves that to 448px and `"never"` keeps a rail inline — and a bottom drawer opts in the same way; do not derive `presentation` from `deviceClass`, and overlays never resize. At compact widths an overlay rail fills the Workbench less a 44px dismiss strip (`--kui-workbench-overlay-dismiss-margin`) on the side away from its edge; `compactOverlay: "full"` makes one rail fill it. Pass each such panel's `collapsed` signal to `wireWorkbench` too (`panels: { leftRail: { collapsed: navCollapsed } }`, `size` optional) so the overlay is transient like `wireSidebar`'s compact overlay: it collapses when the breakpoint begins to apply (the inline state returns when it ends), takes focus on its first control and keeps Tab inside it while open, and closes on Escape or an outside press with focus returned to its toggle (give each toggle `aria-controls` naming its panel's derived id, `<workbench id>-left-rail` / `-right-rail` / `-bottom-drawer`, so a panel open at wire-up has a focus target too); opening one overlay closes the other open overlays, so they never cover each other's controls; do not hand-roll those listeners (`dismissOverlays: false` opts out of all of it, `exclusiveOverlays: false` of exclusivity only). Collapse stays the app's `collapsed` flag and keeps the size, so an expanded panel returns at its last size. Let the Workbench compose panel toolbars: give each panel `toolbar: { label, title?, leading?, center?, trailing?, toggle: { action, name, showLabel?, hideLabel? } }` and the work area `mainToolbar` (and `mainBottomToolbar` for a drawer). Each of these toolbars takes the `Toolbar`'s configuration (`ToolbarConfig`: `dividerSides`, `centerAlign`, `responsive`, `responsiveAt`, `safeAreaEdges`); configure a composed toolbar through those props (for example `dividerSides: ""` to drop its divider), never with CSS. Configure the composed panes and chrome lists the same way: a panel's `pane` (and `CollapsiblePanel`'s `pane`) and the Workbench's `mainPane` take `PaneConfig` (`contentElement`, `contentLabel`, `separators`, `safeAreaEdges` — for example `{ contentElement: "nav", contentLabel: "Files" }` for a navigator rail), and `mainHeaderList` / `mainFooterList` take `ListConfig` (`gap`, `hAlign`, `vAlign`, `dividerSides`, `textInsets`, `controlInsets`). Open, a panel's toolbar places groups in its leading, center, and trailing zones, with the toggle last; mark a ToolbarControlGroup relocateOnCollapse to keep it available when closed (pass marked groups directly or in arrays rather than JSX fragments); closed, marked groups follow zone order into the work area before the toggle — a left rail's lead `mainToolbar`, a right rail's end it, a drawer's trail `mainBottomToolbar` or float in a corner `FloatingToolbar` — and panel-only groups stay behind. A control sits near where its effect appears: a collapsed drawer's restore belongs in the bottom toolbar or a `FloatingToolbar` beside the drawer, not in a distant top toolbar. Do not hand-place panel toggles in the work-area toolbar or render a second copy, and handle only the toggle's `data-action`. A collapsed panel renders `inert` and `aria-hidden` by itself, on the rail/drawer and its content (its `restoreControl` stays outside and reachable), so do not add your own `tabindex`, `aria-hidden`, or `inert` to hide it. These are declarative (the app owns the stack/selection/collapsed/active state as signals) with disposer-returning `wire…` helpers; each stays out of the barrel, and its CSS-aware browser import loads the layout's CSS plus that of every component it renders (`Pane`, `Toolbar`, `List`, …), so do not hand-import `pane.css` or the other internal stylesheets; the companion `.css` subpath is only for pipelines without the `browser` condition. For a standalone collapsible rail or bottom drawer outside a full shell, use `CollapsiblePanel` + `CollapsiblePanelToggle` (`@kerfjs/ui/collapsible-panel`) with `wireSidebar` (`@kerfjs/ui/wire-sidebar`): the standard collapse animation and per-side icon convention (`PanelLeft*`/`PanelRight*`/`PanelBottom*`) plus toggle, focus, compact overlay, and persistence semantics. Give a standalone panel the same `toolbar` roles and render `CollapsiblePanelRelocated` in your work-area toolbar (first in leading for a left rail, last in trailing for a right rail, a bottom toolbar or a `FloatingToolbar` restoreControl for a drawer) instead of hand-placing a second toggle. A collapsed `CollapsiblePanel`, `ResizableRegion`, or Workbench panel renders `inert` and `aria-hidden` by itself, so do not hide collapsed content yourself either. Likewise an open side overlay (a Workbench rail overlay, a `wireSidebar` compact overlay, an overlay `CollapsiblePanel` or horizontal `ResizableRegion`) hides the covered work area's `FloatingToolbar`s and restore corners by itself until it closes, so do not hide them from overlay state. A compact overlay opens only on a user action: wire-up on a compact device and a wide-to-compact crossing collapse every panel, and a wide crossing restores the inline state. Seed the signal with `signal(device.value.compact)` and pass the panel's `inlineCollapsed` default so the first compact render has no overlay. Dialogs pick the same inner layout, then present per device class (full-screen modal on `compact`, inline on desktop). A list-detail dialog is a Workbench-shaped layout on roomy devices: a full-height list sidebar and a full-height main column, each a `Pane` with its own top `Toolbar`; the main column holds the primary xl title, the close control (`data-dialog="close"` in a `without-header` Web Awesome dialog), and the record actions, never a header spanning both columns. A top-level percentage-height shell needs a definite containing height: opt into `@kerfjs/ui/document.css` and put `.kui-app-root` on the one direct mount container, or provide equivalent application-owned geometry. The global baseline is deliberately absent from `styles.css` and component imports. See `docs/app-layouts.md`, `docs/document-baseline.md`, and `docs/collapsible-panel.md`. 23. Layouts and `Pane` are safe-area aware without configuration: backgrounds, separators, and dividers paint through a device's unsafe areas (a collapsible rail or drawer grows by the inset it docks to), content is padded only on the sides a region actually reaches, and block insets are scroll padding inside the scroller so first/last content can always be scrolled clear. Interior edges get nothing, and a collapsed rail hands its edge back to the center. Never add your own `env(safe-area-inset-*)` padding around a kerf layout or pane — that double-insets. In an app-owned arrangement of panes, pass `Pane.safeAreaEdges` (the sides that pane reaches; `[]` opts out); give an app bar or bottom bar that sits at a screen edge outside a Pane header or footer `Toolbar.safeAreaEdges` for the sides it reaches (for example `['block-start', 'inline-start', 'inline-end']`); the Workbench `mainToolbar` / `mainBottomToolbar` and panel `toolbar` configurations forward the same `safeAreaEdges` to their `Toolbar`. Do not set the internal `--kui-edge-inset-*` context yourself. The device insets are `--kui-safe-area-*` (defaulting to `env()`), overridable on `:root`. See `docs/app-layouts.md` "Safe areas".
|
|
214
|
+
|
|
215
|
+
For application tabs, `AppTab presentation="icon-only"` retains its accessible `name`, `labelMaxWidth` truncates the visible name, and `attention` colors it through `--kui-app-tab-attention-color`. Configure TabBar strip geometry through public `--kui-tab-bar-strip-*` tokens.
|
|
216
|
+
|
|
217
|
+
Use `--kui-resizable-region-background` for a region surface and `contentOverflow="visible"` while its anchored popup needs to escape. Choose a top or bottom `restorePosition`, typed `restoreInset`, or `restorePlacement="inline"` for its collapsed restore control. `FloatingToolbar placement="inline"` stays in normal flow; its per-edge inset tokens and `safeAreaInsets` configure floating placement.
|
|
218
|
+
|
|
219
|
+
Use `ListItem density="spacious"` for larger option rows, `multiline` plus `multilineIconAlign="center"` when its icon should center on wrapped copy, `divider` for row separators, and `state="drag-target"` for the drop target treatment. Public `--kui-list-item-*` tokens adjust row, icon, label, and trailing geometry and color; ListHeader height, title padding, and border tokens adjust section density.
|
|
220
|
+
|
|
221
|
+
Use `Toolbar responsive="trailing-priority"` when an expanded trailing search needs a full second row below its heading at `responsiveAt`. Configure a leading minimum width, trailing gap and justification, or zone inline padding with the public `--kui-toolbar-*` tokens rather than selectors into toolbar zones.
|
|
222
|
+
|
|
223
|
+
For compact dialog copy, use `Text flush lineHeight="tight"`; for compact metadata, use `ValueTable density="compact"` and its public row columns/padding/gap tokens. `ToolbarText size="xsmall"` fits a dense rail heading. A `TokenSearchField` editor shrinks inside a narrow group by default; set `--kui-token-search-editor-min-width` when a minimum is needed. A full-height shell uses the one `.kui-app-root` mount container documented in `docs/document-baseline.md`.
|
|
212
224
|
|
|
213
225
|
Common mistakes:
|
|
214
226
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Web Awesome JSX signatures for the UI authoring corpus
|
|
2
2
|
|
|
3
|
-
Generated from the emitted `@kerfjs/ui@5.0.0-beta.
|
|
3
|
+
Generated from the emitted `@kerfjs/ui@5.0.0-beta.60` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { KerfCustomElement } from 'kerfjs/jsx-runtime';
|
package/dist/app-tab.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ type AppTabRootAttributes = Readonly<Record<`data-${string}`, string | undefined
|
|
|
8
8
|
'data-selected'?: never;
|
|
9
9
|
'data-tab-dragging'?: never;
|
|
10
10
|
'data-tab-drop-position'?: never;
|
|
11
|
+
'data-attention'?: never;
|
|
11
12
|
}>;
|
|
12
13
|
type AppTabPresentation = 'pill' | 'segmented' | 'icon-only';
|
|
13
14
|
type AppTabSize = 'default' | 'compact';
|
|
@@ -15,6 +16,8 @@ interface AppTabProps {
|
|
|
15
16
|
id: string;
|
|
16
17
|
name: string;
|
|
17
18
|
selected?: boolean;
|
|
19
|
+
/** Emphasize the visible tab name with the attention color token. */
|
|
20
|
+
attention?: boolean;
|
|
18
21
|
closable?: boolean;
|
|
19
22
|
draggable?: boolean;
|
|
20
23
|
leading?: KerfUiContent;
|
|
@@ -47,6 +50,6 @@ interface AppTabProps {
|
|
|
47
50
|
/** Native named-slot assignment when composed inside a web component. */
|
|
48
51
|
slot?: string;
|
|
49
52
|
}
|
|
50
|
-
declare function AppTab({ id, name, selected, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
53
|
+
declare function AppTab({ id, name, selected, attention, closable, draggable, leading, trailing, presentation, size, labelMaxWidth, closeIcon, selectAction, closeAction, className, placeholder, pending, rootAttributes, slot, }: AppTabProps): SafeHtml;
|
|
51
54
|
|
|
52
55
|
export { AppTab, type AppTabPresentation, type AppTabProps, type AppTabSize };
|
package/dist/app-tab.js
CHANGED
package/dist/catalog.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { Workbench } from './chunk-
|
|
1
|
+
import { Workbench } from './chunk-2OXQHM7I.js';
|
|
2
2
|
|
|
3
3
|
import { PopupMenu } from './chunk-UWONG4QE.js';
|
|
4
4
|
|
|
5
5
|
import { Row } from './chunk-VZOFZPSO.js';
|
|
6
6
|
import { ListInsetText } from './chunk-DG6G5EPF.js';
|
|
7
|
-
import { ListItem } from './chunk-
|
|
7
|
+
import { ListItem } from './chunk-5I7OHCIP.js';
|
|
8
8
|
import { List } from './chunk-NAPE7WUS.js';
|
|
9
9
|
|
|
10
|
-
import { ToolbarText } from './chunk-
|
|
10
|
+
import { ToolbarText } from './chunk-3SXMEK3B.js';
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
import { ListHeader } from './chunk-
|
|
15
|
-
import { Text } from './chunk-
|
|
14
|
+
import { ListHeader } from './chunk-5Q3N6EV7.js';
|
|
15
|
+
import { Text } from './chunk-AUKT3KMG.js';
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
import { ToolbarControlGroup, ToolbarActionLink } from './chunk-7JUBXOIV.js';
|
|
21
|
-
import { Toolbar } from './chunk-
|
|
21
|
+
import { Toolbar } from './chunk-MERWRTBG.js';
|
|
22
22
|
|
|
23
23
|
import { LucideIcon } from './chunk-4R777DUZ.js';
|
|
24
24
|
import { filterDataAttributes } from './chunk-SRSJO5QE.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { WORKBENCH_MAIN_MIN_SIZE, WORKBENCH_MAIN_MIN_HEIGHT, workbenchRegionId, WORKBENCH_RESIZE_DEFAULTS } from './chunk-PSHUSWQH.js';
|
|
2
|
-
import { clampRegionSize, ResizeGrip } from './chunk-
|
|
2
|
+
import { clampRegionSize, ResizeGrip } from './chunk-KLJKU6ZL.js';
|
|
3
3
|
import { List } from './chunk-NAPE7WUS.js';
|
|
4
|
-
import { FloatingToolbar } from './chunk-
|
|
5
|
-
import { composedPanelBody, relocatedPanelGroups } from './chunk-
|
|
6
|
-
import { Toolbar } from './chunk-
|
|
4
|
+
import { FloatingToolbar } from './chunk-I3Q7KKYM.js';
|
|
5
|
+
import { composedPanelBody, relocatedPanelGroups } from './chunk-T57AXDFM.js';
|
|
6
|
+
import { Toolbar } from './chunk-MERWRTBG.js';
|
|
7
7
|
import { Pane } from './chunk-EZVNC4J6.js';
|
|
8
8
|
import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
|
|
9
9
|
|
|
@@ -415,4 +415,4 @@ function Workbench({
|
|
|
415
415
|
|
|
416
416
|
export { Workbench };
|
|
417
417
|
|
|
418
|
-
//# sourceMappingURL=chunk-
|
|
418
|
+
//# sourceMappingURL=chunk-2OXQHM7I.js.map
|