@kerfjs/ui 5.0.0-beta.24 → 5.0.0-beta.26
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 +44 -23
- package/ai/application-ui-diagnostic-ids-v1.json +3 -0
- package/ai/application-ui-profile.defaults.json +1 -1
- package/ai/compile-time-contracts-v1.json +3 -11
- package/ai/component-catalog-v2-overrides.json +7 -37
- package/ai/component-catalog-v2.d.ts +1 -0
- package/ai/component-catalog-v2.json +415 -91
- package/ai/component-catalog-v2.schema.json +2 -1
- package/ai/component-catalog.json +602 -158
- package/ai/public-api-signatures-v1.md +132 -65
- package/ai/skill.md +20 -20
- package/ai/webawesome-jsx-signatures-v1.md +2 -1
- package/analyzer/cli.mjs +5 -2
- package/analyzer/index.d.mts +1 -0
- package/analyzer/index.mjs +117 -10
- package/dist/app-tab.d.ts +10 -2
- package/dist/app-tab.js +1 -1
- package/dist/browser/list-action-row.js +1 -0
- package/dist/browser/list-item.js +1 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/catalog.js +5 -4
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-FEAMR7S4.js → chunk-4EF2CMYS.js} +24 -5
- package/dist/chunk-4EF2CMYS.js.map +1 -0
- package/dist/{chunk-NWSEP5RT.js → chunk-FRVS5RFM.js} +23 -5
- package/dist/chunk-FRVS5RFM.js.map +1 -0
- package/dist/{chunk-PSKN344N.js → chunk-GWEAPEZI.js} +15 -2
- package/dist/chunk-GWEAPEZI.js.map +1 -0
- package/dist/chunk-HP2B2L26.js +102 -0
- package/dist/chunk-HP2B2L26.js.map +1 -0
- package/dist/{chunk-OJWWHFH3.js → chunk-JFGXQBIP.js} +49 -23
- package/dist/chunk-JFGXQBIP.js.map +1 -0
- package/dist/chunk-OBLTAKSX.js +43 -0
- package/dist/chunk-OBLTAKSX.js.map +1 -0
- package/dist/{chunk-Y45PPBDV.js → chunk-OT6RPYAP.js} +16 -2
- package/dist/chunk-OT6RPYAP.js.map +1 -0
- package/dist/{chunk-UFZKLBCF.js → chunk-VCE4MPVE.js} +25 -3
- package/dist/chunk-VCE4MPVE.js.map +1 -0
- package/dist/{chunk-5VTB2BKP.js → chunk-WNWD54GR.js} +16 -2
- package/dist/chunk-WNWD54GR.js.map +1 -0
- package/dist/{chunk-M7JBER5U.js → chunk-X2U3QJCJ.js} +8 -2
- package/dist/chunk-X2U3QJCJ.js.map +1 -0
- package/dist/{chunk-DPDBVKNA.js → chunk-YMKH5XTF.js} +5 -3
- package/dist/chunk-YMKH5XTF.js.map +1 -0
- package/dist/collapsible-panel.d.ts +9 -1
- package/dist/collapsible-panel.js +36 -15
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +12 -12
- package/dist/list-action-row.d.ts +11 -1
- package/dist/list-action-row.js +2 -1
- package/dist/list-header.d.ts +15 -2
- package/dist/list-header.js +1 -1
- package/dist/list-item.d.ts +12 -1
- package/dist/list-item.js +2 -1
- package/dist/resizable-region.d.ts +19 -2
- package/dist/resizable-region.js +1 -1
- package/dist/select.d.ts +12 -1
- package/dist/select.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/styles/app-tab.css +26 -0
- package/dist/styles/collapsible-panel.css +66 -4
- package/dist/styles/list-action-row.css +64 -0
- package/dist/styles/list-header.css +32 -0
- package/dist/styles/list-item.css +39 -0
- package/dist/styles/resizable-region.css +132 -0
- package/dist/styles/select.css +68 -0
- package/dist/styles/styles.css +1 -1
- package/dist/styles/surface-scaffold.css +51 -0
- package/dist/styles/tab-bar.css +24 -0
- package/dist/styles/toolbar-control-group.css +73 -1
- package/dist/styles/toolbar-text.css +1 -1
- package/dist/styles/webawesome.css +12 -0
- package/dist/styles/workbench.css +89 -0
- package/dist/surface-scaffold.d.ts +25 -0
- package/dist/surface-scaffold.js +3 -0
- package/dist/surface-scaffold.js.map +1 -0
- package/dist/tab-bar.d.ts +11 -2
- package/dist/tab-bar.js +1 -1
- package/dist/toolbar-control-group.d.ts +16 -2
- package/dist/toolbar-control-group.js +1 -1
- package/dist/webawesome.d.ts +1 -0
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +6 -1
- package/dist/wire-sidebar.js +27 -8
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +8 -0
- package/dist/workbench.js +42 -0
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +55 -12
- package/docs/collapsible-panel.md +7 -0
- package/docs/component-contract.md +5 -8
- package/docs/component-selection.md +63 -33
- package/docs/design/templates.md +5 -7
- package/docs/examples/component-catalog-extension-v2.json +3 -6
- package/docs/examples/component-catalog-extension.json +1 -1
- package/docs/layout.md +7 -9
- package/docs/recipes.md +8 -7
- package/docs/surface-scaffold.md +17 -0
- package/docs/type-contracts.md +6 -8
- package/docs/ui-analyzer.md +19 -1
- package/docs/ui-doctor.md +1 -1
- package/docs/ux-demo.md +6 -3
- package/docs/webawesome-theme.md +4 -1
- package/docs/workbench.md +49 -2
- package/doctor/eslint-diagnostics.d.mts +16 -0
- package/doctor/eslint-diagnostics.mjs +17 -0
- package/doctor/index.mjs +16 -1
- package/llms.txt +19 -9
- package/package.json +7 -7
- package/ux-demo/recipes/app-shell.tsx +36 -23
- package/ux-demo/recipes/collapsible-sidebar.tsx +22 -16
- package/ux-demo/recipes/composer-form.tsx +15 -6
- package/ux-demo/recipes/list-detail-dialog.tsx +31 -15
- package/ux-demo/recipes/list-workspace-states.tsx +16 -7
- package/ux-demo/recipes/loading-inspector.tsx +39 -18
- package/ux-demo/recipes/recipes.css +7 -2
- package/ux-demo/recipes/workspace-header.tsx +17 -7
- package/dist/browser/panel-header.js +0 -7
- package/dist/chunk-5VTB2BKP.js.map +0 -1
- package/dist/chunk-7XRDUG4Y.js +0 -58
- package/dist/chunk-7XRDUG4Y.js.map +0 -1
- package/dist/chunk-DPDBVKNA.js.map +0 -1
- package/dist/chunk-FEAMR7S4.js.map +0 -1
- package/dist/chunk-M7JBER5U.js.map +0 -1
- package/dist/chunk-NENBUYX5.js +0 -79
- package/dist/chunk-NENBUYX5.js.map +0 -1
- package/dist/chunk-NWSEP5RT.js.map +0 -1
- package/dist/chunk-OJWWHFH3.js.map +0 -1
- package/dist/chunk-PSKN344N.js.map +0 -1
- package/dist/chunk-UFZKLBCF.js.map +0 -1
- package/dist/chunk-Y45PPBDV.js.map +0 -1
- package/dist/panel-header.d.ts +0 -42
- package/dist/panel-header.js +0 -7
- package/dist/panel-header.js.map +0 -1
- package/dist/styles/panel-header.css +0 -64
- package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-actions.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
- package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
- package/docs/design/templates/panel-header/no-icon.svg +0 -1
- package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
- package/docs/design/templates/panel-header/page-heading.svg +0 -1
- package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
- package/docs/design/templates/panel-header/title-only.svg +0 -1
- package/docs/design/templates/panel-header-dark.svg +0 -1
- package/docs/design/templates/panel-header.svg +0 -1
package/dist/workbench.js
CHANGED
|
@@ -24,11 +24,25 @@ function Workbench({
|
|
|
24
24
|
class: "kui-workbench__rail kui-workbench__rail--left",
|
|
25
25
|
"data-workbench-rail": "left",
|
|
26
26
|
"data-collapsed": String(leftRail.collapsed ?? false),
|
|
27
|
+
"data-separator": leftRail.separator ?? "auto",
|
|
28
|
+
"data-collapse-motion": leftRail.collapseMotion ?? "slide",
|
|
29
|
+
"data-content-overflow": leftRail.contentOverflow ?? "clip",
|
|
30
|
+
"data-presentation": leftRail.presentation ?? "inline",
|
|
27
31
|
"aria-label": leftRail.label || void 0,
|
|
32
|
+
"aria-hidden": leftRail.presentation === "hidden" ? "true" : void 0,
|
|
28
33
|
style: leftRail.size ? `--kui-workbench-rail-width: ${leftRail.size}px` : void 0,
|
|
29
34
|
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: leftRail.content })
|
|
30
35
|
}
|
|
31
36
|
),
|
|
37
|
+
leftRail?.collapsed && leftRail.restoreControl && leftRail.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
class: "kui-workbench__restore",
|
|
41
|
+
"data-panel": "left",
|
|
42
|
+
"data-position": leftRail.restorePosition ?? "bottom-start",
|
|
43
|
+
children: leftRail.restoreControl
|
|
44
|
+
}
|
|
45
|
+
),
|
|
32
46
|
/* @__PURE__ */ jsxs("div", { class: "kui-workbench__center", children: [
|
|
33
47
|
/* @__PURE__ */ jsx("div", { class: "kui-workbench__main", "data-workbench-main": true, children: main }),
|
|
34
48
|
bottomDrawer && /* @__PURE__ */ jsx(
|
|
@@ -37,10 +51,24 @@ function Workbench({
|
|
|
37
51
|
class: "kui-workbench__drawer",
|
|
38
52
|
"data-workbench-drawer": true,
|
|
39
53
|
"data-collapsed": String(bottomDrawer.collapsed ?? false),
|
|
54
|
+
"data-separator": bottomDrawer.separator ?? "auto",
|
|
55
|
+
"data-collapse-motion": bottomDrawer.collapseMotion ?? "slide",
|
|
56
|
+
"data-content-overflow": bottomDrawer.contentOverflow ?? "clip",
|
|
57
|
+
"data-presentation": bottomDrawer.presentation ?? "inline",
|
|
40
58
|
"aria-label": bottomDrawer.label || void 0,
|
|
59
|
+
"aria-hidden": bottomDrawer.presentation === "hidden" ? "true" : void 0,
|
|
41
60
|
style: bottomDrawer.size ? `--kui-workbench-drawer-height: ${bottomDrawer.size}px` : void 0,
|
|
42
61
|
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: bottomDrawer.content })
|
|
43
62
|
}
|
|
63
|
+
),
|
|
64
|
+
bottomDrawer?.collapsed && bottomDrawer.restoreControl && bottomDrawer.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
class: "kui-workbench__restore",
|
|
68
|
+
"data-panel": "bottom",
|
|
69
|
+
"data-position": bottomDrawer.restorePosition ?? "bottom-end",
|
|
70
|
+
children: bottomDrawer.restoreControl
|
|
71
|
+
}
|
|
44
72
|
)
|
|
45
73
|
] }),
|
|
46
74
|
rightRail && /* @__PURE__ */ jsx(
|
|
@@ -49,10 +77,24 @@ function Workbench({
|
|
|
49
77
|
class: "kui-workbench__rail kui-workbench__rail--right",
|
|
50
78
|
"data-workbench-rail": "right",
|
|
51
79
|
"data-collapsed": String(rightRail.collapsed ?? false),
|
|
80
|
+
"data-separator": rightRail.separator ?? "auto",
|
|
81
|
+
"data-collapse-motion": rightRail.collapseMotion ?? "slide",
|
|
82
|
+
"data-content-overflow": rightRail.contentOverflow ?? "clip",
|
|
83
|
+
"data-presentation": rightRail.presentation ?? "inline",
|
|
52
84
|
"aria-label": rightRail.label || void 0,
|
|
85
|
+
"aria-hidden": rightRail.presentation === "hidden" ? "true" : void 0,
|
|
53
86
|
style: rightRail.size ? `--kui-workbench-rail-width: ${rightRail.size}px` : void 0,
|
|
54
87
|
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: rightRail.content })
|
|
55
88
|
}
|
|
89
|
+
),
|
|
90
|
+
rightRail?.collapsed && rightRail.restoreControl && rightRail.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
91
|
+
"div",
|
|
92
|
+
{
|
|
93
|
+
class: "kui-workbench__restore",
|
|
94
|
+
"data-panel": "right",
|
|
95
|
+
"data-position": rightRail.restorePosition ?? "bottom-end",
|
|
96
|
+
children: rightRail.restoreControl
|
|
97
|
+
}
|
|
56
98
|
)
|
|
57
99
|
]
|
|
58
100
|
}
|
package/dist/workbench.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/workbench.tsx"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"sources":["../src/workbench.tsx"],"names":[],"mappings":"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","file":"workbench.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type {\n ResizableRegionCollapseMotion,\n ResizableRegionContentOverflow,\n ResizableRegionPresentation,\n ResizableRegionRestorePosition,\n ResizableRegionSeparator,\n} from './resizable-region.js';\n\n/** A collapsible Workbench panel — a side rail or the bottom drawer. */\nexport interface WorkbenchPanel {\n content: SafeHtml;\n /** Whether the panel is currently collapsed (the app owns this). */\n collapsed?: boolean;\n /** Rail width, or drawer height, in px. Overrides the CSS default. */\n size?: number;\n /** Accessible name for the panel region. */\n label?: string;\n separator?: ResizableRegionSeparator;\n collapseMotion?: ResizableRegionCollapseMotion;\n contentOverflow?: ResizableRegionContentOverflow;\n presentation?: ResizableRegionPresentation;\n /** Control shown in a safe-area-aware viewport corner while collapsed. */\n restoreControl?: SafeHtml;\n restorePosition?: ResizableRegionRestorePosition;\n}\n\nexport interface WorkbenchProps {\n id: string;\n label: string;\n /** The central work area. */\n main: SafeHtml;\n leftRail?: WorkbenchPanel;\n rightRail?: WorkbenchPanel;\n bottomDrawer?: WorkbenchPanel;\n className?: string;\n}\n\n/**\n * The Xcode-like multi-panel workspace: a collapsible left rail, right rail, and\n * bottom drawer around a central work area (any absent). Collapsing snaps the\n * panel's track to zero in one reflow while its fixed-size content slides out via\n * a composited transform — the instant-width / sliding-content technique, so the\n * work area relayouts once, not per frame. The app owns each `collapsed` flag;\n * the collapse is pure CSS (no wire). See `docs/23-app-layouts.md` §3.3.\n */\nexport function Workbench({\n id,\n label,\n main,\n leftRail,\n rightRail,\n bottomDrawer,\n className = '',\n}: WorkbenchProps) {\n return (\n <section\n class={`kui-workbench ${className}`.trim()}\n id={id}\n data-component=\"workbench\"\n aria-label={label}\n >\n {leftRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--left\"\n data-workbench-rail=\"left\"\n data-collapsed={String(leftRail.collapsed ?? false)}\n data-separator={leftRail.separator ?? 'auto'}\n data-collapse-motion={leftRail.collapseMotion ?? 'slide'}\n data-content-overflow={leftRail.contentOverflow ?? 'clip'}\n data-presentation={leftRail.presentation ?? 'inline'}\n aria-label={leftRail.label || undefined}\n aria-hidden={leftRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n leftRail.size\n ? `--kui-workbench-rail-width: ${leftRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{leftRail.content}</div>\n </aside>\n )}\n {leftRail?.collapsed &&\n leftRail.restoreControl &&\n leftRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"left\"\n data-position={leftRail.restorePosition ?? 'bottom-start'}\n >\n {leftRail.restoreControl}\n </div>\n )}\n <div class=\"kui-workbench__center\">\n <div class=\"kui-workbench__main\" data-workbench-main>\n {main}\n </div>\n {bottomDrawer && (\n <section\n class=\"kui-workbench__drawer\"\n data-workbench-drawer\n data-collapsed={String(bottomDrawer.collapsed ?? false)}\n data-separator={bottomDrawer.separator ?? 'auto'}\n data-collapse-motion={bottomDrawer.collapseMotion ?? 'slide'}\n data-content-overflow={bottomDrawer.contentOverflow ?? 'clip'}\n data-presentation={bottomDrawer.presentation ?? 'inline'}\n aria-label={bottomDrawer.label || undefined}\n aria-hidden={\n bottomDrawer.presentation === 'hidden' ? 'true' : undefined\n }\n style={\n bottomDrawer.size\n ? `--kui-workbench-drawer-height: ${bottomDrawer.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">\n {bottomDrawer.content}\n </div>\n </section>\n )}\n {bottomDrawer?.collapsed &&\n bottomDrawer.restoreControl &&\n bottomDrawer.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"bottom\"\n data-position={bottomDrawer.restorePosition ?? 'bottom-end'}\n >\n {bottomDrawer.restoreControl}\n </div>\n )}\n </div>\n {rightRail && (\n <aside\n class=\"kui-workbench__rail kui-workbench__rail--right\"\n data-workbench-rail=\"right\"\n data-collapsed={String(rightRail.collapsed ?? false)}\n data-separator={rightRail.separator ?? 'auto'}\n data-collapse-motion={rightRail.collapseMotion ?? 'slide'}\n data-content-overflow={rightRail.contentOverflow ?? 'clip'}\n data-presentation={rightRail.presentation ?? 'inline'}\n aria-label={rightRail.label || undefined}\n aria-hidden={rightRail.presentation === 'hidden' ? 'true' : undefined}\n style={\n rightRail.size\n ? `--kui-workbench-rail-width: ${rightRail.size}px`\n : undefined\n }\n >\n <div class=\"kui-workbench__panel-content\">{rightRail.content}</div>\n </aside>\n )}\n {rightRail?.collapsed &&\n rightRail.restoreControl &&\n rightRail.presentation !== 'hidden' && (\n <div\n class=\"kui-workbench__restore\"\n data-panel=\"right\"\n data-position={rightRail.restorePosition ?? 'bottom-end'}\n >\n {rightRail.restoreControl}\n </div>\n )}\n </section>\n );\n}\n"]}
|
package/docs/accessibility.md
CHANGED
|
@@ -17,6 +17,37 @@ These are normative contracts for package components and consuming applications.
|
|
|
17
17
|
- `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may override `--kui-disclosure-arrow-size` without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
|
|
18
18
|
- `List` is layout-only and adds no `list` role. Children own their native or ARIA semantics. Give a scrollable List a bounded block size, avoid nested scroll owners, and keep focused children visible while scrolling.
|
|
19
19
|
|
|
20
|
+
## Select
|
|
21
|
+
|
|
22
|
+
Supply a visible `label`, or `ariaLabel` when the surrounding interface already
|
|
23
|
+
provides visual context. A nonempty `label` takes precedence when both are
|
|
24
|
+
supplied. Kerf forwards that name through Web Awesome's internal label contract;
|
|
25
|
+
an `aria-label` on the custom-element host alone cannot name its shadow
|
|
26
|
+
combobox. With `ariaLabel` alone, Kerf visually hides the internal label without
|
|
27
|
+
adding height or spacing. This also applies to `renderSelected`: selected content
|
|
28
|
+
stays separate from the control's stable accessible name. Applications do not
|
|
29
|
+
need shadow-DOM patches or extra label styling.
|
|
30
|
+
|
|
31
|
+
Use `presentation="toolbar-borderless"` with `size="compact"` inside a
|
|
32
|
+
`ToolbarControlGroup`; set `focusRingOwner="group"` when that parent paints the
|
|
33
|
+
composed focus ring. `selectedPresentation="icon-only"` hides only the visible
|
|
34
|
+
selected label—the required `label` or `ariaLabel` still names the combobox.
|
|
35
|
+
Navigation selects can use intrinsic `presentation="navigation"` plus
|
|
36
|
+
`labelMaxWidth` for component-owned ellipsis. These props own the control's
|
|
37
|
+
appearance; its parent continues to own outer placement.
|
|
38
|
+
|
|
39
|
+
Use `hint` for persistent supporting text below the control; use
|
|
40
|
+
`placeholderText` only for the empty value shown inside the closed control.
|
|
41
|
+
Kerf passes hint text through Web Awesome's form-control contract, which renders
|
|
42
|
+
the hint part and connects the shadow combobox to it with `aria-describedby`.
|
|
43
|
+
Loading placeholders keep the same visible hint while replacing the interactive
|
|
44
|
+
control with inert chrome.
|
|
45
|
+
|
|
46
|
+
`tests/unit/components.test.tsx` covers name projection and visible/hidden label
|
|
47
|
+
variants. `tests/browser/select-accessibility.spec.ts` verifies actual accessible
|
|
48
|
+
names, unchanged unlabeled geometry, keyboard selection, controlled rerenders,
|
|
49
|
+
native hint wiring, and wide/narrow presentation in Chromium, Firefox, and WebKit.
|
|
50
|
+
|
|
20
51
|
## ListActionRow
|
|
21
52
|
|
|
22
53
|
`ListActionRow` renders a noninteractive visual root containing primary and
|
|
@@ -45,21 +76,21 @@ The handle exposes separator role, orientation, name, minimum, maximum, and curr
|
|
|
45
76
|
|
|
46
77
|
The application owns persistence and collapsed/expanded policy. Keep the last expanded size outside the component and restore it when reopening. An optional `handleIcon` replaces only decorative dormant content; it must not contain controls or interactive roles because the separator remains the sole focus and interaction owner.
|
|
47
78
|
|
|
48
|
-
##
|
|
79
|
+
## Toolbar headings
|
|
49
80
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
`ToolbarText
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
81
|
+
Compose panel, dialog, and page headings as a plain `Toolbar`. Its leading zone
|
|
82
|
+
holds an optional icon `ToolbarControlGroup` and a direct extra-large
|
|
83
|
+
`ToolbarText`; controls belong in a trailing `ToolbarControlGroup`. By default
|
|
84
|
+
the title carries no native heading role, so for a **dialog or panel** the
|
|
85
|
+
application connects the title id and optional supporting-copy id to the owning
|
|
86
|
+
host through `aria-labelledby` and `aria-describedby`. For a **page or view**
|
|
87
|
+
title, pass `headingLevel` (usually `1`) to `ToolbarText`: it then exposes
|
|
57
88
|
`role="heading"` with a matching `aria-level`, giving the view a heading landmark
|
|
58
89
|
so screen-reader heading navigation and "main heading" semantics work — the same
|
|
59
|
-
role/level pair
|
|
60
|
-
|
|
90
|
+
role/level pair used throughout Kerf UI. Keep the levels meaningful and
|
|
91
|
+
non-skipping within a view. Pass trailing
|
|
61
92
|
controls as a labeled `ToolbarControlGroup` when that group needs an accessible
|
|
62
|
-
name.
|
|
93
|
+
name. Keep supporting copy as app-owned content below the toolbar.
|
|
63
94
|
|
|
64
95
|
## FloatingToolbar
|
|
65
96
|
|
|
@@ -75,6 +106,13 @@ and — via `position` and `--kui-floating-toolbar-inset` — where it sits.
|
|
|
75
106
|
|
|
76
107
|
`AppTab` renders one controlled tab. `TabBar` supplies the containing tab list,
|
|
77
108
|
fixed leading/trailing regions, and a horizontally scrollable strip.
|
|
109
|
+
Use `TabBar.presentation` for rail, segmented, or inspector chrome,
|
|
110
|
+
`allocation="fill"` when peers should divide the strip, and
|
|
111
|
+
`trailingPlacement="adjacent"` when an action belongs beside the final tab.
|
|
112
|
+
`AppTab` provides compact 32px, segmented, truncating-label, and icon-only
|
|
113
|
+
presentations. Icon-only tabs keep the required `name` as the tab button's
|
|
114
|
+
accessible name while visually hiding the duplicate label. These props own
|
|
115
|
+
component appearance only; the application still owns the bar's outer placement.
|
|
78
116
|
`AppTab.rootAttributes` accepts application `data-*` metadata only; runtime
|
|
79
117
|
filtering rejects roles plus case variants of component- or wiring-owned
|
|
80
118
|
action, identity, selection, drag, drop, and component attributes. An optional
|
|
@@ -126,7 +164,12 @@ and `placeTokenSearchCaret()` to restore a text caret without landing inside a
|
|
|
126
164
|
chip. Call `wireTokenSearchFields()` once at a stable root so Enter submits
|
|
127
165
|
without inserting a contenteditable line break and keyboard chip deletion
|
|
128
166
|
restores focus plus the text-relative caret after controlled rendering replaces
|
|
129
|
-
the editor
|
|
167
|
+
the editor. Restoration finishes after synchronous input listeners and before
|
|
168
|
+
another keystroke; it does not wait for an animation frame that could overwrite
|
|
169
|
+
a later selection. Select All + Backspace/Delete shares that replacement path
|
|
170
|
+
and keeps the adopted expanded signal open while managed focus is enabled.
|
|
171
|
+
Real outside focus, empty Escape, disposal, and removed fields retain their usual
|
|
172
|
+
behavior. The editor still wraps text visually at its inline edge. Editable text is DOM-owned between token changes; a clear handler empties
|
|
130
173
|
the editor's `textContent` before updating application state. Leading and
|
|
131
174
|
trailing controls share the first text line's fixed vertical center and remain
|
|
132
175
|
there as the editor wraps. In `collapsible` mode, the closed state is one named
|
|
@@ -20,6 +20,9 @@ Import the panel CSS (`@kerfjs/ui/collapsible-panel.css`) alongside `foundation.
|
|
|
20
20
|
the fixed-size content slides out via `transform` (composited, clipped) — never
|
|
21
21
|
a per-frame width/height animation. The app owns the `collapsed` signal; `size`
|
|
22
22
|
overrides the CSS default width/height.
|
|
23
|
+
Reusable shell policies are typed props: `separator`, `collapseMotion`,
|
|
24
|
+
`contentOverflow`, and `presentation`. A collapsed panel may also receive a
|
|
25
|
+
`restoreControl`, which Kerf places at the safe-area-aware `restorePosition`.
|
|
23
26
|
- **`CollapsiblePanelToggle({ side, collapsed, action, panelId?, label? })`** and
|
|
24
27
|
**`collapsiblePanelToggleIcon(side, collapsed)`** — the standard toggle
|
|
25
28
|
affordance and its icon convention, so every sidebar reads the same: `PanelLeft*`
|
|
@@ -38,6 +41,10 @@ Import the panel CSS (`@kerfjs/ui/collapsible-panel.css`) alongside `foundation.
|
|
|
38
41
|
`deviceClass()` signal): the open panel floats over the content with a
|
|
39
42
|
dismissable backdrop, Escape and backdrop-click collapse it, and Tab is trapped
|
|
40
43
|
within the panel (the ARIA dialog pattern);
|
|
44
|
+
- accepts `compactPresentation: "hidden"` when a compact application replaces
|
|
45
|
+
the panel with different navigation instead of overlaying it;
|
|
46
|
+
- keeps compact overlays exclusive by default, collapsing another open panel
|
|
47
|
+
when a new one opens (`exclusiveCompact: false` opts out);
|
|
41
48
|
- **persists** the collapsed state to `storage` (default `localStorage`) under
|
|
42
49
|
`storageKey`, seeding the signal on wire-up.
|
|
43
50
|
|
|
@@ -263,14 +263,11 @@ into the section label. Do not add padding to pane shells,
|
|
|
263
263
|
double child-owned geometry with wrapper insets, or create competing scroll
|
|
264
264
|
owners. The [layout contract](./layout.md) lists the public roles and tokens.
|
|
265
265
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
when no icon is passed. The optional summary is a separate row aligned below the
|
|
272
|
-
title, so it cannot pull the icon group out of vertical alignment with the
|
|
273
|
-
title and action row.
|
|
266
|
+
Panel, dialog, and page headings are direct `Toolbar` compositions. The leading
|
|
267
|
+
zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
|
|
268
|
+
`ToolbarText`; app actions belong in a trailing `ToolbarControlGroup`. Omit the
|
|
269
|
+
icon group when it has no content. Supporting copy is app-owned content below
|
|
270
|
+
the toolbar so it cannot pull the icon or actions out of alignment.
|
|
274
271
|
|
|
275
272
|
`ValueTable` composes typed `ValueTableRow` entries. A row owns its `dt`/`dd`
|
|
276
273
|
semantics and may receive a leading `SafeHtml` icon. Every row keeps 8px of
|