@kerfjs/ui 5.0.0-beta.81 → 5.0.0-beta.83
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 +74 -30
- 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 +4 -2
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +3 -3
- package/dist/catalog.js +51 -42
- 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-CVKIADIS.js → chunk-3BXDWEGB.js} +5 -5
- package/dist/{chunk-CVKIADIS.js.map → chunk-3BXDWEGB.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-LQKY5S4F.js → chunk-EA5R75B5.js} +4 -4
- package/dist/{chunk-LQKY5S4F.js.map → chunk-EA5R75B5.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-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-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 +27 -25
- 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.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.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 -1
- package/dist/styles/catalog/components/catalog-stage.css +26 -42
- package/dist/styles/catalog/components/catalog.css +0 -24
- 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/row/row.css +4 -1
- 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/row.css +4 -1
- package/dist/styles/styles.css +1 -0
- package/dist/styles/tab-navigator.css +25 -9
- package/dist/styles/webawesome.css +4 -1
- 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-CXrh9Wyx.d.ts} +6 -2
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +1 -9
- package/dist/wire-catalog.js +37 -205
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.js +2 -1
- package/docs/anchored-surface.md +51 -0
- package/docs/catalog.md +41 -85
- package/docs/component-contract.md +3 -1
- package/docs/component-selection.md +19 -1
- package/docs/layout.md +13 -2
- package/docs/tab-navigator.md +12 -4
- package/docs/type-contracts.md +2 -0
- package/docs/ux-demo.md +4 -4
- package/docs/webawesome-theme.md +4 -1
- package/llms.txt +8 -3
- package/package.json +7 -1
- package/dist/chunk-5D3WDMIK.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
|
@@ -1,55 +1,39 @@
|
|
|
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
|
+
padding: var(--kui-space-xs);
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
.kui-catalog__stage[data-background-style="vertical-stripes"] {
|
|
13
|
+
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");
|
|
14
|
+
background-size: 1rem 1rem;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.kui-catalog__stage[data-background-style="surface"] {
|
|
18
|
+
background-color: var(--kui-color-surface);
|
|
19
|
+
background-image: none;
|
|
20
|
+
background-size: auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.kui-catalog__stage[data-background-style="sunken"] {
|
|
24
|
+
background-color: transparent;
|
|
25
|
+
background-image: none;
|
|
26
|
+
background-size: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Align the specimen canvas with the work area's reading start. */
|
|
12
30
|
.kui-catalog__canvas {
|
|
13
31
|
position: relative;
|
|
14
32
|
display: grid;
|
|
15
33
|
width: min(100%, 70rem);
|
|
16
34
|
min-width: 0;
|
|
17
35
|
min-height: 100%;
|
|
18
|
-
margin-inline: auto;
|
|
19
36
|
padding: var(--kui-layout-content-gap);
|
|
20
37
|
box-sizing: border-box;
|
|
21
|
-
place-items:
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* `wireCatalogGeometryOverlay` appends the bound, border, and margin layers. */
|
|
25
|
-
/* css-ownership: allow-root kui-catalog__geometry-bound -- The catalog wire appends measured specimen bound layers at runtime. */
|
|
26
|
-
/* css-ownership: allow-root kui-catalog__geometry-border -- The catalog wire appends computed border layers at runtime. */
|
|
27
|
-
/* css-ownership: allow-root kui-catalog__geometry-margin -- The catalog wire appends computed margin layers at runtime. */
|
|
28
|
-
.kui-catalog__geometry-overlay {
|
|
29
|
-
position: absolute;
|
|
30
|
-
z-index: 3;
|
|
31
|
-
pointer-events: none;
|
|
32
|
-
inset: 0;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.kui-catalog__geometry-bound,
|
|
36
|
-
.kui-catalog__geometry-border,
|
|
37
|
-
.kui-catalog__geometry-margin {
|
|
38
|
-
position: absolute;
|
|
39
|
-
top: 0;
|
|
40
|
-
left: 0;
|
|
41
|
-
box-sizing: border-box;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.kui-catalog__geometry-bound {
|
|
45
|
-
border: 1px dashed color-mix(in srgb, var(--kui-color-text) 40%, transparent);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.kui-catalog__geometry-border {
|
|
49
|
-
border: 0 solid
|
|
50
|
-
color-mix(in srgb, var(--kui-color-brand-on-quiet) 72%, transparent);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.kui-catalog__geometry-margin {
|
|
54
|
-
background: color-mix(in srgb, #f6a94c 55%, transparent);
|
|
38
|
+
place-items: start;
|
|
55
39
|
}
|
|
@@ -4,30 +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
|
-
width: 100%;
|
|
16
|
-
min-width: 0;
|
|
17
|
-
box-sizing: border-box;
|
|
18
|
-
padding: 0.5rem 0.625rem;
|
|
19
|
-
border: 1px solid var(--kui-color-neutral-border-normal);
|
|
20
|
-
border-radius: var(--kui-layout-rounded-radius);
|
|
21
|
-
color: var(--kui-color-text);
|
|
22
|
-
background: var(--kui-color-surface);
|
|
23
|
-
font: inherit;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.kui-catalog__filter:focus-visible {
|
|
27
|
-
outline: 2px solid var(--kui-color-focus);
|
|
28
|
-
outline-offset: 2px;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
7
|
.kui-catalog [data-catalog-filter-empty],
|
|
32
8
|
.kui-catalog [data-catalog-section][hidden],
|
|
33
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"] {
|
|
@@ -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"] {
|
|
@@ -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),
|
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
|
|
|
@@ -202,7 +202,10 @@
|
|
|
202
202
|
/* Geometry stays aligned with the compact Kerf primitives. */
|
|
203
203
|
--wa-border-radius-pill: 999px;
|
|
204
204
|
--wa-form-control-border-color: var(--wa-color-neutral-border-normal);
|
|
205
|
-
--wa-form-control-border-radius: var(
|
|
205
|
+
--wa-form-control-border-radius: var(
|
|
206
|
+
--kui-layout-rounded-radius,
|
|
207
|
+
calc(1px + 0.6875rem)
|
|
208
|
+
);
|
|
206
209
|
--wa-form-control-activated-color: var(--wa-color-brand-fill-loud);
|
|
207
210
|
/* Field inset: a 1px border with 8px inside it, the same content-item
|
|
208
211
|
geometry the Kerf primitives use (docs/layout.md). WA's defaults are a
|
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: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/navigation/tab-navigator/tab-navigator.tsx"],"names":[],"mappings":"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","file":"tab-navigator.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { Badge } from '../../feedback/badge/badge.js';\nimport type { PaneAppearance } from '../../layout/pane/pane.js';\n\ninterface TabNavigatorTabBase<Id extends string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: KerfUiContent;\n /** Background of this scene's scrolling work surface. */\n appearance?: PaneAppearance;\n /** Add 8px to every side of a plain scene's scrolling content. */\n deepInset?: boolean;\n /** Opt into keyboard (`0`) or programmatic (`-1`) focus on this scene. */\n tabIndex?: 0 | -1;\n /** Keep the standard focus outline visible while this scene is active. */\n outlined?: boolean;\n}\n\n/** A tab with an optional count or short-status badge. */\ninterface TabNavigatorTabCountBadge {\n /**\n * Optional count or short status shown as a solid danger `Badge` at the\n * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,\n * or non-finite numbers render no badge. The visual badge is `aria-hidden`;\n * its meaning reaches assistive technology through `badgeLabel`.\n *\n * Pass `true` instead for the text-free dot (new content without a count).\n */\n badge?: string | number;\n /**\n * Localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"3 unread\"` → `\"Inbox, 3 unread\"`).\n * Defaults to the badge text itself. Ignored when no badge renders.\n */\n badgeLabel?: string;\n}\n\n/** A tab with the text-free dot badge (new content without a count). */\ninterface TabNavigatorTabDotBadge {\n /**\n * `true` shows a solid danger dot `Badge` at the top-trailing corner of the\n * tab icon — the iOS tab-bar dot for new content without a count.\n */\n badge: true;\n /**\n * Required localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"New activity\"` →\n * `\"Feed, New activity\"`). A dot has no text, so this is its only meaning.\n */\n badgeLabel: string;\n}\n\n/** One bottom-bar destination: its label, optional icon and badge, and content. */\nexport type TabNavigatorTab<Id extends string = string> =\n TabNavigatorTabBase<Id> &\n (TabNavigatorTabCountBadge | TabNavigatorTabDotBadge);\n\nexport interface TabNavigatorProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabNavigatorTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n /**\n * The line over the tab bar, where it meets the active scene. `scroll`\n * (default) shows it only while more of the scene's content lies below —\n * never at the scroll end or when the content fits — once\n * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above\n * the scaffold; unwired, it does not show. `always` shows it without the\n * wiring; `none` never, even when wired. The line is the bar's own 1px top\n * border, so no state moves the bar or a tab.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab navigator: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-navigator`'s `wireTabNavigator`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabNavigator<Id extends string>({\n id,\n label,\n tabs,\n active,\n chromeDividers = 'scroll',\n className = '',\n slot,\n}: TabNavigatorProps<Id>) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n slot={slot}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n data-appearance={tab.appearance === 'sunken' ? 'sunken' : undefined}\n data-deep-inset={tab.deepInset ? 'true' : undefined}\n data-outlined={\n tab.id === active && tab.outlined ? 'true' : undefined\n }\n role={tab.tabIndex === undefined ? undefined : 'tabpanel'}\n aria-label={tab.tabIndex === undefined ? undefined : tab.label}\n aria-hidden={String(tab.id !== active)}\n tabindex={\n tab.id === active\n ? tab.tabIndex\n : tab.tabIndex === undefined\n ? undefined\n : -1\n }\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => {\n const dot = tab.badge === true;\n const badgeText = dot ? undefined : normalizeBadge(tab.badge);\n const hasBadge = dot || badgeText !== undefined;\n const badge = hasBadge && (\n <span\n class=\"kui-tab-scaffold__tab-badge\"\n data-badge-kind={dot ? 'dot' : 'text'}\n >\n {badgeText === undefined ? (\n <Badge tone=\"danger\" size=\"dot\" ariaHidden />\n ) : (\n <Badge\n tone=\"danger\"\n appearance=\"solid\"\n size=\"compact\"\n ariaHidden\n >\n {badgeText}\n </Badge>\n )}\n </span>\n );\n // A dot has no text fallback: without a usable badgeLabel (reachable\n // only from untyped callers) the tab keeps its plain accessible name.\n const badgeLabel = hasBadge\n ? tab.badgeLabel?.trim() || badgeText\n : undefined;\n return (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n aria-label={\n badgeLabel === undefined\n ? undefined\n : `${tab.label}, ${badgeLabel}`\n }\n data-has-badge={hasBadge ? 'true' : undefined}\n >\n {tab.icon ? (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n {badge}\n </span>\n ) : (\n badge\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </section>\n );\n}\n\nfunction normalizeBadge(\n badge: string | number | undefined,\n): string | undefined {\n if (typeof badge === 'number')\n return Number.isFinite(badge) ? String(badge) : undefined;\n if (typeof badge === 'string' && badge.trim()) return badge.trim();\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/navigation/tab-navigator/tab-navigator.tsx"],"names":[],"mappings":"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","file":"tab-navigator.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { Badge } from '../../feedback/badge/badge.js';\nimport type { PaneAppearance } from '../../layout/pane/pane.js';\n\ninterface TabNavigatorTabBase<Id extends string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: KerfUiContent;\n /** Background of this scene's scrolling work surface. */\n appearance?: PaneAppearance;\n /** Add 8px to every side of a plain scene's scrolling content. */\n deepInset?: boolean;\n /** Opt into keyboard (`0`) or programmatic (`-1`) focus on this scene. */\n tabIndex?: 0 | -1;\n /** Keep the standard focus outline visible while this scene is active. */\n outlined?: boolean;\n}\n\n/** A tab with an optional count or short-status badge. */\ninterface TabNavigatorTabCountBadge {\n /**\n * Optional count or short status shown as a solid danger `Badge` at the\n * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,\n * or non-finite numbers render no badge. The visual badge is `aria-hidden`;\n * its meaning reaches assistive technology through `badgeLabel`.\n *\n * Pass `true` instead for the text-free dot (new content without a count).\n */\n badge?: string | number;\n /**\n * Localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"3 unread\"` → `\"Inbox, 3 unread\"`).\n * Defaults to the badge text itself. Ignored when no badge renders.\n */\n badgeLabel?: string;\n}\n\n/** A tab with the text-free dot badge (new content without a count). */\ninterface TabNavigatorTabDotBadge {\n /**\n * `true` shows a solid danger dot `Badge` at the top-trailing corner of the\n * tab icon — the iOS tab-bar dot for new content without a count.\n */\n badge: true;\n /**\n * Required localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"New activity\"` →\n * `\"Feed, New activity\"`). A dot has no text, so this is its only meaning.\n */\n badgeLabel: string;\n}\n\n/** One bottom-bar destination: its label, optional icon and badge, and content. */\nexport type TabNavigatorTab<Id extends string = string> =\n TabNavigatorTabBase<Id> &\n (TabNavigatorTabCountBadge | TabNavigatorTabDotBadge);\n\nexport interface TabNavigatorProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabNavigatorTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n /**\n * The bar's top separator. `auto` (default) draws it against a sunken active\n * work surface and otherwise follows `chromeDividers`; `hidden` suppresses\n * the line, including a scroll divider.\n */\n separator?: 'auto' | 'hidden';\n /**\n * The line over the tab bar, where it meets the active scene. `scroll`\n * (default) shows it only while more of the scene's content lies below —\n * never at the scroll end or when the content fits — once\n * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above\n * the scaffold; unwired, it does not show. `always` shows it without the\n * wiring; `none` suppresses that scroll divider. A sunken active work\n * surface still draws the separator unless `separator=\"hidden\"`. The line\n * is the bar's own 1px top border, so no state moves the bar or a tab.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab navigator: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-navigator`'s `wireTabNavigator`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabNavigator<Id extends string>({\n id,\n label,\n tabs,\n active,\n separator = 'auto',\n chromeDividers = 'scroll',\n className = '',\n slot,\n}: TabNavigatorProps<Id>) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n data-separator={separator}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n slot={slot}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n data-appearance={tab.appearance === 'sunken' ? 'sunken' : undefined}\n data-deep-inset={tab.deepInset ? 'true' : undefined}\n data-outlined={\n tab.id === active && tab.outlined ? 'true' : undefined\n }\n role={tab.tabIndex === undefined ? undefined : 'tabpanel'}\n aria-label={tab.tabIndex === undefined ? undefined : tab.label}\n aria-hidden={String(tab.id !== active)}\n tabindex={\n tab.id === active\n ? tab.tabIndex\n : tab.tabIndex === undefined\n ? undefined\n : -1\n }\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => {\n const dot = tab.badge === true;\n const badgeText = dot ? undefined : normalizeBadge(tab.badge);\n const hasBadge = dot || badgeText !== undefined;\n const badge = hasBadge && (\n <span\n class=\"kui-tab-scaffold__tab-badge\"\n data-badge-kind={dot ? 'dot' : 'text'}\n >\n {badgeText === undefined ? (\n <Badge tone=\"danger\" size=\"dot\" ariaHidden />\n ) : (\n <Badge\n tone=\"danger\"\n appearance=\"solid\"\n size=\"compact\"\n ariaHidden\n >\n {badgeText}\n </Badge>\n )}\n </span>\n );\n // A dot has no text fallback: without a usable badgeLabel (reachable\n // only from untyped callers) the tab keeps its plain accessible name.\n const badgeLabel = hasBadge\n ? tab.badgeLabel?.trim() || badgeText\n : undefined;\n return (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n aria-label={\n badgeLabel === undefined\n ? undefined\n : `${tab.label}, ${badgeLabel}`\n }\n data-has-badge={hasBadge ? 'true' : undefined}\n >\n {tab.icon ? (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n {badge}\n </span>\n ) : (\n badge\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </section>\n );\n}\n\nfunction normalizeBadge(\n badge: string | number | undefined,\n): string | undefined {\n if (typeof badge === 'number')\n return Number.isFinite(badge) ? String(badge) : undefined;\n if (typeof badge === 'string' && badge.trim()) return badge.trim();\n return undefined;\n}\n"]}
|
package/dist/toolbar-text.js
CHANGED
|
@@ -44,7 +44,10 @@ interface CatalogBrand {
|
|
|
44
44
|
}
|
|
45
45
|
type CatalogStageRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
46
46
|
'data-catalog-stage'?: never;
|
|
47
|
+
'data-background-style'?: never;
|
|
47
48
|
}>;
|
|
49
|
+
/** Background used behind catalog specimens. */
|
|
50
|
+
type CatalogBackgroundStyle = 'checkerboard' | 'vertical-stripes' | 'surface' | 'sunken';
|
|
48
51
|
/**
|
|
49
52
|
* The Catalog sidebar's configuration, forwarded to its Workbench left rail.
|
|
50
53
|
* Everything is optional; omitted fields keep the Catalog's defaults.
|
|
@@ -75,7 +78,8 @@ interface CatalogProps {
|
|
|
75
78
|
secondarySections?: CatalogSecondaryGroup;
|
|
76
79
|
sidebarFooter?: KerfUiContent;
|
|
77
80
|
status?: KerfUiContent;
|
|
78
|
-
|
|
81
|
+
/** Preview background (default `checkerboard`). */
|
|
82
|
+
backgroundStyle?: CatalogBackgroundStyle;
|
|
79
83
|
/** Consumer-owned data attributes applied to the preview stage. */
|
|
80
84
|
stageRootAttributes?: CatalogStageRootAttributes;
|
|
81
85
|
selectAction?: string;
|
|
@@ -114,4 +118,4 @@ interface CatalogProps {
|
|
|
114
118
|
slot?: string;
|
|
115
119
|
}
|
|
116
120
|
|
|
117
|
-
export type { CatalogResource as C, CatalogProps as a,
|
|
121
|
+
export type { CatalogResource as C, CatalogProps as a, CatalogBackgroundStyle as b, CatalogBrand as c, CatalogEntry as d, CatalogRelated as e, CatalogSecondaryGroup as f, CatalogSection as g, CatalogStageRootAttributes as h };
|
package/dist/value-table.js
CHANGED
package/dist/wire-catalog.d.ts
CHANGED
|
@@ -60,14 +60,6 @@ interface CatalogRevealOptions {
|
|
|
60
60
|
* moving focus. Returns a cancellation function for rapid selection changes.
|
|
61
61
|
*/
|
|
62
62
|
declare function revealCatalogEntry(root: HTMLElement, id: string, { block, inline, behavior, media, }?: CatalogRevealOptions): () => void;
|
|
63
|
-
/**
|
|
64
|
-
* Keep a Catalog's opt-in geometry overlay synchronized with its preview.
|
|
65
|
-
* Specimens receive computed border highlights (or a dashed bound when they
|
|
66
|
-
* have no border and are transparent), while positive computed margins use
|
|
67
|
-
* devtools-style orange bands. CSS/stylesheet-only changes are observed too.
|
|
68
|
-
* Returns a disposer.
|
|
69
|
-
*/
|
|
70
|
-
declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
|
|
71
63
|
/**
|
|
72
64
|
* Wire a {@link Catalog}'s interactions with one delegated listener set: sidebar
|
|
73
65
|
* item selection (and the related-entry popup menu), the sidebar collapse toggle, and
|
|
@@ -79,4 +71,4 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
|
|
|
79
71
|
*/
|
|
80
72
|
declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
|
|
81
73
|
|
|
82
|
-
export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog
|
|
74
|
+
export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog };
|