@kerfjs/ui 5.0.0-beta.53 → 5.0.0-beta.55
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 +4 -2
- package/ai/application-ui-diagnostic-ids-v1.json +1 -0
- package/ai/component-catalog-v2.json +138 -5
- package/ai/component-catalog-v2.schema.json +2 -1
- package/ai/component-catalog.json +208 -16
- package/ai/public-api-signatures-v1.md +462 -39
- package/ai/skill.md +28 -20
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +48 -0
- package/analyzer/loud-pairs.d.mts +49 -0
- package/analyzer/loud-pairs.mjs +357 -0
- package/dist/app-tab.d.ts +7 -5
- package/dist/app-tab.js +1 -1
- package/dist/browser/popup-menu.js +3 -0
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +10 -4
- package/dist/catalog.js +243 -300
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-7IUSV4XG.js → chunk-24PHKUR3.js} +2 -2
- package/dist/chunk-24PHKUR3.js.map +1 -0
- package/dist/{chunk-EKYZCRCX.js → chunk-3CGQ7ZNO.js} +54 -22
- package/dist/chunk-3CGQ7ZNO.js.map +1 -0
- package/dist/{chunk-UKKSMZYT.js → chunk-46263QLK.js} +51 -1
- package/dist/chunk-46263QLK.js.map +1 -0
- package/dist/chunk-4BIMLITI.js +92 -0
- package/dist/chunk-4BIMLITI.js.map +1 -0
- package/dist/{chunk-NDUGJ4TU.js → chunk-5NDQABWK.js} +1 -1
- package/dist/{chunk-NDUGJ4TU.js.map → chunk-5NDQABWK.js.map} +1 -1
- package/dist/{chunk-ZK5EGVFP.js → chunk-5OLVUEND.js} +12 -2
- package/dist/chunk-5OLVUEND.js.map +1 -0
- package/dist/{chunk-CMUIXJZM.js → chunk-BSKEH3UC.js} +2 -2
- package/dist/{chunk-CMUIXJZM.js.map → chunk-BSKEH3UC.js.map} +1 -1
- package/dist/chunk-EAX2GSS4.js +384 -0
- package/dist/chunk-EAX2GSS4.js.map +1 -0
- package/dist/chunk-KH6VUGHU.js +399 -0
- package/dist/chunk-KH6VUGHU.js.map +1 -0
- package/dist/{chunk-BJJKFVWW.js → chunk-LZXQVUGN.js} +2 -2
- package/dist/chunk-LZXQVUGN.js.map +1 -0
- package/dist/chunk-N7FHFNT6.js +55 -0
- package/dist/chunk-N7FHFNT6.js.map +1 -0
- package/dist/{chunk-CCMKJWLX.js → chunk-NE5JAOQS.js} +7 -7
- package/dist/chunk-NE5JAOQS.js.map +1 -0
- package/dist/chunk-PSHUSWQH.js +18 -0
- package/dist/chunk-PSHUSWQH.js.map +1 -0
- package/dist/{chunk-KPNTVB7A.js → chunk-R754MHXX.js} +3 -3
- package/dist/{chunk-KPNTVB7A.js.map → chunk-R754MHXX.js.map} +1 -1
- package/dist/{chunk-HJKRCKDR.js → chunk-RNRUVPJ3.js} +4 -2
- package/dist/chunk-RNRUVPJ3.js.map +1 -0
- package/dist/{chunk-VOCPXGQN.js → chunk-VHADGP3B.js} +9 -8
- package/dist/chunk-VHADGP3B.js.map +1 -0
- package/dist/chunk-XQV2B4IL.js +14 -0
- package/dist/chunk-XQV2B4IL.js.map +1 -0
- package/dist/collapsible-panel.d.ts +46 -15
- package/dist/collapsible-panel.js +42 -10
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/floating-toolbar.d.ts +5 -2
- package/dist/floating-toolbar.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +20 -18
- package/dist/list-header.js +1 -1
- package/dist/list-inset-text.d.ts +7 -1
- package/dist/list-inset-text.js +2 -1
- package/dist/panel-toolbar-BFQxFITu.d.ts +52 -0
- package/dist/popup-menu-register.d.ts +9 -0
- package/dist/popup-menu-register.js +30 -0
- package/dist/popup-menu-register.js.map +1 -0
- package/dist/popup-menu.d.ts +71 -0
- package/dist/popup-menu.js +3 -0
- package/dist/popup-menu.js.map +1 -0
- package/dist/resizable-region.d.ts +4 -1
- package/dist/resizable-region.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog/components/catalog-example.css +0 -16
- package/dist/styles/catalog/components/catalog-stage.css +8 -13
- package/dist/styles/catalog/components/catalog.css +8 -18
- package/dist/styles/catalog.css +0 -5
- package/dist/styles/collapsible-panel.css +88 -10
- package/dist/styles/floating-toolbar.css +11 -6
- package/dist/styles/popup-menu.css +12 -0
- package/dist/styles/resizable-region.css +81 -13
- package/dist/styles/state-banner.css +13 -4
- package/dist/styles/styles.css +1 -0
- package/dist/styles/tab-bar.css +31 -3
- package/dist/styles/toolbar-control-group.css +13 -0
- package/dist/styles/toolbar.css +43 -2
- package/dist/styles/workbench.css +503 -10
- package/dist/text.js +1 -1
- package/dist/token-search-field.d.ts +10 -1
- package/dist/token-search-field.js +1 -1
- package/dist/{types-CEsieBZi.d.ts → types-D6vzj-VT.d.ts} +15 -0
- package/dist/wire-catalog.d.ts +13 -1
- package/dist/wire-catalog.js +18 -3
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-resizable-regions.d.ts +2 -1
- package/dist/wire-resizable-regions.js +2 -1
- package/dist/wire-sidebar.js +6 -3
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/wire-workbench.d.ts +109 -0
- package/dist/wire-workbench.js +6 -0
- package/dist/wire-workbench.js.map +1 -0
- package/dist/workbench.d.ts +166 -6
- package/dist/workbench.js +11 -104
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +66 -10
- package/docs/app-layouts.md +12 -1
- package/docs/catalog.md +27 -9
- package/docs/collapsible-panel.md +114 -1
- package/docs/component-contract.md +2 -2
- package/docs/component-selection.md +41 -23
- package/docs/design/templates/state-banner/danger-dark.svg +1 -1
- package/docs/design/templates/state-banner/danger.svg +1 -1
- package/docs/design/templates/state-banner/info-dark.svg +1 -1
- package/docs/design/templates/state-banner/info.svg +1 -1
- package/docs/design/templates/state-banner/success-dark.svg +1 -1
- package/docs/design/templates/state-banner/success.svg +1 -1
- package/docs/design/templates/state-banner/warning-dark.svg +1 -1
- package/docs/design/templates/state-banner/warning.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/document-baseline.md +4 -0
- package/docs/layout.md +10 -1
- package/docs/recipes.md +48 -39
- package/docs/surface-scaffold.md +1 -1
- package/docs/type-contracts.md +2 -1
- package/docs/ui-analyzer.md +94 -19
- package/docs/ui-doctor.md +6 -0
- package/docs/ux-demo.md +7 -3
- package/docs/webawesome-theme.md +11 -2
- package/docs/workbench.md +388 -8
- package/llms.txt +13 -8
- package/package.json +17 -2
- package/ux-demo/recipes/app-shell.tsx +141 -223
- package/ux-demo/recipes/collapsible-sidebar.tsx +48 -78
- package/ux-demo/recipes/list-detail-dialog.tsx +150 -54
- package/ux-demo/recipes/mount-recipe.ts +0 -5
- package/ux-demo/recipes/types.ts +0 -1
- package/dist/chunk-7IUSV4XG.js.map +0 -1
- package/dist/chunk-BJJKFVWW.js.map +0 -1
- package/dist/chunk-CCMKJWLX.js.map +0 -1
- package/dist/chunk-EKYZCRCX.js.map +0 -1
- package/dist/chunk-HJKRCKDR.js.map +0 -1
- package/dist/chunk-UKKSMZYT.js.map +0 -1
- package/dist/chunk-VOCPXGQN.js.map +0 -1
- package/dist/chunk-ZK5EGVFP.js.map +0 -1
- package/dist/styles/catalog/components/catalog-detail.css +0 -35
- package/dist/styles/catalog/components/catalog-resource-footer.css +0 -37
- package/dist/styles/catalog/components/catalog-secondary-sections.css +0 -38
- package/dist/styles/catalog/components/catalog-section-list.css +0 -22
- package/dist/styles/catalog/components/catalog-sidebar.css +0 -82
package/dist/workbench.d.ts
CHANGED
|
@@ -1,32 +1,189 @@
|
|
|
1
1
|
import { SafeHtml } from 'kerfjs';
|
|
2
2
|
import { ResizableRegionSeparator, ResizableRegionCollapseMotion, ResizableRegionContentOverflow, ResizableRegionPresentation, ResizableRegionRestorePosition } from './resizable-region.js';
|
|
3
3
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
4
|
+
import { a as PanelToolbar, b as PanelToggle } from './panel-toolbar-BFQxFITu.js';
|
|
5
|
+
import { ToolbarProps } from './toolbar.js';
|
|
6
|
+
import './lucide-icon.js';
|
|
7
|
+
import 'lucide';
|
|
8
|
+
import './divider-sides-BzB6rphT.js';
|
|
9
|
+
import './pane.js';
|
|
4
10
|
|
|
11
|
+
/** The standard toggle a Workbench renders for a panel (see {@link PanelToggle}). */
|
|
12
|
+
type WorkbenchPanelToggle = PanelToggle;
|
|
13
|
+
/**
|
|
14
|
+
* A Workbench panel's top toolbar, composed by the Workbench so its groups can
|
|
15
|
+
* follow the panel's open state (see {@link PanelToolbar} for the roles).
|
|
16
|
+
* A collapsed rail's `constant` groups and toggle go to the leading edge of
|
|
17
|
+
* `mainToolbar` (left rail) or its trailing edge (right rail); a collapsed
|
|
18
|
+
* drawer's go to the trailing edge of `mainBottomToolbar`, else to a
|
|
19
|
+
* `FloatingToolbar` in the work area's bottom-end corner.
|
|
20
|
+
*/
|
|
21
|
+
type WorkbenchPanelToolbar = PanelToolbar;
|
|
22
|
+
/** The work area's top toolbar; collapsed rails add their groups to it. */
|
|
23
|
+
interface WorkbenchMainToolbar {
|
|
24
|
+
label: string;
|
|
25
|
+
/** The work area's title, usually an extra-large `ToolbarText`. */
|
|
26
|
+
title?: KerfUiContent;
|
|
27
|
+
/** Groups after the title. */
|
|
28
|
+
leading?: KerfUiContent;
|
|
29
|
+
center?: KerfUiContent;
|
|
30
|
+
/** Groups at the trailing edge, before a collapsed right rail's groups. */
|
|
31
|
+
trailing?: KerfUiContent;
|
|
32
|
+
/** The toolbar's narrow-width policy (see `Toolbar.responsive`). */
|
|
33
|
+
responsive?: ToolbarProps['responsive'];
|
|
34
|
+
responsiveAt?: ToolbarProps['responsiveAt'];
|
|
35
|
+
}
|
|
36
|
+
/** The work area's bottom toolbar; a collapsed drawer adds its groups to it. */
|
|
37
|
+
interface WorkbenchMainBottomToolbar {
|
|
38
|
+
label: string;
|
|
39
|
+
leading?: KerfUiContent;
|
|
40
|
+
trailing?: KerfUiContent;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The work area: the app's `main` under `mainToolbar` (and above
|
|
44
|
+
* `mainBottomToolbar`), with each collapsed panel's groups added to the
|
|
45
|
+
* toolbar on its side. Without either toolbar, `main` renders as given.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Whether the work area's header or footer chrome stays pinned (`fixed`) or
|
|
49
|
+
* scrolls away with the content (`scroll`).
|
|
50
|
+
*/
|
|
51
|
+
type WorkbenchChromePlacement = 'fixed' | 'scroll';
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The Workbench container breakpoint below which a panel presents as an
|
|
55
|
+
* overlay: `narrow` (704px or less) or `compact` (448px or less) — the same
|
|
56
|
+
* breakpoints as `ResizableRegion`'s `responsiveFillAt` — or `never` to keep
|
|
57
|
+
* it inline at every width.
|
|
58
|
+
*/
|
|
59
|
+
type WorkbenchResponsiveOverlayAt = 'compact' | 'narrow' | 'never';
|
|
60
|
+
/**
|
|
61
|
+
* How wide a rail's overlay is in a compact (448px or less) Workbench: `inset`
|
|
62
|
+
* fills the Workbench less a dismiss margin on the side away from the rail's
|
|
63
|
+
* edge, so a press beside it closes it; `full` fills the Workbench.
|
|
64
|
+
*/
|
|
65
|
+
type WorkbenchCompactOverlay = 'inset' | 'full';
|
|
66
|
+
/** Drag-resize limits for a resizable Workbench panel, in px. */
|
|
67
|
+
interface WorkbenchPanelResizable {
|
|
68
|
+
/** Smallest size (default 180 for a rail, 120 for the drawer). */
|
|
69
|
+
min?: number;
|
|
70
|
+
/** Largest size (default 480). */
|
|
71
|
+
max?: number;
|
|
72
|
+
}
|
|
5
73
|
/** A collapsible Workbench panel — a side rail or the bottom drawer. */
|
|
6
74
|
interface WorkbenchPanel {
|
|
7
75
|
content: KerfUiContent;
|
|
76
|
+
/**
|
|
77
|
+
* The panel's top toolbar, composed by the Workbench: its `constant` groups
|
|
78
|
+
* and standard `toggle` move to the work area's toolbar while the panel is
|
|
79
|
+
* collapsed. With it, `content` renders in a `Pane` below the toolbar.
|
|
80
|
+
*/
|
|
81
|
+
toolbar?: WorkbenchPanelToolbar;
|
|
82
|
+
/** Optional bottom toolbar under a `toolbar` panel's content. */
|
|
83
|
+
footer?: KerfUiContent;
|
|
8
84
|
/** Whether the panel is currently collapsed (the app owns this). */
|
|
9
85
|
collapsed?: boolean;
|
|
10
|
-
/**
|
|
86
|
+
/**
|
|
87
|
+
* Rail width, or drawer height, in px. Overrides the CSS default. For a
|
|
88
|
+
* resizable panel it is the current size (default 280 for a rail, 220 for
|
|
89
|
+
* the drawer), clamped to the limits; the app owns it and `wireWorkbench`
|
|
90
|
+
* reports each resize.
|
|
91
|
+
*/
|
|
11
92
|
size?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Opt in to drag and keyboard resizing on the panel's inner separator:
|
|
95
|
+
* `true` for the default limits, or `{ min, max }`. Off by default. Pair it
|
|
96
|
+
* with `wireWorkbench` from `@kerfjs/ui/wire-workbench`.
|
|
97
|
+
*/
|
|
98
|
+
resizable?: boolean | WorkbenchPanelResizable;
|
|
12
99
|
/** Accessible name for the panel region. */
|
|
13
100
|
label?: string;
|
|
14
101
|
separator?: ResizableRegionSeparator;
|
|
15
102
|
collapseMotion?: ResizableRegionCollapseMotion;
|
|
16
103
|
contentOverflow?: ResizableRegionContentOverflow;
|
|
17
104
|
presentation?: ResizableRegionPresentation;
|
|
18
|
-
/**
|
|
105
|
+
/**
|
|
106
|
+
* Present the panel as an overlay, without a separator, below a Workbench
|
|
107
|
+
* container breakpoint, and inline above it — the CSS decides, so the app
|
|
108
|
+
* needs no device-class check. A rail overlays from its side at full
|
|
109
|
+
* height, over the work area and an open drawer; the bottom drawer
|
|
110
|
+
* overlays the bottom of the work-area column. Rails default to `narrow`
|
|
111
|
+
* (pass `never` to keep one inline); the drawer defaults to inline.
|
|
112
|
+
*/
|
|
113
|
+
responsiveOverlayAt?: WorkbenchResponsiveOverlayAt;
|
|
114
|
+
/**
|
|
115
|
+
* A rail's overlay width in a compact Workbench (default `inset`: the
|
|
116
|
+
* Workbench less `--kui-workbench-overlay-dismiss-margin`, 44px). Ignored
|
|
117
|
+
* by the drawer.
|
|
118
|
+
*/
|
|
119
|
+
compactOverlay?: WorkbenchCompactOverlay;
|
|
120
|
+
/**
|
|
121
|
+
* Control shown while collapsed, in a safe-area-aware corner of the
|
|
122
|
+
* Workbench (not the viewport); the bottom drawer's sits in the work-area
|
|
123
|
+
* column. Prefer `toolbar.toggle`, which the Workbench relocates into the
|
|
124
|
+
* work area's toolbar (or this corner when that toolbar is absent).
|
|
125
|
+
*/
|
|
19
126
|
restoreControl?: SafeHtml;
|
|
20
127
|
restorePosition?: ResizableRegionRestorePosition;
|
|
21
128
|
}
|
|
22
129
|
interface WorkbenchProps {
|
|
130
|
+
/**
|
|
131
|
+
* The Workbench's `id`. Each panel's `id` derives from it —
|
|
132
|
+
* `<id>-left-rail`, `<id>-right-rail`, `<id>-bottom-drawer` — so a toggle
|
|
133
|
+
* can name the panel it shows and hides with `aria-controls`.
|
|
134
|
+
*/
|
|
23
135
|
id: string;
|
|
24
136
|
label: string;
|
|
25
137
|
/** The central work area. */
|
|
26
138
|
main: KerfUiContent;
|
|
139
|
+
/**
|
|
140
|
+
* The work area's top toolbar. A collapsed left rail's `constant` groups
|
|
141
|
+
* and toggle lead it; a collapsed right rail's trail it. With it, `main`
|
|
142
|
+
* renders in a `Pane` below the toolbar.
|
|
143
|
+
*/
|
|
144
|
+
mainToolbar?: WorkbenchMainToolbar;
|
|
145
|
+
/**
|
|
146
|
+
* Fixed content under `mainToolbar` — supporting copy such as a
|
|
147
|
+
* description — divided from the scrolling `main` below it.
|
|
148
|
+
*/
|
|
149
|
+
mainHeader?: KerfUiContent;
|
|
150
|
+
/**
|
|
151
|
+
* Fixed content over `mainBottomToolbar` — a status line or a resource
|
|
152
|
+
* toolbar — divided from the scrolling `main` above it.
|
|
153
|
+
*/
|
|
154
|
+
mainFooter?: KerfUiContent;
|
|
155
|
+
/**
|
|
156
|
+
* The work area's bottom toolbar. A collapsed drawer's `constant` groups and
|
|
157
|
+
* toggle trail it; without it they float in the work area's corner.
|
|
158
|
+
*/
|
|
159
|
+
mainBottomToolbar?: WorkbenchMainBottomToolbar;
|
|
160
|
+
/**
|
|
161
|
+
* Whether `mainToolbar` and `mainHeader` stay pinned (`fixed`, default) or
|
|
162
|
+
* scroll away with `main` (`scroll`) — useful where large text would leave
|
|
163
|
+
* pinned chrome little room.
|
|
164
|
+
*/
|
|
165
|
+
mainHeaderPlacement?: WorkbenchChromePlacement;
|
|
166
|
+
/** The same for `mainFooter` and `mainBottomToolbar` (default `fixed`). */
|
|
167
|
+
mainFooterPlacement?: WorkbenchChromePlacement;
|
|
27
168
|
leftRail?: WorkbenchPanel;
|
|
28
169
|
rightRail?: WorkbenchPanel;
|
|
29
170
|
bottomDrawer?: WorkbenchPanel;
|
|
171
|
+
/**
|
|
172
|
+
* Minimum width, in px, the work area keeps beside the inline rails, fixed
|
|
173
|
+
* or `resizable` (default 320; `0` turns it off). Resizing a rail stops
|
|
174
|
+
* where the work area would drop below it, and inline rails shrink
|
|
175
|
+
* proportionally when the Workbench gets narrower. Workbenches without a
|
|
176
|
+
* rail ignore it.
|
|
177
|
+
*/
|
|
178
|
+
mainMinSize?: number;
|
|
179
|
+
/**
|
|
180
|
+
* Minimum height, in px, the work area keeps above an inline bottom drawer,
|
|
181
|
+
* fixed or `resizable` (default 120; `0` turns it off) — the drawer's
|
|
182
|
+
* counterpart of `mainMinSize`. Resizing the drawer stops where the work
|
|
183
|
+
* area would drop below it, and the drawer shrinks when the Workbench gets
|
|
184
|
+
* shorter. Workbenches without a drawer ignore it.
|
|
185
|
+
*/
|
|
186
|
+
mainMinHeight?: number;
|
|
30
187
|
className?: string;
|
|
31
188
|
/** Native named-slot assignment when composed inside a web component. */
|
|
32
189
|
slot?: string;
|
|
@@ -38,9 +195,12 @@ interface WorkbenchProps {
|
|
|
38
195
|
* a composited transform — the instant-width / sliding-content technique, so the
|
|
39
196
|
* work area relayouts once, not per frame. Bottom-drawer content stays anchored
|
|
40
197
|
* to the shell's stable bottom edge throughout that transition. The app owns
|
|
41
|
-
* each `collapsed` flag; the collapse is pure CSS
|
|
42
|
-
* `
|
|
198
|
+
* each `collapsed` flag; the collapse is pure CSS. A collapsed panel renders
|
|
199
|
+
* `inert` and `aria-hidden`, so neither Tab nor assistive technology reaches
|
|
200
|
+
* controls that have slid out of view or an empty landmark (its restore control
|
|
201
|
+
* lives outside it and stays reachable). A panel may opt in to drag and keyboard resizing with
|
|
202
|
+
* `resizable`, which `wireWorkbench` drives. See `docs/23-app-layouts.md` §3.3.
|
|
43
203
|
*/
|
|
44
|
-
declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, className, slot, }: WorkbenchProps): SafeHtml;
|
|
204
|
+
declare function Workbench({ id, label, main, leftRail, rightRail, bottomDrawer, mainToolbar, mainHeader, mainFooter, mainBottomToolbar, mainHeaderPlacement, mainFooterPlacement, mainMinSize, mainMinHeight, className, slot, }: WorkbenchProps): SafeHtml;
|
|
45
205
|
|
|
46
|
-
export { Workbench, type WorkbenchPanel, type WorkbenchProps };
|
|
206
|
+
export { Workbench, type WorkbenchChromePlacement, type WorkbenchCompactOverlay, type WorkbenchMainBottomToolbar, type WorkbenchMainToolbar, type WorkbenchPanel, type WorkbenchPanelResizable, type WorkbenchPanelToggle, type WorkbenchPanelToolbar, type WorkbenchProps, type WorkbenchResponsiveOverlayAt };
|
package/dist/workbench.js
CHANGED
|
@@ -1,108 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
export { Workbench } from './chunk-EAX2GSS4.js';
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
2
12
|
|
|
3
|
-
// src/workbench.tsx
|
|
4
|
-
function Workbench({
|
|
5
|
-
id,
|
|
6
|
-
label,
|
|
7
|
-
main,
|
|
8
|
-
leftRail,
|
|
9
|
-
rightRail,
|
|
10
|
-
bottomDrawer,
|
|
11
|
-
className = "",
|
|
12
|
-
slot
|
|
13
|
-
}) {
|
|
14
|
-
return /* @__PURE__ */ jsxs(
|
|
15
|
-
"section",
|
|
16
|
-
{
|
|
17
|
-
class: `kui-workbench ${className}`.trim(),
|
|
18
|
-
id,
|
|
19
|
-
"data-component": "workbench",
|
|
20
|
-
"aria-label": label,
|
|
21
|
-
slot,
|
|
22
|
-
children: [
|
|
23
|
-
leftRail && /* @__PURE__ */ jsx(
|
|
24
|
-
"aside",
|
|
25
|
-
{
|
|
26
|
-
class: "kui-workbench__rail kui-workbench__rail--left",
|
|
27
|
-
"data-workbench-rail": "left",
|
|
28
|
-
"data-collapsed": String(leftRail.collapsed ?? false),
|
|
29
|
-
"data-separator": leftRail.separator ?? "auto",
|
|
30
|
-
"data-collapse-motion": leftRail.collapseMotion ?? "slide",
|
|
31
|
-
"data-content-overflow": leftRail.contentOverflow ?? "clip",
|
|
32
|
-
"data-presentation": leftRail.presentation ?? "inline",
|
|
33
|
-
"aria-label": leftRail.label || void 0,
|
|
34
|
-
"aria-hidden": leftRail.presentation === "hidden" ? "true" : void 0,
|
|
35
|
-
style: leftRail.size ? `--kui-workbench-rail-width: ${leftRail.size}px` : void 0,
|
|
36
|
-
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: leftRail.content })
|
|
37
|
-
}
|
|
38
|
-
),
|
|
39
|
-
leftRail?.collapsed && leftRail.restoreControl && leftRail.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
40
|
-
"div",
|
|
41
|
-
{
|
|
42
|
-
class: "kui-workbench__restore",
|
|
43
|
-
"data-panel": "left",
|
|
44
|
-
"data-position": leftRail.restorePosition ?? "bottom-start",
|
|
45
|
-
children: leftRail.restoreControl
|
|
46
|
-
}
|
|
47
|
-
),
|
|
48
|
-
/* @__PURE__ */ jsxs("div", { class: "kui-workbench__center", children: [
|
|
49
|
-
/* @__PURE__ */ jsx("div", { class: "kui-workbench__main", "data-workbench-main": true, children: main }),
|
|
50
|
-
bottomDrawer && /* @__PURE__ */ jsx(
|
|
51
|
-
"section",
|
|
52
|
-
{
|
|
53
|
-
class: "kui-workbench__drawer",
|
|
54
|
-
"data-workbench-drawer": true,
|
|
55
|
-
"data-collapsed": String(bottomDrawer.collapsed ?? false),
|
|
56
|
-
"data-separator": bottomDrawer.separator ?? "auto",
|
|
57
|
-
"data-collapse-motion": bottomDrawer.collapseMotion ?? "slide",
|
|
58
|
-
"data-content-overflow": bottomDrawer.contentOverflow ?? "clip",
|
|
59
|
-
"data-presentation": bottomDrawer.presentation ?? "inline",
|
|
60
|
-
"aria-label": bottomDrawer.label || void 0,
|
|
61
|
-
"aria-hidden": bottomDrawer.presentation === "hidden" ? "true" : void 0,
|
|
62
|
-
style: bottomDrawer.size ? `--kui-workbench-drawer-height: ${bottomDrawer.size}px` : void 0,
|
|
63
|
-
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: bottomDrawer.content })
|
|
64
|
-
}
|
|
65
|
-
),
|
|
66
|
-
bottomDrawer?.collapsed && bottomDrawer.restoreControl && bottomDrawer.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
67
|
-
"div",
|
|
68
|
-
{
|
|
69
|
-
class: "kui-workbench__restore",
|
|
70
|
-
"data-panel": "bottom",
|
|
71
|
-
"data-position": bottomDrawer.restorePosition ?? "bottom-end",
|
|
72
|
-
children: bottomDrawer.restoreControl
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
] }),
|
|
76
|
-
rightRail && /* @__PURE__ */ jsx(
|
|
77
|
-
"aside",
|
|
78
|
-
{
|
|
79
|
-
class: "kui-workbench__rail kui-workbench__rail--right",
|
|
80
|
-
"data-workbench-rail": "right",
|
|
81
|
-
"data-collapsed": String(rightRail.collapsed ?? false),
|
|
82
|
-
"data-separator": rightRail.separator ?? "auto",
|
|
83
|
-
"data-collapse-motion": rightRail.collapseMotion ?? "slide",
|
|
84
|
-
"data-content-overflow": rightRail.contentOverflow ?? "clip",
|
|
85
|
-
"data-presentation": rightRail.presentation ?? "inline",
|
|
86
|
-
"aria-label": rightRail.label || void 0,
|
|
87
|
-
"aria-hidden": rightRail.presentation === "hidden" ? "true" : void 0,
|
|
88
|
-
style: rightRail.size ? `--kui-workbench-rail-width: ${rightRail.size}px` : void 0,
|
|
89
|
-
children: /* @__PURE__ */ jsx("div", { class: "kui-workbench__panel-content", children: rightRail.content })
|
|
90
|
-
}
|
|
91
|
-
),
|
|
92
|
-
rightRail?.collapsed && rightRail.restoreControl && rightRail.presentation !== "hidden" && /* @__PURE__ */ jsx(
|
|
93
|
-
"div",
|
|
94
|
-
{
|
|
95
|
-
class: "kui-workbench__restore",
|
|
96
|
-
"data-panel": "right",
|
|
97
|
-
"data-position": rightRail.restorePosition ?? "bottom-end",
|
|
98
|
-
children: rightRail.restoreControl
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
13
|
|
|
106
|
-
export { Workbench };
|
|
107
14
|
|
|
108
15
|
//# sourceMappingURL=workbench.js.map
|
package/dist/workbench.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"workbench.js"}
|
package/docs/accessibility.md
CHANGED
|
@@ -12,6 +12,7 @@ These are normative contracts for package components and consuming applications.
|
|
|
12
12
|
- `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
|
|
13
13
|
- In any `.kui-pane`, menu rows, `ListHeader` actions, and toolbar groups keep a minimum 44px target in both dimensions. A `ListHeader` fills the available inline width and keeps that action at the logical end, including in RTL. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square; a transparent hit layer extends the pointer target to at least 44 × 44 around that square without moving layout or enlarging the painted surface. Compact headers are 36px tall like the rest of the compact List family, so their action target is 44px wide and clamped to the 36px header height instead of reaching into a neighboring row. Do not reduce the target to the visible icon, and do not force the button itself to 44px.
|
|
14
14
|
- `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
|
|
15
|
+
- An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
|
|
15
16
|
- `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
|
|
16
17
|
- `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
|
|
17
18
|
- `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
|
|
@@ -34,7 +35,7 @@ Use `presentation="toolbar-borderless"` inside a `ToolbarControlGroup`, with
|
|
|
34
35
|
parent paints the composed focus ring. `selectedPresentation="icon-only"` hides
|
|
35
36
|
only the visible selected label—the required `label` or `ariaLabel` still names
|
|
36
37
|
the combobox. An icon-only trigger keeps its disclosure caret: the selected icon
|
|
37
|
-
and caret form one pill with the same geometry as a
|
|
38
|
+
and caret form one pill with the same geometry as a `PopupMenu`
|
|
38
39
|
trigger (8px inline padding on both sides, 12px from the icon to the caret, a
|
|
39
40
|
40px default or 32px compact control height), so the caret still signals a
|
|
40
41
|
choice list. Inside a group the trigger is inset evenly on every side (2px in a
|
|
@@ -80,6 +81,17 @@ repeated and out-of-order completions, cancellation, instance isolation, and
|
|
|
80
81
|
removal. `tests/browser/select-lifecycle.spec.ts` repeats animation/resize/reopen
|
|
81
82
|
sequences at wide and narrow widths in Chromium, Firefox, and WebKit.
|
|
82
83
|
|
|
84
|
+
## PopupMenu
|
|
85
|
+
|
|
86
|
+
`PopupMenu` renders a Web Awesome dropdown, so the menu roles, arrow-key and
|
|
87
|
+
typeahead navigation, Escape, and focus return to the trigger come from
|
|
88
|
+
`wa-dropdown`. Kerf's part is the trigger's name. A Web Awesome button takes its
|
|
89
|
+
name from its content and ignores an `aria-label` on the host, so an icon-only
|
|
90
|
+
trigger requires `label`, which renders as visually hidden text inside the
|
|
91
|
+
button; a trigger with visible `text` is named by that text. Group headings render as the dropdown's native menu labels, and
|
|
92
|
+
dividers are presentational. A disabled item stays in the menu but cannot be
|
|
93
|
+
chosen; disable the whole trigger only when every command is unavailable.
|
|
94
|
+
|
|
83
95
|
## ListActionRow
|
|
84
96
|
|
|
85
97
|
`ListActionRow` renders a noninteractive visual root containing primary and
|
|
@@ -120,6 +132,15 @@ The handle exposes separator role, orientation, name, minimum, maximum, and curr
|
|
|
120
132
|
them after a re-render writes the rendered props back, so assistive
|
|
121
133
|
technology never reads an unclamped size between interactions (the
|
|
122
134
|
disposer disconnects both observers);
|
|
135
|
+
- a truthful value below the minimum: when the container shows the track at
|
|
136
|
+
less than `min` (a narrowing `Workbench` squeezes its resizable rails), the
|
|
137
|
+
handle reports that shown size in `aria-valuenow` and pins `aria-valuemin`
|
|
138
|
+
and `aria-valuemax` to it — WAI-ARIA requires the value to lie inside the
|
|
139
|
+
range, and the separator cannot move a track its container holds. A pinned
|
|
140
|
+
separator — squeezed, or with a reachable range collapsed to one size —
|
|
141
|
+
commits nothing: arrow keys, Home/End, and drags leave the app's size (and
|
|
142
|
+
its storage) as it was, so the track returns to it, with the rendered range,
|
|
143
|
+
once it has room;
|
|
123
144
|
- a whole hit target and focus ring at a clamped edge: when the separator has
|
|
124
145
|
less room past it than the handle's 10px overhang (a parent clamps the track
|
|
125
146
|
to its own edge), the region carries `data-handle-inset` and the handle sits
|
|
@@ -162,7 +183,10 @@ forced to a dark color scheme, but it is **not** in the top layer, so it never
|
|
|
162
183
|
covers dialogs, popovers, or other overlays. Its children are the app's controls
|
|
163
184
|
(normally `ToolbarControlGroup`s), which keep their own names, focus, and
|
|
164
185
|
keyboard behavior; the application owns their actions, the toolbar's visibility,
|
|
165
|
-
and — via `position` and `--kui-floating-toolbar-inset
|
|
186
|
+
and — via `position` and `--kui-floating-toolbar-inset`, set on the toolbar
|
|
187
|
+
or an ancestor — where it sits. Inside a `Workbench`, `CollapsiblePanel`, or
|
|
188
|
+
`ResizableRegion` `restoreControl` the restore corner owns the inset, so the
|
|
189
|
+
toolbar floats from that corner.
|
|
166
190
|
|
|
167
191
|
## Tabs
|
|
168
192
|
|
|
@@ -180,8 +204,11 @@ that geometry; applications must not override its anatomy to create the split.
|
|
|
180
204
|
presentations. Icon-only tabs keep the required `name` as the tab button's
|
|
181
205
|
accessible name while visually hiding the duplicate label. A `pending` tab (known,
|
|
182
206
|
still opening) keeps its visible name as the tab button's accessible name, so a
|
|
183
|
-
trailing spinner's own label is not folded into it
|
|
184
|
-
|
|
207
|
+
trailing spinner's own label is not folded into it. It is `aria-busy` and stays
|
|
208
|
+
selectable (in the roving tab order like a live tab), so the application can
|
|
209
|
+
show placeholder content in its panel until loading completes; its close
|
|
210
|
+
button is disabled and hidden and it is not draggable. A `placeholder` tab
|
|
211
|
+
(unknown) is instead disabled, out of the tab order, and not draggable. These props own
|
|
185
212
|
component appearance only; the application still owns the bar's outer placement.
|
|
186
213
|
`AppTab.rootAttributes` accepts application `data-*` metadata only; runtime
|
|
187
214
|
filtering rejects roles plus case variants of component- or wiring-owned
|
|
@@ -192,8 +219,11 @@ and must not contain interactive descendants.
|
|
|
192
219
|
activation, same-bar pointer reordering, `Alt+Shift+ArrowLeft/ArrowRight`
|
|
193
220
|
reordering, focus restoration, scroll-into-view, and pointer-proximity
|
|
194
221
|
autoscroll at either horizontal edge. Edge autoscroll is direct manipulation,
|
|
195
|
-
stops on drop/drag end/disposal, and does not change keyboard behavior.
|
|
196
|
-
|
|
222
|
+
stops on drop/drag end/disposal, and does not change keyboard behavior. When
|
|
223
|
+
the application changes a bar's selected tab without focus (adding and
|
|
224
|
+
selecting a tab), the wiring scrolls that tab's strip — never the page — so
|
|
225
|
+
the new selection is fully visible; a re-render that keeps the same selection
|
|
226
|
+
leaves a strip the user scrolled where it is. It returns a disposer.
|
|
197
227
|
|
|
198
228
|
Arrow / Home / End follow the ARIA Tabs **automatic-activation** pattern by
|
|
199
229
|
default: they move roving focus and select the focused tab. If selection synchronously
|
|
@@ -276,15 +306,26 @@ and focus deliberately moved to another control; no app-level reopen callback is
|
|
|
276
306
|
|
|
277
307
|
## CollapsiblePanel / sidebar
|
|
278
308
|
|
|
279
|
-
`CollapsiblePanel` is a labeled `aside` region that
|
|
280
|
-
collapsed
|
|
309
|
+
`CollapsiblePanel` is a labeled `aside` region that renders `inert` and
|
|
310
|
+
`aria-hidden` while collapsed, straight from the app's `collapsed` flag, so its
|
|
311
|
+
controls leave the Tab order and the accessibility tree even while the content
|
|
312
|
+
is still sliding out, and focusing one can never scroll clipped content back into
|
|
313
|
+
view (`aria-hidden` alone left them focusable inside a hidden subtree). Its
|
|
314
|
+
content slides via transform (disabled under reduced motion); `inert` does not
|
|
315
|
+
affect rendering, so the slide still plays. A `restoreControl` renders outside
|
|
316
|
+
the panel and stays reachable. A collapsed `ResizableRegion` renders `inert` and
|
|
317
|
+
`aria-hidden` on the region itself the same way (its content wrapper is `inert`
|
|
318
|
+
too, and its separator is already hidden and not displayed), so no empty
|
|
319
|
+
labeled region landmark stays behind; its `restoreControl` stays outside the
|
|
320
|
+
region.
|
|
281
321
|
`CollapsiblePanelToggle` is a named button carrying `aria-expanded` and the
|
|
282
322
|
standard per-side collapse/expand glyph (`PanelLeft*` / `PanelRight*` /
|
|
283
323
|
`PanelBottom*`); place a collapse toggle inside the panel and an expand toggle in
|
|
284
324
|
an always-visible location so it is reachable while collapsed. `wireSidebar()`
|
|
285
325
|
moves focus into the panel when it opens and restores it to the trigger when it
|
|
286
|
-
closes; a trigger inside the now-
|
|
287
|
-
outside it instead
|
|
326
|
+
closes; a trigger inside the now-inert panel hands focus to the panel's toggle
|
|
327
|
+
outside it instead (and focus stranded there by a wide → compact crossing is
|
|
328
|
+
rescued the same way), so an app may render the expand toggle only while the panel
|
|
288
329
|
is collapsed. When a `deviceClass()` reports `compact`, an open panel becomes an overlay
|
|
289
330
|
with a dismissable backdrop, Escape and backdrop-click collapse it, and Tab is
|
|
290
331
|
trapped within it (the ARIA dialog pattern). That modal state only ever begins
|
|
@@ -293,6 +334,21 @@ crossing, every panel starts collapsed, so no page load or resize traps focus. T
|
|
|
293
334
|
signal, the panels, their sizes, and content; the wire may persist the collapsed
|
|
294
335
|
state per panel.
|
|
295
336
|
|
|
337
|
+
## Workbench
|
|
338
|
+
|
|
339
|
+
Each `Workbench` rail and drawer is a labeled region (`aside` for a rail, `section`
|
|
340
|
+
for the drawer). While a panel is collapsed the region itself renders `inert` and
|
|
341
|
+
`aria-hidden="true"`, and so does not linger as an empty landmark, and its content
|
|
342
|
+
wrapper is `inert`, all rendered from the app's `collapsed` flag, so its controls
|
|
343
|
+
leave the Tab order and the accessibility tree even while the content is still
|
|
344
|
+
sliding out, and focusing one can never scroll clipped content back into view. The panel's `restoreControl` renders
|
|
345
|
+
outside that content and stays reachable; a resizable panel's separator also leaves
|
|
346
|
+
the Tab order while collapsed or not inline. `wireWorkbench`, given a panel's
|
|
347
|
+
`collapsed` signal, returns focus stranded in a closing panel to the control that
|
|
348
|
+
opened it, else the restore control, else a control whose `aria-controls` names the
|
|
349
|
+
panel; an open overlay panel takes focus and keeps Tab inside it (the ARIA dialog
|
|
350
|
+
pattern). See [`workbench.md`](workbench.md).
|
|
351
|
+
|
|
296
352
|
## Verification matrix
|
|
297
353
|
|
|
298
354
|
For each changed component, inspect default, hover, focus, disabled, selected/pressed, busy/error, long-content, wide, narrow, light, dark, increased-contrast, reduced-motion, keyboard-only, and 200%-zoom states where applicable. DOM order must match reading and focus order, with no clipping or unreachable action.
|
package/docs/app-layouts.md
CHANGED
|
@@ -113,7 +113,18 @@ device in tests.
|
|
|
113
113
|
selection).
|
|
114
114
|
- **IDE (complex tool):** `Workbench` with a left navigator rail, a right
|
|
115
115
|
inspector rail, and a bottom console drawer, each `collapsed` bound to a
|
|
116
|
-
signal. Only offer this `atLeast('desktop')`.
|
|
116
|
+
signal. Only offer this `atLeast('desktop')`. To let people size the
|
|
117
|
+
navigator or console, opt those panels in with `resizable` and call
|
|
118
|
+
`wireWorkbench` with their size signals and `deviceClass`; resizing is
|
|
119
|
+
suspended on `compact`, where the rails become overlay drawers — or give each
|
|
120
|
+
rail `responsiveOverlayAt: "narrow"` and let the Workbench's own width decide
|
|
121
|
+
when it overlays, with no device check; pass each rail's `collapsed` signal
|
|
122
|
+
to `wireWorkbench` so the overlay starts collapsed, takes focus and keeps Tab
|
|
123
|
+
inside it while open, and closes on Escape or an outside press. Inline
|
|
124
|
+
rails, fixed or resizable, leave the editor its `mainMinSize` (320px by
|
|
125
|
+
default) and shrink in proportion when the window narrows; the bottom drawer
|
|
126
|
+
leaves it `mainMinHeight` (120px by default) and shrinks when the window gets
|
|
127
|
+
shorter.
|
|
117
128
|
- **Social app (tabbed):** `TabScaffold` with Home / Search / Profile tabs, each
|
|
118
129
|
`content` a `NavStack`. On a tablet/desktop, render the same sections as a
|
|
119
130
|
`Workbench` left rail instead of a bottom bar.
|
package/docs/catalog.md
CHANGED
|
@@ -6,6 +6,15 @@ footer that the kerf UI catalog itself uses. Point it at your own components and
|
|
|
6
6
|
you get the same shell without rebuilding it. Like the app layouts, it is a
|
|
7
7
|
subpath-only, tree-shakeable module that adds nothing to the main barrel.
|
|
8
8
|
|
|
9
|
+
The shell is a [`Workbench`](workbench.md) built entirely from `@kerfjs/ui`
|
|
10
|
+
components: the sidebar is its left rail and the active entry its work area. So
|
|
11
|
+
the sidebar behaves like any Workbench rail — its standard toggle moves into the
|
|
12
|
+
entry toolbar while it is collapsed, and on a small screen (a Workbench narrower
|
|
13
|
+
than 704px) it overlays the stage, one tap from the entry toolbar, filling the
|
|
14
|
+
width less a 44px strip that closes it, instead of squeezing the stage. Pass the
|
|
15
|
+
app's `collapsed` signal to `wireCatalog` so that overlay closes on Escape, on a
|
|
16
|
+
press outside, and when an entry is chosen from it.
|
|
17
|
+
|
|
9
18
|
```bash
|
|
10
19
|
npm install @kerfjs/ui # kerfjs is a peer; @kerfjs/ui/select/register is needed only if entries use `related`
|
|
11
20
|
```
|
|
@@ -36,9 +45,9 @@ expanded? }`. When `collapsible`, the label is a disclosure toggle controlling
|
|
|
36
45
|
sidebar content), and `status` (a footer status line).
|
|
37
46
|
|
|
38
47
|
Per-entry `resources` render as "open in new tab" links in the footer, and
|
|
39
|
-
`related` renders a "Related entries"
|
|
40
|
-
|
|
41
|
-
with `@kerfjs/ui/
|
|
48
|
+
`related` renders a "Related entries" `PopupMenu` in a `single`
|
|
49
|
+
`ToolbarControlGroup` (grouped by each entry's `group`), so register its elements
|
|
50
|
+
with `@kerfjs/ui/popup-menu/register` when you use it.
|
|
42
51
|
|
|
43
52
|
## Catalog demo authoring contract
|
|
44
53
|
|
|
@@ -249,8 +258,8 @@ Set `revealSelection: true` on `wireCatalog` for a long desktop sidebar. After
|
|
|
249
258
|
`onSelect` updates controlled state, the helper waits one animation frame, finds
|
|
250
259
|
the exact matching `data-item-id`, and scrolls it into view without changing
|
|
251
260
|
focus. A newer selection or disposal cancels the pending reveal. The default
|
|
252
|
-
media guard
|
|
253
|
-
|
|
261
|
+
media guard follows the Workbench's inline sidebar (`min-width: 44.01rem`), so a
|
|
262
|
+
closed phone overlay is never scrolled behind the user's back.
|
|
254
263
|
|
|
255
264
|
Pass an options object instead of `true` to customize `block`, `inline`,
|
|
256
265
|
`behavior`, or `media`; `media: false` deliberately enables the behavior at all
|
|
@@ -384,6 +393,12 @@ revealCatalogEntry(app, initial, { block: "center" });
|
|
|
384
393
|
- **`active`** is domain state (which entry is shown) — the app's signal, updated in
|
|
385
394
|
`onSelect`, read to compute `content`.
|
|
386
395
|
- **`collapsed`** is transient UI — the app's signal, flipped in `onToggleSidebar`.
|
|
396
|
+
Pass the same signal as `wireCatalog`'s `collapsed` option so the sidebar is
|
|
397
|
+
wired as a Workbench rail (transient on small screens, focus handed to the
|
|
398
|
+
relocated toggle).
|
|
399
|
+
- **`headerPlacement` / `footerPlacement`** choose whether the entry toolbar and the
|
|
400
|
+
status + resource footer stay pinned (`fixed`, default) or scroll with the preview
|
|
401
|
+
(`scroll`) — useful where large text would leave pinned chrome little room.
|
|
387
402
|
- **`theme`** is a global preference — the app's signal; `wireCatalog` only reports
|
|
388
403
|
the toggle, the app applies the theme (the shell reads `theme` to show the toggle's
|
|
389
404
|
opposite-state label). Omit `theme` to hide the toggle entirely.
|
|
@@ -397,7 +412,10 @@ matching options on `wireCatalog`) if they collide with your own action table.
|
|
|
397
412
|
|
|
398
413
|
## CSS
|
|
399
414
|
|
|
400
|
-
`Catalog` composes public
|
|
401
|
-
…)
|
|
402
|
-
|
|
403
|
-
|
|
415
|
+
`Catalog` composes public components (`Workbench`, `Pane`, `Toolbar`, `List`,
|
|
416
|
+
`ListHeader`, `ListItem`, `ListInsetText`, `Text`, …) and owns only the preview stage
|
|
417
|
+
(the checkerboard and centered canvas), the geometry overlay, the example viewport
|
|
418
|
+
options, and the brand mark's size. Import `@kerfjs/ui/styles.css` for the whole
|
|
419
|
+
layer, or `@kerfjs/ui/catalog.css` plus `@kerfjs/ui/workbench.css` and each composed
|
|
420
|
+
primitive's CSS. Like any Workbench it needs a definite containing height — the
|
|
421
|
+
`@kerfjs/ui/document.css` baseline's `.kui-app-root`.
|