@kerfjs/ui 5.0.0-beta.82 → 5.0.0-beta.84
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 +1 -0
- package/ai/catalog-authoring.json +1 -3
- package/ai/catalog-authoring.schema.json +3 -7
- package/ai/component-catalog.json +73 -2
- package/ai/component-composition.json +64 -1
- package/ai/components/README.md +1 -0
- package/ai/components/anchored-surface.md +86 -0
- package/ai/components/tab-navigator.md +3 -2
- package/ai/public-api-signatures-v1.md +79 -35
- package/ai/skill.md +2 -2
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/dist/anchored-surface.d.ts +30 -0
- package/dist/anchored-surface.js +3 -0
- package/dist/anchored-surface.js.map +1 -0
- package/dist/app-tab.js +1 -1
- package/dist/browser/anchored-surface.js +3 -0
- package/dist/browser/catalog.js +1 -1
- package/dist/catalog-resources.d.ts +2 -2
- package/dist/catalog.d.ts +4 -4
- package/dist/catalog.js +34 -31
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-I4SDIMFA.js → chunk-2YPPNFYT.js} +2 -2
- package/dist/{chunk-I4SDIMFA.js.map → chunk-2YPPNFYT.js.map} +1 -1
- package/dist/{chunk-VHXHLZ6R.js → chunk-3DXHNLME.js} +3 -3
- package/dist/{chunk-VHXHLZ6R.js.map → chunk-3DXHNLME.js.map} +1 -1
- package/dist/{chunk-HFQDSSED.js → chunk-3PO7JEK7.js} +4 -4
- package/dist/{chunk-HFQDSSED.js.map → chunk-3PO7JEK7.js.map} +1 -1
- package/dist/chunk-6IVNMC6R.js +19 -0
- package/dist/chunk-6IVNMC6R.js.map +1 -0
- package/dist/{chunk-VR7MWD2X.js → chunk-CD5TOO22.js} +4 -13
- package/dist/chunk-CD5TOO22.js.map +1 -0
- package/dist/{chunk-H7ZJEI3H.js → chunk-DL55BSQX.js} +3 -3
- package/dist/{chunk-H7ZJEI3H.js.map → chunk-DL55BSQX.js.map} +1 -1
- package/dist/{chunk-VIGVNDXZ.js → chunk-GPCAXYMT.js} +4 -4
- package/dist/{chunk-VIGVNDXZ.js.map → chunk-GPCAXYMT.js.map} +1 -1
- package/dist/chunk-IOS2NXW7.js +53 -0
- package/dist/chunk-IOS2NXW7.js.map +1 -0
- package/dist/{chunk-HFLGWMG3.js → chunk-KAJVVN7Q.js} +3 -3
- package/dist/{chunk-HFLGWMG3.js.map → chunk-KAJVVN7Q.js.map} +1 -1
- package/dist/{chunk-LQKY5S4F.js → chunk-KL3W6FUN.js} +4 -4
- package/dist/{chunk-LQKY5S4F.js.map → chunk-KL3W6FUN.js.map} +1 -1
- package/dist/{chunk-NVKRZ5DI.js → chunk-LFPW4YC6.js} +4 -4
- package/dist/{chunk-NVKRZ5DI.js.map → chunk-LFPW4YC6.js.map} +1 -1
- package/dist/{chunk-75I3SNUJ.js → chunk-MN3POJFN.js} +2 -2
- package/dist/{chunk-75I3SNUJ.js.map → chunk-MN3POJFN.js.map} +1 -1
- package/dist/{chunk-5D3WDMIK.js → chunk-MORVLMDG.js} +4 -16
- package/dist/chunk-MORVLMDG.js.map +1 -0
- package/dist/{chunk-RRCD3A6G.js → chunk-MTCTX25G.js} +2 -2
- package/dist/{chunk-RRCD3A6G.js.map → chunk-MTCTX25G.js.map} +1 -1
- package/dist/{chunk-PQQQXJGV.js → chunk-NP3FSLNX.js} +2 -2
- package/dist/{chunk-PQQQXJGV.js.map → chunk-NP3FSLNX.js.map} +1 -1
- package/dist/{chunk-ARZ4RSQO.js → chunk-PGL6TXFW.js} +3 -3
- package/dist/{chunk-ARZ4RSQO.js.map → chunk-PGL6TXFW.js.map} +1 -1
- package/dist/{chunk-NVRJ7C3W.js → chunk-QQICWWNX.js} +4 -16
- package/dist/chunk-QQICWWNX.js.map +1 -0
- package/dist/{chunk-CVKIADIS.js → chunk-SJW5BCEQ.js} +7 -5
- package/dist/chunk-SJW5BCEQ.js.map +1 -0
- package/dist/{chunk-JZM3G6RT.js → chunk-TTGIHMDR.js} +4 -4
- package/dist/{chunk-JZM3G6RT.js.map → chunk-TTGIHMDR.js.map} +1 -1
- package/dist/{chunk-LRAIS3YB.js → chunk-U657IHFB.js} +1 -1
- package/dist/chunk-U657IHFB.js.map +1 -0
- package/dist/{chunk-3SXWV2IR.js → chunk-VLGQIYZ5.js} +2 -2
- package/dist/{chunk-3SXWV2IR.js.map → chunk-VLGQIYZ5.js.map} +1 -1
- package/dist/{chunk-YLJ6X3AC.js → chunk-XK4E225T.js} +2 -2
- package/dist/{chunk-YLJ6X3AC.js.map → chunk-XK4E225T.js.map} +1 -1
- package/dist/{chunk-BJLXE56E.js → chunk-XKZPBRU7.js} +4 -4
- package/dist/{chunk-BJLXE56E.js.map → chunk-XKZPBRU7.js.map} +1 -1
- package/dist/{chunk-62VMNBV2.js → chunk-XNXKIPU5.js} +2 -2
- package/dist/{chunk-62VMNBV2.js.map → chunk-XNXKIPU5.js.map} +1 -1
- package/dist/{chunk-EFDCALR3.js → chunk-Y43B6DS3.js} +2 -2
- package/dist/{chunk-EFDCALR3.js.map → chunk-Y43B6DS3.js.map} +1 -1
- package/dist/{chunk-3RE2JMZU.js → chunk-YOKEL75M.js} +2 -2
- package/dist/{chunk-3RE2JMZU.js.map → chunk-YOKEL75M.js.map} +1 -1
- package/dist/collapsible-panel.js +4 -3
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/css-values.d.ts +8 -1
- package/dist/css-values.js +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/grid.d.ts +5 -4
- package/dist/grid.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +26 -24
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +5 -4
- package/dist/list.js +2 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/{nav-stack-B1Qc2e5q.d.ts → nav-stack-BvSKY448.d.ts} +10 -2
- package/dist/nav-stack.d.ts +1 -1
- package/dist/nav-stack.js +2 -1
- package/dist/row.d.ts +5 -4
- package/dist/row.js +2 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-view.d.ts +1 -1
- package/dist/split-view.js +2 -1
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/anchored-surface.css +15 -0
- package/dist/styles/catalog/components/catalog-example.css +1 -2
- package/dist/styles/catalog/components/catalog-stage.css +40 -42
- package/dist/styles/catalog/components/catalog.css +0 -11
- package/dist/styles/components/collections/list/list.css +4 -1
- package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +15 -0
- package/dist/styles/components/layout/grid/grid.css +4 -1
- package/dist/styles/components/layout/pane/pane.css +15 -0
- package/dist/styles/components/layout/row/row.css +4 -1
- package/dist/styles/components/layout/workbench/workbench.css +17 -0
- package/dist/styles/components/navigation/nav-stack/nav-stack.css +21 -5
- package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +25 -9
- package/dist/styles/grid.css +4 -1
- package/dist/styles/list.css +4 -1
- package/dist/styles/nav-stack.css +21 -5
- package/dist/styles/pane.css +15 -0
- package/dist/styles/row.css +4 -1
- package/dist/styles/styles.css +1 -0
- package/dist/styles/tab-navigator.css +25 -9
- package/dist/styles/workbench.css +17 -0
- package/dist/tab-navigator.d.ts +10 -3
- package/dist/tab-navigator.js +2 -0
- package/dist/tab-navigator.js.map +1 -1
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/{types-C9BubXfz.d.ts → types-Bn-dXLcs.d.ts} +6 -2
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +1 -9
- package/dist/wire-catalog.js +2 -200
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +1 -1
- package/dist/workbench.js +2 -1
- package/docs/anchored-surface.md +51 -0
- package/docs/catalog.md +38 -82
- package/docs/component-contract.md +3 -1
- package/docs/component-selection.md +19 -1
- package/docs/layout.md +19 -2
- package/docs/nav-stack.md +13 -4
- package/docs/tab-navigator.md +12 -4
- package/docs/type-contracts.md +2 -0
- package/docs/ux-demo.md +4 -4
- package/docs/workbench.md +2 -0
- package/llms.txt +8 -3
- package/package.json +7 -1
- package/dist/chunk-5D3WDMIK.js.map +0 -1
- package/dist/chunk-CVKIADIS.js.map +0 -1
- package/dist/chunk-LRAIS3YB.js.map +0 -1
- package/dist/chunk-NVRJ7C3W.js.map +0 -1
- package/dist/chunk-VR7MWD2X.js.map +0 -1
|
@@ -97,7 +97,6 @@
|
|
|
97
97
|
|
|
98
98
|
.kui-catalog-example__viewport[data-frame] {
|
|
99
99
|
border: 1px solid var(--kui-color-neutral-border-normal);
|
|
100
|
-
border-radius: var(--kui-radius-m);
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
.kui-catalog-example__viewport[data-frame="dashed"] {
|
|
@@ -150,7 +149,7 @@
|
|
|
150
149
|
}
|
|
151
150
|
}
|
|
152
151
|
|
|
153
|
-
/*
|
|
152
|
+
/* Bare specimens use a small inset to align with the surrounding examples. */
|
|
154
153
|
.kui-catalog-example[data-align="glyph"]
|
|
155
154
|
> :not([data-catalog-example-label]):not([data-catalog-example-note]) {
|
|
156
155
|
--kui-catalog-example-align: 1rem;
|
|
@@ -1,55 +1,53 @@
|
|
|
1
|
-
/* The preview stage fills the work area's scroller
|
|
2
|
-
specimen, never shrinking under it
|
|
3
|
-
|
|
1
|
+
/* The preview stage fills the work area's scroller and grows with a taller
|
|
2
|
+
specimen, never shrinking under it. The default checkerboard shares the
|
|
3
|
+
sunken Pane's translucent surface instead of painting a second layer. */
|
|
4
4
|
.kui-catalog__stage {
|
|
5
5
|
flex: 1 0 auto;
|
|
6
|
-
background-color:
|
|
7
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0
|
|
8
|
-
background-size:
|
|
6
|
+
background-color: transparent;
|
|
7
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%238e8e93' fill-opacity='.12' d='M0 0h8v8H0zM8 8h8v8H8z'/%3E%3C/svg%3E");
|
|
8
|
+
background-size: 1rem 1rem;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
.
|
|
13
|
-
|
|
14
|
-
display: grid;
|
|
15
|
-
width: min(100%, 70rem);
|
|
16
|
-
min-width: 0;
|
|
17
|
-
min-height: 100%;
|
|
18
|
-
margin-inline: auto;
|
|
19
|
-
padding: var(--kui-layout-content-gap);
|
|
20
|
-
box-sizing: border-box;
|
|
21
|
-
place-items: center;
|
|
11
|
+
.kui-catalog__stage[data-background-style="vertical-stripes"] {
|
|
12
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%238e8e93' fill-opacity='.12' d='M0 0h8v16H0z'/%3E%3C/svg%3E");
|
|
13
|
+
background-size: 1rem 1rem;
|
|
22
14
|
}
|
|
23
15
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
16
|
+
.kui-catalog__stage[data-background-style="layout-guide"] {
|
|
17
|
+
background-image: linear-gradient(
|
|
18
|
+
to right,
|
|
19
|
+
transparent 15px,
|
|
20
|
+
rgb(142 142 147 / 12%) 15px 16px,
|
|
21
|
+
transparent 16px 23px,
|
|
22
|
+
rgb(142 142 147 / 12%) 23px 24px,
|
|
23
|
+
transparent 24px 32px,
|
|
24
|
+
rgb(142 142 147 / 12%) 32px 33px,
|
|
25
|
+
transparent 33px
|
|
26
|
+
);
|
|
27
|
+
background-size: auto;
|
|
28
|
+
background-repeat: no-repeat;
|
|
33
29
|
}
|
|
34
30
|
|
|
35
|
-
.kui-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
top: 0;
|
|
40
|
-
left: 0;
|
|
41
|
-
box-sizing: border-box;
|
|
31
|
+
.kui-catalog__stage[data-background-style="surface"] {
|
|
32
|
+
background-color: var(--kui-color-surface);
|
|
33
|
+
background-image: none;
|
|
34
|
+
background-size: auto;
|
|
42
35
|
}
|
|
43
36
|
|
|
44
|
-
.kui-
|
|
45
|
-
|
|
37
|
+
.kui-catalog__stage[data-background-style="sunken"] {
|
|
38
|
+
background-color: transparent;
|
|
39
|
+
background-image: none;
|
|
40
|
+
background-size: auto;
|
|
46
41
|
}
|
|
47
42
|
|
|
48
|
-
.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
43
|
+
/* Align the specimen canvas with the work area's reading start. */
|
|
44
|
+
.kui-catalog__canvas {
|
|
45
|
+
position: relative;
|
|
46
|
+
display: grid;
|
|
47
|
+
width: min(100%, 70rem);
|
|
48
|
+
min-width: 0;
|
|
49
|
+
min-height: 100%;
|
|
50
|
+
padding: var(--kui-space-m);
|
|
51
|
+
box-sizing: border-box;
|
|
52
|
+
place-items: start;
|
|
55
53
|
}
|
|
@@ -4,17 +4,6 @@
|
|
|
4
4
|
height: 100%;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
/* The brand mark, sized to sit inside a toolbar group. */
|
|
8
|
-
.kui-catalog__mark {
|
|
9
|
-
display: block;
|
|
10
|
-
width: 2.125rem;
|
|
11
|
-
height: 2.125rem;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.kui-catalog__filter {
|
|
15
|
-
border-radius: var(--kui-layout-rounded-radius);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
7
|
.kui-catalog [data-catalog-filter-empty],
|
|
19
8
|
.kui-catalog [data-catalog-section][hidden],
|
|
20
9
|
.kui-catalog [data-catalog-entry-name][hidden],
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
omits `gap` or `flex` never inherits its ancestor's; the component's inline
|
|
6
6
|
style overrides these defaults for the props it does set. */
|
|
7
7
|
--_kui-list-gap: 0;
|
|
8
|
+
--_kui-list-column-gap: var(--_kui-list-gap);
|
|
9
|
+
--_kui-list-row-gap: var(--_kui-list-gap);
|
|
8
10
|
--_kui-list-flex: 0 1 auto;
|
|
9
11
|
--_kui-list-inset-top: 0;
|
|
10
12
|
--_kui-list-inset-right: 0;
|
|
@@ -26,7 +28,8 @@
|
|
|
26
28
|
align-items: stretch;
|
|
27
29
|
align-content: space-between;
|
|
28
30
|
justify-content: flex-start;
|
|
29
|
-
gap: var(--_kui-list-gap
|
|
31
|
+
column-gap: var(--_kui-list-column-gap);
|
|
32
|
+
row-gap: var(--_kui-list-row-gap);
|
|
30
33
|
box-shadow:
|
|
31
34
|
inset 0 1px var(--_kui-list-divider-top),
|
|
32
35
|
inset -1px 0 var(--_kui-list-divider-right),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
.kui-anchored-surface {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
inset: auto;
|
|
4
|
+
width: max-content;
|
|
5
|
+
max-width: calc(100vw - 2 * var(--kui-space-xs, 8px));
|
|
6
|
+
max-height: calc(100dvh - 2 * var(--kui-space-xs, 8px));
|
|
7
|
+
overflow: auto;
|
|
8
|
+
padding: var(--kui-anchored-surface-inset, var(--kui-space-xs, 8px));
|
|
9
|
+
border: 1px solid var(--kui-color-neutral-border-normal);
|
|
10
|
+
border-radius: var(--kui-anchored-surface-radius, var(--kui-radius-m));
|
|
11
|
+
color: var(--kui-color-text, inherit);
|
|
12
|
+
background: var(--kui-color-surface-raised);
|
|
13
|
+
box-shadow: var(--kui-shadow-l);
|
|
14
|
+
font: inherit;
|
|
15
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
/* Private per-instance values are reset on every Grid so a nested Grid never
|
|
4
4
|
inherits its ancestor's; the inline style overrides them per prop. */
|
|
5
5
|
--_kui-grid-gap: var(--kui-grid-gap);
|
|
6
|
+
--_kui-grid-column-gap: var(--_kui-grid-gap);
|
|
7
|
+
--_kui-grid-row-gap: var(--_kui-grid-gap);
|
|
6
8
|
--_kui-grid-flex: 0 1 auto;
|
|
7
9
|
--_kui-grid-inset-top: 0;
|
|
8
10
|
--_kui-grid-inset-right: 0;
|
|
@@ -17,7 +19,8 @@
|
|
|
17
19
|
var(--_kui-grid-inset-bottom, 0) var(--_kui-grid-inset-left, 0);
|
|
18
20
|
flex: var(--_kui-grid-flex, initial);
|
|
19
21
|
grid-template-columns: repeat(var(--_kui-grid-columns), minmax(0, 1fr));
|
|
20
|
-
gap: var(--_kui-grid-
|
|
22
|
+
column-gap: var(--_kui-grid-column-gap);
|
|
23
|
+
row-gap: var(--_kui-grid-row-gap);
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
.kui-grid[data-control-insets*="t"] {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
--kui-pane-separator-inline-start-width: 0;
|
|
5
5
|
--kui-pane-separator-inline-end-width: 0;
|
|
6
6
|
|
|
7
|
+
position: relative;
|
|
7
8
|
display: grid;
|
|
8
9
|
min-width: 0;
|
|
9
10
|
min-height: 0;
|
|
@@ -27,6 +28,18 @@
|
|
|
27
28
|
outline-offset: -3px;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/* A bleeding child can establish its own paint layer above the Pane outline.
|
|
32
|
+
Repeat the ring as an overlay after the content, without intercepting input. */
|
|
33
|
+
.kui-pane:is(:focus-visible, [data-outlined="true"])::after {
|
|
34
|
+
position: absolute;
|
|
35
|
+
z-index: 1;
|
|
36
|
+
outline: var(--kui-focus-ring);
|
|
37
|
+
outline-offset: -3px;
|
|
38
|
+
content: "";
|
|
39
|
+
inset: 0;
|
|
40
|
+
pointer-events: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
/* Paint the active scroll owner once, so alpha lowered colors do not stack.
|
|
31
44
|
Fixed chrome leaves the content slot scrolling; auto chrome lets the Pane
|
|
32
45
|
root scroll in its short mode, while its content remains transparent. */
|
|
@@ -180,6 +193,8 @@
|
|
|
180
193
|
/* Add one outer gutter without changing the inherited item-margin token.
|
|
181
194
|
Nested Row, List, and Grid therefore keep their own default 8px insets. */
|
|
182
195
|
.kui-pane[data-deep-inset="true"] > .kui-pane__content {
|
|
196
|
+
/* Reserve a vertical scrollbar gutter when the host uses opaque edge-to-edge content. */
|
|
197
|
+
scrollbar-gutter: var(--kui-pane-scrollbar-gutter, auto);
|
|
183
198
|
--_kui-pane-deep-block-inset: var(--kui-space-xs);
|
|
184
199
|
--kui-pane-content-inset-inline-start: calc(
|
|
185
200
|
var(--_kui-pane-safe-inline-start) + var(--kui-space-xs)
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
/* Private per-instance values are reset on every Row so a nested Row never
|
|
4
4
|
inherits its ancestor's; the inline style overrides them per prop. */
|
|
5
5
|
--_kui-row-gap: var(--kui-row-gap);
|
|
6
|
+
--_kui-row-column-gap: var(--_kui-row-gap);
|
|
7
|
+
--_kui-row-row-gap: var(--_kui-row-gap);
|
|
6
8
|
--_kui-row-flex: 0 1 auto;
|
|
7
9
|
--_kui-row-inset-top: 0;
|
|
8
10
|
--_kui-row-inset-right: 0;
|
|
@@ -21,7 +23,8 @@
|
|
|
21
23
|
align-items: stretch;
|
|
22
24
|
align-content: space-between;
|
|
23
25
|
justify-content: flex-start;
|
|
24
|
-
gap: var(--_kui-row-
|
|
26
|
+
column-gap: var(--_kui-row-column-gap);
|
|
27
|
+
row-gap: var(--_kui-row-row-gap);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
.kui-row[data-control-insets*="t"] {
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
.kui-workbench__main {
|
|
103
|
+
position: relative;
|
|
103
104
|
flex: 1;
|
|
104
105
|
min-height: 0;
|
|
105
106
|
overflow: auto;
|
|
@@ -113,6 +114,22 @@
|
|
|
113
114
|
outline-offset: -3px;
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
/* A sole Pane can host an opaque full-width scroller above the main outline.
|
|
118
|
+
Keep the selected work-area ring in the final paint layer, without blocking
|
|
119
|
+
controls in that Pane. Other main compositions retain their own outline. */
|
|
120
|
+
.kui-workbench__main:has(> [data-component="pane"]:only-child):is(
|
|
121
|
+
:focus-visible,
|
|
122
|
+
[data-outlined="true"]
|
|
123
|
+
)::after {
|
|
124
|
+
position: absolute;
|
|
125
|
+
z-index: 1;
|
|
126
|
+
outline: var(--kui-focus-ring);
|
|
127
|
+
outline-offset: -3px;
|
|
128
|
+
content: "";
|
|
129
|
+
inset: 0;
|
|
130
|
+
pointer-events: none;
|
|
131
|
+
}
|
|
132
|
+
|
|
116
133
|
/* When no Pane chrome is composed, the Workbench region owns its scroll.
|
|
117
134
|
A resizable auto-overflow panel instead scrolls its content box so its
|
|
118
135
|
separator handle remains fixed. Paint only that owner. */
|
|
@@ -197,10 +197,19 @@
|
|
|
197
197
|
neither, whatever it reports. The chrome's line is an overlaid 1px pseudo-element
|
|
198
198
|
(whatever the chrome holds never covers it) and the bottom's border is
|
|
199
199
|
always there, so showing either never moves the chrome, the toolbar, or
|
|
200
|
-
the content. A cross-fading chrome copy keeps the line its snapshot had.
|
|
201
|
-
|
|
200
|
+
the content. A cross-fading chrome copy keeps the line its snapshot had.
|
|
201
|
+
With `separator="auto"`, an active sunken Pane also colors both available
|
|
202
|
+
edges; `hidden` suppresses the stack-owned lines. */
|
|
203
|
+
.kui-nav-stack[data-separator="auto"]:has(
|
|
204
|
+
> .kui-nav-stack__viewport
|
|
205
|
+
> .kui-nav-stack__view[data-nav-active="true"]
|
|
206
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
207
|
+
)
|
|
208
|
+
> .kui-nav-stack__chrome::after,
|
|
209
|
+
.kui-nav-stack[data-separator="auto"]:not([data-chrome-dividers])
|
|
202
210
|
> .kui-nav-stack__chrome[data-scroll-divider*="b"]::after,
|
|
203
|
-
.kui-nav-stack[data-chrome-dividers="always"]
|
|
211
|
+
.kui-nav-stack[data-separator="auto"][data-chrome-dividers="always"]
|
|
212
|
+
> .kui-nav-stack__chrome::after {
|
|
204
213
|
position: absolute;
|
|
205
214
|
block-size: 1px;
|
|
206
215
|
background: var(--kui-color-neutral-border-normal);
|
|
@@ -210,9 +219,16 @@
|
|
|
210
219
|
pointer-events: none;
|
|
211
220
|
}
|
|
212
221
|
|
|
213
|
-
.kui-nav-stack
|
|
222
|
+
.kui-nav-stack[data-separator="auto"]:has(
|
|
223
|
+
> .kui-nav-stack__viewport
|
|
224
|
+
> .kui-nav-stack__view[data-nav-active="true"]
|
|
225
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
226
|
+
)
|
|
227
|
+
> .kui-nav-stack__bottom,
|
|
228
|
+
.kui-nav-stack[data-separator="auto"]:not([data-chrome-dividers])
|
|
214
229
|
> .kui-nav-stack__bottom[data-scroll-divider*="t"],
|
|
215
|
-
.kui-nav-stack[data-chrome-dividers="always"]
|
|
230
|
+
.kui-nav-stack[data-separator="auto"][data-chrome-dividers="always"]
|
|
231
|
+
> .kui-nav-stack__bottom {
|
|
216
232
|
--_kui-nav-stack-bottom-divider: var(--kui-color-neutral-border-normal);
|
|
217
233
|
}
|
|
218
234
|
|
|
@@ -133,21 +133,37 @@
|
|
|
133
133
|
);
|
|
134
134
|
padding-inline: var(--_kui-tab-scaffold-safe-inline-start)
|
|
135
135
|
var(--_kui-tab-scaffold-safe-inline-end);
|
|
136
|
-
/*
|
|
137
|
-
|
|
138
|
-
content continues below it — never at the scroll end or when the content
|
|
139
|
-
fits. `wireScrollDividers` reports that state through
|
|
140
|
-
`data-scroll-divider`; `always` shows it without the wiring, and `none`
|
|
141
|
-
never. The border is always there and only its color changes, so
|
|
142
|
-
showing it never moves the bar or a tab. */
|
|
136
|
+
/* The reserved 1px edge serves both the sunken-surface separator and the
|
|
137
|
+
scroll divider. Changing its color never moves the bar or a tab. */
|
|
143
138
|
border-block-start: 1px solid
|
|
144
139
|
var(--_kui-tab-scaffold-bar-divider, transparent);
|
|
145
140
|
background: var(--kui-color-surface);
|
|
146
141
|
}
|
|
147
142
|
|
|
148
|
-
.kui-tab-scaffold
|
|
143
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
144
|
+
> .kui-tab-scaffold__scenes
|
|
145
|
+
> .kui-tab-scaffold__scene[data-active="true"][data-appearance="sunken"]
|
|
146
|
+
)
|
|
147
|
+
> .kui-tab-scaffold__bar,
|
|
148
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
149
|
+
> .kui-tab-scaffold__scenes
|
|
150
|
+
> .kui-tab-scaffold__scene[data-active="true"]
|
|
151
|
+
> [data-component="pane"][data-appearance="sunken"]:only-child
|
|
152
|
+
)
|
|
153
|
+
> .kui-tab-scaffold__bar,
|
|
154
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
155
|
+
> .kui-tab-scaffold__scenes
|
|
156
|
+
> .kui-tab-scaffold__scene[data-active="true"]
|
|
157
|
+
> [data-component="nav-stack"]:only-child
|
|
158
|
+
> [data-nav-stack-viewport]
|
|
159
|
+
> [data-nav-active="true"]
|
|
160
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
161
|
+
)
|
|
162
|
+
> .kui-tab-scaffold__bar,
|
|
163
|
+
.kui-tab-scaffold[data-separator="auto"]:not([data-chrome-dividers])
|
|
149
164
|
> .kui-tab-scaffold__bar[data-scroll-divider*="t"],
|
|
150
|
-
.kui-tab-scaffold[data-chrome-dividers="always"]
|
|
165
|
+
.kui-tab-scaffold[data-separator="auto"][data-chrome-dividers="always"]
|
|
166
|
+
> .kui-tab-scaffold__bar {
|
|
151
167
|
--_kui-tab-scaffold-bar-divider: var(--kui-color-neutral-border-normal);
|
|
152
168
|
}
|
|
153
169
|
|
package/dist/styles/grid.css
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
/* Private per-instance values are reset on every Grid so a nested Grid never
|
|
4
4
|
inherits its ancestor's; the inline style overrides them per prop. */
|
|
5
5
|
--_kui-grid-gap: var(--kui-grid-gap);
|
|
6
|
+
--_kui-grid-column-gap: var(--_kui-grid-gap);
|
|
7
|
+
--_kui-grid-row-gap: var(--_kui-grid-gap);
|
|
6
8
|
--_kui-grid-flex: 0 1 auto;
|
|
7
9
|
--_kui-grid-inset-top: 0;
|
|
8
10
|
--_kui-grid-inset-right: 0;
|
|
@@ -17,7 +19,8 @@
|
|
|
17
19
|
var(--_kui-grid-inset-bottom, 0) var(--_kui-grid-inset-left, 0);
|
|
18
20
|
flex: var(--_kui-grid-flex, initial);
|
|
19
21
|
grid-template-columns: repeat(var(--_kui-grid-columns), minmax(0, 1fr));
|
|
20
|
-
gap: var(--_kui-grid-
|
|
22
|
+
column-gap: var(--_kui-grid-column-gap);
|
|
23
|
+
row-gap: var(--_kui-grid-row-gap);
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
.kui-grid[data-control-insets*="t"] {
|
package/dist/styles/list.css
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
omits `gap` or `flex` never inherits its ancestor's; the component's inline
|
|
6
6
|
style overrides these defaults for the props it does set. */
|
|
7
7
|
--_kui-list-gap: 0;
|
|
8
|
+
--_kui-list-column-gap: var(--_kui-list-gap);
|
|
9
|
+
--_kui-list-row-gap: var(--_kui-list-gap);
|
|
8
10
|
--_kui-list-flex: 0 1 auto;
|
|
9
11
|
--_kui-list-inset-top: 0;
|
|
10
12
|
--_kui-list-inset-right: 0;
|
|
@@ -26,7 +28,8 @@
|
|
|
26
28
|
align-items: stretch;
|
|
27
29
|
align-content: space-between;
|
|
28
30
|
justify-content: flex-start;
|
|
29
|
-
gap: var(--_kui-list-gap
|
|
31
|
+
column-gap: var(--_kui-list-column-gap);
|
|
32
|
+
row-gap: var(--_kui-list-row-gap);
|
|
30
33
|
box-shadow:
|
|
31
34
|
inset 0 1px var(--_kui-list-divider-top),
|
|
32
35
|
inset -1px 0 var(--_kui-list-divider-right),
|
|
@@ -197,10 +197,19 @@
|
|
|
197
197
|
neither, whatever it reports. The chrome's line is an overlaid 1px pseudo-element
|
|
198
198
|
(whatever the chrome holds never covers it) and the bottom's border is
|
|
199
199
|
always there, so showing either never moves the chrome, the toolbar, or
|
|
200
|
-
the content. A cross-fading chrome copy keeps the line its snapshot had.
|
|
201
|
-
|
|
200
|
+
the content. A cross-fading chrome copy keeps the line its snapshot had.
|
|
201
|
+
With `separator="auto"`, an active sunken Pane also colors both available
|
|
202
|
+
edges; `hidden` suppresses the stack-owned lines. */
|
|
203
|
+
.kui-nav-stack[data-separator="auto"]:has(
|
|
204
|
+
> .kui-nav-stack__viewport
|
|
205
|
+
> .kui-nav-stack__view[data-nav-active="true"]
|
|
206
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
207
|
+
)
|
|
208
|
+
> .kui-nav-stack__chrome::after,
|
|
209
|
+
.kui-nav-stack[data-separator="auto"]:not([data-chrome-dividers])
|
|
202
210
|
> .kui-nav-stack__chrome[data-scroll-divider*="b"]::after,
|
|
203
|
-
.kui-nav-stack[data-chrome-dividers="always"]
|
|
211
|
+
.kui-nav-stack[data-separator="auto"][data-chrome-dividers="always"]
|
|
212
|
+
> .kui-nav-stack__chrome::after {
|
|
204
213
|
position: absolute;
|
|
205
214
|
block-size: 1px;
|
|
206
215
|
background: var(--kui-color-neutral-border-normal);
|
|
@@ -210,9 +219,16 @@
|
|
|
210
219
|
pointer-events: none;
|
|
211
220
|
}
|
|
212
221
|
|
|
213
|
-
.kui-nav-stack
|
|
222
|
+
.kui-nav-stack[data-separator="auto"]:has(
|
|
223
|
+
> .kui-nav-stack__viewport
|
|
224
|
+
> .kui-nav-stack__view[data-nav-active="true"]
|
|
225
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
226
|
+
)
|
|
227
|
+
> .kui-nav-stack__bottom,
|
|
228
|
+
.kui-nav-stack[data-separator="auto"]:not([data-chrome-dividers])
|
|
214
229
|
> .kui-nav-stack__bottom[data-scroll-divider*="t"],
|
|
215
|
-
.kui-nav-stack[data-chrome-dividers="always"]
|
|
230
|
+
.kui-nav-stack[data-separator="auto"][data-chrome-dividers="always"]
|
|
231
|
+
> .kui-nav-stack__bottom {
|
|
216
232
|
--_kui-nav-stack-bottom-divider: var(--kui-color-neutral-border-normal);
|
|
217
233
|
}
|
|
218
234
|
|
package/dist/styles/pane.css
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
--kui-pane-separator-inline-start-width: 0;
|
|
5
5
|
--kui-pane-separator-inline-end-width: 0;
|
|
6
6
|
|
|
7
|
+
position: relative;
|
|
7
8
|
display: grid;
|
|
8
9
|
min-width: 0;
|
|
9
10
|
min-height: 0;
|
|
@@ -27,6 +28,18 @@
|
|
|
27
28
|
outline-offset: -3px;
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/* A bleeding child can establish its own paint layer above the Pane outline.
|
|
32
|
+
Repeat the ring as an overlay after the content, without intercepting input. */
|
|
33
|
+
.kui-pane:is(:focus-visible, [data-outlined="true"])::after {
|
|
34
|
+
position: absolute;
|
|
35
|
+
z-index: 1;
|
|
36
|
+
outline: var(--kui-focus-ring);
|
|
37
|
+
outline-offset: -3px;
|
|
38
|
+
content: "";
|
|
39
|
+
inset: 0;
|
|
40
|
+
pointer-events: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
/* Paint the active scroll owner once, so alpha lowered colors do not stack.
|
|
31
44
|
Fixed chrome leaves the content slot scrolling; auto chrome lets the Pane
|
|
32
45
|
root scroll in its short mode, while its content remains transparent. */
|
|
@@ -180,6 +193,8 @@
|
|
|
180
193
|
/* Add one outer gutter without changing the inherited item-margin token.
|
|
181
194
|
Nested Row, List, and Grid therefore keep their own default 8px insets. */
|
|
182
195
|
.kui-pane[data-deep-inset="true"] > .kui-pane__content {
|
|
196
|
+
/* Reserve a vertical scrollbar gutter when the host uses opaque edge-to-edge content. */
|
|
197
|
+
scrollbar-gutter: var(--kui-pane-scrollbar-gutter, auto);
|
|
183
198
|
--_kui-pane-deep-block-inset: var(--kui-space-xs);
|
|
184
199
|
--kui-pane-content-inset-inline-start: calc(
|
|
185
200
|
var(--_kui-pane-safe-inline-start) + var(--kui-space-xs)
|
package/dist/styles/row.css
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
/* Private per-instance values are reset on every Row so a nested Row never
|
|
4
4
|
inherits its ancestor's; the inline style overrides them per prop. */
|
|
5
5
|
--_kui-row-gap: var(--kui-row-gap);
|
|
6
|
+
--_kui-row-column-gap: var(--_kui-row-gap);
|
|
7
|
+
--_kui-row-row-gap: var(--_kui-row-gap);
|
|
6
8
|
--_kui-row-flex: 0 1 auto;
|
|
7
9
|
--_kui-row-inset-top: 0;
|
|
8
10
|
--_kui-row-inset-right: 0;
|
|
@@ -21,7 +23,8 @@
|
|
|
21
23
|
align-items: stretch;
|
|
22
24
|
align-content: space-between;
|
|
23
25
|
justify-content: flex-start;
|
|
24
|
-
gap: var(--_kui-row-
|
|
26
|
+
column-gap: var(--_kui-row-column-gap);
|
|
27
|
+
row-gap: var(--_kui-row-row-gap);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
.kui-row[data-control-insets*="t"] {
|
package/dist/styles/styles.css
CHANGED
|
@@ -133,21 +133,37 @@
|
|
|
133
133
|
);
|
|
134
134
|
padding-inline: var(--_kui-tab-scaffold-safe-inline-start)
|
|
135
135
|
var(--_kui-tab-scaffold-safe-inline-end);
|
|
136
|
-
/*
|
|
137
|
-
|
|
138
|
-
content continues below it — never at the scroll end or when the content
|
|
139
|
-
fits. `wireScrollDividers` reports that state through
|
|
140
|
-
`data-scroll-divider`; `always` shows it without the wiring, and `none`
|
|
141
|
-
never. The border is always there and only its color changes, so
|
|
142
|
-
showing it never moves the bar or a tab. */
|
|
136
|
+
/* The reserved 1px edge serves both the sunken-surface separator and the
|
|
137
|
+
scroll divider. Changing its color never moves the bar or a tab. */
|
|
143
138
|
border-block-start: 1px solid
|
|
144
139
|
var(--_kui-tab-scaffold-bar-divider, transparent);
|
|
145
140
|
background: var(--kui-color-surface);
|
|
146
141
|
}
|
|
147
142
|
|
|
148
|
-
.kui-tab-scaffold
|
|
143
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
144
|
+
> .kui-tab-scaffold__scenes
|
|
145
|
+
> .kui-tab-scaffold__scene[data-active="true"][data-appearance="sunken"]
|
|
146
|
+
)
|
|
147
|
+
> .kui-tab-scaffold__bar,
|
|
148
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
149
|
+
> .kui-tab-scaffold__scenes
|
|
150
|
+
> .kui-tab-scaffold__scene[data-active="true"]
|
|
151
|
+
> [data-component="pane"][data-appearance="sunken"]:only-child
|
|
152
|
+
)
|
|
153
|
+
> .kui-tab-scaffold__bar,
|
|
154
|
+
.kui-tab-scaffold[data-separator="auto"]:has(
|
|
155
|
+
> .kui-tab-scaffold__scenes
|
|
156
|
+
> .kui-tab-scaffold__scene[data-active="true"]
|
|
157
|
+
> [data-component="nav-stack"]:only-child
|
|
158
|
+
> [data-nav-stack-viewport]
|
|
159
|
+
> [data-nav-active="true"]
|
|
160
|
+
> [data-component="pane"][data-appearance="sunken"]
|
|
161
|
+
)
|
|
162
|
+
> .kui-tab-scaffold__bar,
|
|
163
|
+
.kui-tab-scaffold[data-separator="auto"]:not([data-chrome-dividers])
|
|
149
164
|
> .kui-tab-scaffold__bar[data-scroll-divider*="t"],
|
|
150
|
-
.kui-tab-scaffold[data-chrome-dividers="always"]
|
|
165
|
+
.kui-tab-scaffold[data-separator="auto"][data-chrome-dividers="always"]
|
|
166
|
+
> .kui-tab-scaffold__bar {
|
|
151
167
|
--_kui-tab-scaffold-bar-divider: var(--kui-color-neutral-border-normal);
|
|
152
168
|
}
|
|
153
169
|
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
.kui-workbench__main {
|
|
103
|
+
position: relative;
|
|
103
104
|
flex: 1;
|
|
104
105
|
min-height: 0;
|
|
105
106
|
overflow: auto;
|
|
@@ -113,6 +114,22 @@
|
|
|
113
114
|
outline-offset: -3px;
|
|
114
115
|
}
|
|
115
116
|
|
|
117
|
+
/* A sole Pane can host an opaque full-width scroller above the main outline.
|
|
118
|
+
Keep the selected work-area ring in the final paint layer, without blocking
|
|
119
|
+
controls in that Pane. Other main compositions retain their own outline. */
|
|
120
|
+
.kui-workbench__main:has(> [data-component="pane"]:only-child):is(
|
|
121
|
+
:focus-visible,
|
|
122
|
+
[data-outlined="true"]
|
|
123
|
+
)::after {
|
|
124
|
+
position: absolute;
|
|
125
|
+
z-index: 1;
|
|
126
|
+
outline: var(--kui-focus-ring);
|
|
127
|
+
outline-offset: -3px;
|
|
128
|
+
content: "";
|
|
129
|
+
inset: 0;
|
|
130
|
+
pointer-events: none;
|
|
131
|
+
}
|
|
132
|
+
|
|
116
133
|
/* When no Pane chrome is composed, the Workbench region owns its scroll.
|
|
117
134
|
A resizable auto-overflow panel instead scrolls its content box so its
|
|
118
135
|
separator handle remains fixed. Paint only that owner. */
|
package/dist/tab-navigator.d.ts
CHANGED
|
@@ -59,14 +59,21 @@ interface TabNavigatorProps<Id extends string = string> {
|
|
|
59
59
|
tabs: readonly TabNavigatorTab<Id>[];
|
|
60
60
|
/** The controlled active tab id (the app owns selection). */
|
|
61
61
|
active: NoInfer<Id>;
|
|
62
|
+
/**
|
|
63
|
+
* The bar's top separator. `auto` (default) draws it against a sunken active
|
|
64
|
+
* work surface and otherwise follows `chromeDividers`; `hidden` suppresses
|
|
65
|
+
* the line, including a scroll divider.
|
|
66
|
+
*/
|
|
67
|
+
separator?: 'auto' | 'hidden';
|
|
62
68
|
/**
|
|
63
69
|
* The line over the tab bar, where it meets the active scene. `scroll`
|
|
64
70
|
* (default) shows it only while more of the scene's content lies below —
|
|
65
71
|
* never at the scroll end or when the content fits — once
|
|
66
72
|
* `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
|
|
67
73
|
* the scaffold; unwired, it does not show. `always` shows it without the
|
|
68
|
-
* wiring; `none`
|
|
69
|
-
*
|
|
74
|
+
* wiring; `none` suppresses that scroll divider. A sunken active work
|
|
75
|
+
* surface still draws the separator unless `separator="hidden"`. The line
|
|
76
|
+
* is the bar's own 1px top border, so no state moves the bar or a tab.
|
|
70
77
|
*/
|
|
71
78
|
chromeDividers?: 'scroll' | 'always' | 'none';
|
|
72
79
|
className?: string;
|
|
@@ -81,6 +88,6 @@ interface TabNavigatorProps<Id extends string = string> {
|
|
|
81
88
|
* On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
|
|
82
89
|
* a bottom bar. See `docs/23-app-layouts.md` §3.4.
|
|
83
90
|
*/
|
|
84
|
-
declare function TabNavigator<Id extends string>({ id, label, tabs, active, chromeDividers, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
|
|
91
|
+
declare function TabNavigator<Id extends string>({ id, label, tabs, active, separator, chromeDividers, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
|
|
85
92
|
|
|
86
93
|
export { TabNavigator, type TabNavigatorProps, type TabNavigatorTab };
|
package/dist/tab-navigator.js
CHANGED
|
@@ -6,6 +6,7 @@ function TabNavigator({
|
|
|
6
6
|
label,
|
|
7
7
|
tabs,
|
|
8
8
|
active,
|
|
9
|
+
separator = "auto",
|
|
9
10
|
chromeDividers = "scroll",
|
|
10
11
|
className = "",
|
|
11
12
|
slot
|
|
@@ -17,6 +18,7 @@ function TabNavigator({
|
|
|
17
18
|
id,
|
|
18
19
|
"data-component": "tab-scaffold",
|
|
19
20
|
"data-tab-scaffold-id": id,
|
|
21
|
+
"data-separator": separator,
|
|
20
22
|
"data-chrome-dividers": chromeDividers === "always" || chromeDividers === "none" ? chromeDividers : void 0,
|
|
21
23
|
slot,
|
|
22
24
|
children: [
|