@kerfjs/ui 5.0.0-beta.61 → 5.0.0-beta.62

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.
Files changed (80) hide show
  1. package/ai/component-catalog.json +12 -5
  2. package/ai/component-composition.json +8 -1
  3. package/ai/components/pane.md +3 -2
  4. package/ai/components/select.md +1 -0
  5. package/ai/components/toolbar-text.md +2 -1
  6. package/ai/public-api-signatures-v1.md +27 -11
  7. package/ai/skill.md +3 -1
  8. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  9. package/dist/catalog.js +3 -3
  10. package/dist/{chunk-TEYARRAK.js → chunk-4MG3KXJM.js} +4 -1
  11. package/dist/chunk-4MG3KXJM.js.map +1 -0
  12. package/dist/{chunk-NYL63PSD.js → chunk-ENGVYQPG.js} +4 -3
  13. package/dist/chunk-ENGVYQPG.js.map +1 -0
  14. package/dist/{chunk-5PESG2VP.js → chunk-KYDDCJXU.js} +4 -3
  15. package/dist/chunk-KYDDCJXU.js.map +1 -0
  16. package/dist/{chunk-MERWRTBG.js → chunk-N2DRU35S.js} +1 -1
  17. package/dist/chunk-N2DRU35S.js.map +1 -0
  18. package/dist/{chunk-EZVNC4J6.js → chunk-OD2VXAPL.js} +4 -1
  19. package/dist/chunk-OD2VXAPL.js.map +1 -0
  20. package/dist/{chunk-N3GKMPDW.js → chunk-RKTTF3L4.js} +3 -1
  21. package/dist/chunk-RKTTF3L4.js.map +1 -0
  22. package/dist/{chunk-C4OYOKWX.js → chunk-UA6JW52D.js} +36 -2
  23. package/dist/chunk-UA6JW52D.js.map +1 -0
  24. package/dist/{chunk-3SXMEK3B.js → chunk-V3DX3K65.js} +1 -1
  25. package/dist/chunk-V3DX3K65.js.map +1 -0
  26. package/dist/{chunk-Y74NWGQW.js → chunk-X6ADHJNI.js} +45 -20
  27. package/dist/chunk-X6ADHJNI.js.map +1 -0
  28. package/dist/collapsible-panel.js +2 -2
  29. package/dist/index.d.ts +1 -1
  30. package/dist/index.js +6 -6
  31. package/dist/nav-stack.d.ts +3 -1
  32. package/dist/nav-stack.js +1 -1
  33. package/dist/pane.d.ts +8 -3
  34. package/dist/pane.js +1 -1
  35. package/dist/select.d.ts +2 -0
  36. package/dist/select.js +1 -1
  37. package/dist/split-view.d.ts +1 -1
  38. package/dist/split-view.js +1 -1
  39. package/dist/styles/app-tab.css +84 -0
  40. package/dist/styles/nav-stack.css +13 -0
  41. package/dist/styles/pane.css +33 -0
  42. package/dist/styles/resizable-region.css +9 -0
  43. package/dist/styles/select.css +15 -0
  44. package/dist/styles/split-view.css +6 -0
  45. package/dist/styles/tab-bar.css +3 -0
  46. package/dist/styles/tab-scaffold.css +13 -0
  47. package/dist/styles/toolbar-text.css +15 -6
  48. package/dist/styles/toolbar.css +7 -0
  49. package/dist/styles/workbench.css +117 -93
  50. package/dist/tab-bar.d.ts +6 -2
  51. package/dist/tab-bar.js +1 -1
  52. package/dist/tab-scaffold.d.ts +3 -0
  53. package/dist/tab-scaffold.js +1 -0
  54. package/dist/tab-scaffold.js.map +1 -1
  55. package/dist/toolbar-text.d.ts +1 -1
  56. package/dist/toolbar-text.js +1 -1
  57. package/dist/toolbar.d.ts +2 -2
  58. package/dist/toolbar.js +1 -1
  59. package/dist/wire-tab-bars.js +1 -1
  60. package/dist/workbench.js +1 -1
  61. package/docs/collapsible-panel.md +4 -3
  62. package/docs/component-selection.md +27 -8
  63. package/docs/layout.md +31 -0
  64. package/docs/nav-stack.md +5 -0
  65. package/docs/split-view.md +5 -0
  66. package/docs/sunken-panel.md +8 -1
  67. package/docs/tab-scaffold.md +5 -0
  68. package/docs/webawesome-theme.md +36 -6
  69. package/docs/workbench.md +22 -10
  70. package/llms.txt +4 -0
  71. package/package.json +1 -1
  72. package/dist/chunk-3SXMEK3B.js.map +0 -1
  73. package/dist/chunk-5PESG2VP.js.map +0 -1
  74. package/dist/chunk-C4OYOKWX.js.map +0 -1
  75. package/dist/chunk-EZVNC4J6.js.map +0 -1
  76. package/dist/chunk-MERWRTBG.js.map +0 -1
  77. package/dist/chunk-N3GKMPDW.js.map +0 -1
  78. package/dist/chunk-NYL63PSD.js.map +0 -1
  79. package/dist/chunk-TEYARRAK.js.map +0 -1
  80. package/dist/chunk-Y74NWGQW.js.map +0 -1
package/dist/pane.d.ts CHANGED
@@ -22,6 +22,7 @@ type PaneRootAttributes = Readonly<Record<`data-${string}`, string | undefined>
22
22
  'data-safe-area-inline-end'?: never;
23
23
  'data-chrome-placement'?: never;
24
24
  'data-chrome-dividers'?: never;
25
+ 'data-appearance'?: never;
25
26
  }>;
26
27
  /** How a Pane's header and footer relate to its scrolling content. */
27
28
  type PaneChromePlacement = 'fixed' | 'auto';
@@ -31,6 +32,8 @@ type PaneChromePlacement = 'fixed' | 'auto';
31
32
  * chrome, as `wireScrollDividers` reports; `always`; or `none`.
32
33
  */
33
34
  type PaneChromeDividers = 'scroll' | 'always' | 'none';
35
+ /** Background treatment of the Pane's scrolling work surface. */
36
+ type PaneAppearance = 'default' | 'sunken';
34
37
  interface PaneProps {
35
38
  /** Optional fixed chrome above the scrolling content, arranged vertically. */
36
39
  header?: KerfUiContent;
@@ -56,6 +59,8 @@ interface PaneProps {
56
59
  * The line is drawn inside the chrome, so no state moves the content.
57
60
  */
58
61
  chromeDividers?: PaneChromeDividers;
62
+ /** Paint the scrolling work surface with the shared lowered-surface color. */
63
+ appearance?: PaneAppearance;
59
64
  /** Root semantics. Defaults to `div`. */
60
65
  element?: PaneElement;
61
66
  /** Scrolling content semantics. Defaults to `div`. */
@@ -90,13 +95,13 @@ interface PaneProps {
90
95
  * or a CollapsiblePanel) forwards, so the app configures that pane instead of
91
96
  * styling it. An omitted or `undefined` field keeps the composite's default.
92
97
  */
93
- type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers'>;
98
+ type PaneConfig = Pick<PaneProps, 'contentElement' | 'contentLabel' | 'separators' | 'safeAreaEdges' | 'chromeDividers' | 'appearance'>;
94
99
  /**
95
100
  * An unpadded application column with optional fixed header/footer slots and one
96
101
  * scrolling vertical content owner. Separator lines are independently opt-in on
97
102
  * each logical edge, so the same component works as a sidebar, main area,
98
103
  * inspector, or dialog column.
99
104
  */
100
- declare function Pane({ header, children, footer, chromePlacement, chromeDividers, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
105
+ declare function Pane({ header, children, footer, chromePlacement, chromeDividers, appearance, element, contentElement, separators, safeAreaEdges, id, label, contentLabel, className, headerClassName, contentClassName, footerClassName, rootAttributes, slot, }: PaneProps): kerfjs.SafeHtml;
101
106
 
102
- export { Pane, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
107
+ export { Pane, type PaneAppearance, type PaneChromeDividers, type PaneChromePlacement, type PaneConfig, type PaneContentElement, type PaneElement, type PaneProps, type PaneSeparatorSide };
package/dist/pane.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Pane } from './chunk-EZVNC4J6.js';
1
+ export { Pane } from './chunk-OD2VXAPL.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=pane.js.map
package/dist/select.d.ts CHANGED
@@ -58,6 +58,8 @@ interface SelectBaseProps<Value extends string = string> {
58
58
  size?: SelectSize;
59
59
  /** Closed trigger width; omit to keep the presentation's default. */
60
60
  triggerWidth?: SelectTriggerWidth;
61
+ /** Show the disclosure caret (default); omit it for a compact icon-only trigger. */
62
+ caret?: boolean;
61
63
  /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */
62
64
  focusRingOwner?: SelectFocusRingOwner;
63
65
  /** Maximum closed-control label width in CSS pixels before ellipsis. */
package/dist/select.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Select } from './chunk-TEYARRAK.js';
1
+ export { Select } from './chunk-4MG3KXJM.js';
2
2
 
3
3
 
4
4
 
@@ -2,8 +2,8 @@ import * as kerfjs from 'kerfjs';
2
2
  import { NavStackProps, NavStackView } from './nav-stack.js';
3
3
  import { ResizableRegionProps } from './resizable-region.js';
4
4
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
5
- import './toolbar.js';
6
5
  import './pane.js';
6
+ import './toolbar.js';
7
7
  import './sides-BPSWde0A.js';
8
8
  import './toolbar-text.js';
9
9
  import './css-values.js';
@@ -1,4 +1,4 @@
1
- import { NavStack } from './chunk-5PESG2VP.js';
1
+ import { NavStack } from './chunk-KYDDCJXU.js';
2
2
  import { ResizableRegion } from './chunk-KLJKU6ZL.js';
3
3
 
4
4
 
@@ -162,6 +162,90 @@
162
162
  width: 2rem;
163
163
  min-width: 2rem;
164
164
  }
165
+ /* TabBar owns the tablist width query; AppTab owns its own responsive
166
+ geometry and visually hidden name. The name remains in the accessibility
167
+ tree, so the tab keeps its accessible name without a rerender. */
168
+ @container kui-tab-bar-tabs (max-width: 52rem) {
169
+ .kui-tab-bar[data-icon-only-at="wide"]
170
+ .kui-tab-bar__tabs
171
+ > .kui-app-tab[data-presentation="segmented"] {
172
+ width: 2rem;
173
+ min-width: 2rem;
174
+ flex: none;
175
+ }
176
+ .kui-tab-bar[data-icon-only-at="wide"]
177
+ .kui-app-tab[data-presentation="segmented"]
178
+ .kui-app-tab__select {
179
+ width: 100%;
180
+ justify-content: center;
181
+ }
182
+ .kui-tab-bar[data-icon-only-at="wide"]
183
+ .kui-app-tab[data-presentation="segmented"]
184
+ .kui-app-tab__name {
185
+ position: absolute;
186
+ width: 1px;
187
+ height: 1px;
188
+ padding: 0;
189
+ overflow: hidden;
190
+ clip: rect(0, 0, 0, 0);
191
+ white-space: nowrap;
192
+ clip-path: inset(50%);
193
+ }
194
+ }
195
+ @container kui-tab-bar-tabs (max-width: 44rem) {
196
+ .kui-tab-bar[data-icon-only-at="narrow"]
197
+ .kui-tab-bar__tabs
198
+ > .kui-app-tab[data-presentation="segmented"] {
199
+ width: 2rem;
200
+ min-width: 2rem;
201
+ flex: none;
202
+ }
203
+ .kui-tab-bar[data-icon-only-at="narrow"]
204
+ .kui-app-tab[data-presentation="segmented"]
205
+ .kui-app-tab__select {
206
+ width: 100%;
207
+ justify-content: center;
208
+ }
209
+ .kui-tab-bar[data-icon-only-at="narrow"]
210
+ .kui-app-tab[data-presentation="segmented"]
211
+ .kui-app-tab__name {
212
+ position: absolute;
213
+ width: 1px;
214
+ height: 1px;
215
+ padding: 0;
216
+ overflow: hidden;
217
+ clip: rect(0, 0, 0, 0);
218
+ white-space: nowrap;
219
+ clip-path: inset(50%);
220
+ }
221
+ }
222
+ @container kui-tab-bar-tabs (max-width: 28rem) {
223
+ .kui-tab-bar[data-icon-only-at="compact"]
224
+ .kui-tab-bar__tabs
225
+ > .kui-app-tab[data-presentation="segmented"] {
226
+ width: 2rem;
227
+ min-width: 2rem;
228
+ flex: none;
229
+ }
230
+ .kui-tab-bar[data-icon-only-at="compact"]
231
+ .kui-app-tab[data-presentation="segmented"]
232
+ .kui-app-tab__select {
233
+ width: 100%;
234
+ justify-content: center;
235
+ }
236
+ .kui-tab-bar[data-icon-only-at="compact"]
237
+ .kui-app-tab[data-presentation="segmented"]
238
+ .kui-app-tab__name {
239
+ position: absolute;
240
+ width: 1px;
241
+ height: 1px;
242
+ padding: 0;
243
+ overflow: hidden;
244
+ clip: rect(0, 0, 0, 0);
245
+ white-space: nowrap;
246
+ clip-path: inset(50%);
247
+ }
248
+ }
165
249
  /* In a TabBar, the tab styles itself in the context of its parent strip. A
166
250
  segmented strip's outer ends follow the pill track: the first tab's leading
167
251
  corners, and a filled strip's last tab's trailing corners, are pill-rounded
@@ -100,6 +100,13 @@
100
100
  inset: 0;
101
101
  }
102
102
 
103
+ .kui-nav-stack__view[data-appearance="sunken"] {
104
+ background: var(
105
+ --kui-sunken-panel-background,
106
+ var(--kui-color-surface-lowered)
107
+ );
108
+ }
109
+
103
110
  /* Each view is its region's scroll owner: block insets become padding inside
104
111
  the scroller so content scrolls under an unsafe edge but can always be
105
112
  scrolled clear. A view whose only child is a Pane or layout lets that child
@@ -217,4 +224,10 @@
217
224
  :is([data-workbench-main], [data-workbench-panel-content])
218
225
  > [data-component="nav-stack"]:only-child {
219
226
  height: 100%;
227
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
228
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
229
+ --kui-edge-inset-inline-start: var(
230
+ --_kui-workbench-content-edge-inline-start
231
+ );
232
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
220
233
  }
@@ -22,6 +22,33 @@
22
22
  grid-template-rows: auto minmax(0, 1fr) auto;
23
23
  }
24
24
 
25
+ /* Paint the active scroll owner once, so alpha lowered colors do not stack.
26
+ Fixed chrome leaves the content slot scrolling; auto chrome lets the Pane
27
+ root scroll in its short mode, while its content remains transparent. */
28
+ .kui-pane[data-appearance="sunken"] > .kui-pane__content {
29
+ background: var(
30
+ --kui-sunken-panel-background,
31
+ var(--kui-color-surface-lowered)
32
+ );
33
+ }
34
+
35
+ .kui-pane[data-appearance="sunken"][data-chrome-placement="auto"] {
36
+ background: var(
37
+ --kui-sunken-panel-background,
38
+ var(--kui-color-surface-lowered)
39
+ );
40
+ }
41
+
42
+ .kui-pane[data-appearance="sunken"][data-chrome-placement="auto"]
43
+ > .kui-pane__content {
44
+ background: transparent;
45
+ }
46
+
47
+ .kui-pane[data-appearance="sunken"][data-chrome-placement="auto"]
48
+ > :is(.kui-pane__header, .kui-pane__footer) {
49
+ background: var(--kui-pane-chrome-background, var(--kui-color-surface));
50
+ }
51
+
25
52
  /* Safe areas. The pane root never pads, so its background and separators paint
26
53
  through an unsafe area; its slots compensate on the edges the pane still
27
54
  touches. The inherited `--kui-edge-inset-*` context says how far each edge
@@ -217,6 +244,12 @@
217
244
  :is([data-workbench-main], [data-workbench-panel-content])
218
245
  > [data-component="pane"]:only-child {
219
246
  height: 100%;
247
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
248
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
249
+ --kui-edge-inset-inline-start: var(
250
+ --_kui-workbench-content-edge-inline-start
251
+ );
252
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
220
253
  }
221
254
 
222
255
  /* As the only child of a NavStack view or a TabScaffold scene, a Pane fills
@@ -73,6 +73,15 @@
73
73
  > .kui-resizable-region__content {
74
74
  overflow: visible;
75
75
  }
76
+ /* An open Web Awesome dropdown (including PopupMenu) releases both clipping
77
+ ancestors without rerendering the region during the dropdown lifecycle. */
78
+ .kui-resizable-region:has(wa-dropdown[open]) {
79
+ z-index: var(--kui-resizable-region-popup-z, 5);
80
+ overflow: visible;
81
+ }
82
+ .kui-resizable-region:has(wa-dropdown[open]) > .kui-resizable-region__content {
83
+ overflow: visible;
84
+ }
76
85
  .kui-resizable-region[data-separator="hidden"] {
77
86
  --kui-resizable-region-separator-color: transparent;
78
87
  }
@@ -108,6 +108,21 @@
108
108
  margin-inline-start: 0.75rem;
109
109
  transform: scale(0.875);
110
110
  }
111
+ .kui-select[data-caret="false"]::part(expand-icon) {
112
+ display: none;
113
+ }
114
+ .kui-select[data-selected-presentation="icon-only"][data-caret="false"]::part(
115
+ combobox
116
+ ) {
117
+ width: var(
118
+ --_kui-toolbar-control-group-slot-height,
119
+ var(--_kui-select-height)
120
+ );
121
+ justify-content: center;
122
+ }
123
+ .kui-select[data-caret="false"] .kui-select__placeholder-chevron {
124
+ display: none;
125
+ }
111
126
  .kui-select[data-selected-presentation="icon-only"]::part(display-input) {
112
127
  position: absolute;
113
128
  width: 1px;
@@ -137,4 +137,10 @@
137
137
  :is([data-workbench-main], [data-workbench-panel-content])
138
138
  > [data-component="split-view"]:only-child {
139
139
  height: 100%;
140
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
141
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
142
+ --kui-edge-inset-inline-start: var(
143
+ --_kui-workbench-content-edge-inline-start
144
+ );
145
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
140
146
  }
@@ -45,6 +45,9 @@
45
45
  scroll-padding-inline: var(--kui-tab-bar-strip-scroll-padding-inline, 0);
46
46
  overscroll-behavior-inline: contain;
47
47
  }
48
+ .kui-tab-bar[data-icon-only-at] .kui-tab-bar__tabs {
49
+ container: kui-tab-bar-tabs / inline-size;
50
+ }
48
51
  .kui-tab-bar[data-presentation="segmented"],
49
52
  .kui-tab-bar[data-presentation="inspector"] {
50
53
  --kui-tab-bar-background: var(--kui-color-neutral-fill-quiet);
@@ -46,6 +46,13 @@
46
46
  inset: 0;
47
47
  }
48
48
 
49
+ .kui-tab-scaffold__scene[data-appearance="sunken"] {
50
+ background: var(
51
+ --kui-sunken-panel-background,
52
+ var(--kui-color-surface-lowered)
53
+ );
54
+ }
55
+
49
56
  /* A scene is its region's scroll owner, so its top inset is padding inside
50
57
  the scroller. A scene whose only child is a Pane or layout (usually a
51
58
  NavStack) lets that child own the insets instead. */
@@ -191,4 +198,10 @@
191
198
  :is([data-workbench-main], [data-workbench-panel-content])
192
199
  > [data-component="tab-scaffold"]:only-child {
193
200
  height: 100%;
201
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
202
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
203
+ --kui-edge-inset-inline-start: var(
204
+ --_kui-workbench-content-edge-inline-start
205
+ );
206
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
194
207
  }
@@ -47,17 +47,23 @@
47
47
  text-overflow: ellipsis;
48
48
  }
49
49
 
50
- .kui-toolbar-text[data-size="xlarge"] {
51
- /* Matches page/panel titles: the same responsive clamp so a heading toolbar
52
- title reads at the page-title scale without a bespoke override. Height grows
53
- to the larger text (the fixed 40px would clip its ascenders). */
50
+ .kui-toolbar-text:is([data-size="xlarge"], [data-size="xlarge-fixed"]) {
51
+ /* Both title sizes keep page/panel title color and geometry. Height grows to
52
+ their text instead of clipping ascenders in the default 40px box. */
54
53
  height: auto;
55
54
  min-height: 2.75rem;
56
55
  color: var(--kui-color-text);
57
- font-size: clamp(var(--kui-font-l), 2.3vw, var(--kui-font-2xl));
58
56
  letter-spacing: -0.025em;
59
57
  }
60
58
 
59
+ .kui-toolbar-text[data-size="xlarge"] {
60
+ font-size: clamp(var(--kui-font-l), 2.3vw, var(--kui-font-2xl));
61
+ }
62
+
63
+ .kui-toolbar-text[data-size="xlarge-fixed"] {
64
+ font-size: var(--kui-font-l);
65
+ }
66
+
61
67
  .kui-toolbar-text[data-size="large"] {
62
68
  font-size: var(--kui-font-m);
63
69
  letter-spacing: -0.015em;
@@ -93,7 +99,10 @@
93
99
  min-height: 2.5rem;
94
100
  }
95
101
 
96
- .kui-toolbar-text[data-size="xlarge"][data-wrap="true"] {
102
+ .kui-toolbar-text:is(
103
+ [data-size="xlarge"],
104
+ [data-size="xlarge-fixed"]
105
+ )[data-wrap="true"] {
97
106
  min-height: 2.75rem;
98
107
  }
99
108
 
@@ -95,6 +95,13 @@
95
95
  grid-template-columns: minmax(0, 1fr) auto;
96
96
  }
97
97
 
98
+ /* Equal side tracks center the middle zone on the toolbar's content box even
99
+ when one side has no controls. Side content still shrinks or wraps within
100
+ its own track, and responsive policies below may move a zone to a new row. */
101
+ .kui-toolbar[data-center-align="balanced"][data-has-center="true"] {
102
+ grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
103
+ }
104
+
98
105
  .kui-toolbar[data-responsive="trailing-priority"][data-has-center="false"]:has(
99
106
  > .kui-toolbar__trailing [data-expanded="true"]
100
107
  ) {