@kerfjs/ui 5.0.0-beta.6 → 5.0.0-beta.61
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 +494 -138
- package/ai/application-ui-diagnostic-ids-v1.json +109 -0
- package/ai/application-ui-profile-sync.cjs +529 -0
- package/ai/application-ui-profile.d.mts +1 -0
- package/ai/application-ui-profile.d.ts +102 -0
- package/ai/application-ui-profile.defaults.json +96 -0
- package/ai/application-ui-profile.mjs +626 -0
- package/ai/application-ui-profile.schema.json +130 -0
- package/ai/catalog-authoring.json +36 -0
- package/ai/catalog-authoring.schema.json +109 -0
- package/ai/compile-time-contracts-v1.json +149 -0
- package/ai/compile-time-contracts-v1.schema.json +52 -0
- package/ai/component-catalog-extension.schema.json +79 -0
- package/ai/component-catalog.json +4041 -591
- package/ai/component-catalog.schema.json +78 -1
- package/ai/component-class-owners.cjs +83 -0
- package/ai/component-composition-extension.d.ts +7 -0
- package/ai/component-composition-extension.schema.json +7 -0
- package/ai/component-composition-rules.json +524 -0
- package/ai/component-composition.d.ts +125 -0
- package/ai/component-composition.json +7074 -0
- package/ai/component-composition.schema.json +375 -0
- package/ai/components/README.md +171 -0
- package/ai/components/application-tabs.md +65 -0
- package/ai/components/badge.md +72 -0
- package/ai/components/chip.md +72 -0
- package/ai/components/collapsible-panel.md +102 -0
- package/ai/components/content-item.md +90 -0
- package/ai/components/disclosure-arrow.md +77 -0
- package/ai/components/document-baseline.md +75 -0
- package/ai/components/empty-state.md +80 -0
- package/ai/components/feedback.md +71 -0
- package/ai/components/floating-toolbar.md +82 -0
- package/ai/components/foundation.md +65 -0
- package/ai/components/grid.md +96 -0
- package/ai/components/headers.md +63 -0
- package/ai/components/layout.md +75 -0
- package/ai/components/list-action-row.md +91 -0
- package/ai/components/list-header.md +89 -0
- package/ai/components/list-inset-control.md +74 -0
- package/ai/components/list-inset-text.md +72 -0
- package/ai/components/list-item.md +94 -0
- package/ai/components/list.md +103 -0
- package/ai/components/loading-spinner.md +72 -0
- package/ai/components/lucide-icon.md +66 -0
- package/ai/components/nav-stack.md +103 -0
- package/ai/components/pane.md +100 -0
- package/ai/components/popup-menu.md +171 -0
- package/ai/components/recipe-app-shell.md +57 -0
- package/ai/components/recipe-collapsible-sidebar.md +57 -0
- package/ai/components/recipe-compact-toolbar.md +57 -0
- package/ai/components/recipe-composer-form.md +57 -0
- package/ai/components/recipe-list-detail-dialog.md +57 -0
- package/ai/components/recipe-list-workspace-states.md +57 -0
- package/ai/components/recipe-loading-inspector.md +57 -0
- package/ai/components/recipe-navigation-sidebar.md +57 -0
- package/ai/components/recipe-navigation-stack.md +57 -0
- package/ai/components/recipe-workspace-header.md +57 -0
- package/ai/components/resize.md +106 -0
- package/ai/components/row.md +96 -0
- package/ai/components/segmented-control.md +82 -0
- package/ai/components/select.md +112 -0
- package/ai/components/skeleton.md +84 -0
- package/ai/components/spacer.md +86 -0
- package/ai/components/split-view.md +102 -0
- package/ai/components/state-banner.md +94 -0
- package/ai/components/sunken-panel.md +79 -0
- package/ai/components/surface-scaffold.md +78 -0
- package/ai/components/tab-bar.md +112 -0
- package/ai/components/tab-scaffold.md +94 -0
- package/ai/components/tabs.md +95 -0
- package/ai/components/text.md +83 -0
- package/ai/components/token-search-field.md +103 -0
- package/ai/components/toolbar-control-group.md +102 -0
- package/ai/components/toolbar-text.md +78 -0
- package/ai/components/toolbar.md +97 -0
- package/ai/components/value-table.md +73 -0
- package/ai/components/wa-accordion-item.md +55 -0
- package/ai/components/wa-accordion.md +65 -0
- package/ai/components/wa-animated-image.md +55 -0
- package/ai/components/wa-animation.md +55 -0
- package/ai/components/wa-avatar.md +55 -0
- package/ai/components/wa-badge.md +55 -0
- package/ai/components/wa-breadcrumb-item.md +53 -0
- package/ai/components/wa-breadcrumb.md +55 -0
- package/ai/components/wa-button-group.md +59 -0
- package/ai/components/wa-button.md +55 -0
- package/ai/components/wa-callout.md +58 -0
- package/ai/components/wa-card.md +59 -0
- package/ai/components/wa-carousel-item.md +53 -0
- package/ai/components/wa-carousel.md +55 -0
- package/ai/components/wa-checkbox-group.md +55 -0
- package/ai/components/wa-checkbox.md +55 -0
- package/ai/components/wa-color-picker.md +55 -0
- package/ai/components/wa-comparison.md +55 -0
- package/ai/components/wa-copy-button.md +55 -0
- package/ai/components/wa-details.md +61 -0
- package/ai/components/wa-dialog.md +59 -0
- package/ai/components/wa-divider.md +53 -0
- package/ai/components/wa-drawer.md +55 -0
- package/ai/components/wa-dropdown-item.md +60 -0
- package/ai/components/wa-dropdown.md +60 -0
- package/ai/components/wa-format-bytes.md +53 -0
- package/ai/components/wa-format-date.md +53 -0
- package/ai/components/wa-format-number.md +53 -0
- package/ai/components/wa-icon.md +58 -0
- package/ai/components/wa-include.md +53 -0
- package/ai/components/wa-input.md +59 -0
- package/ai/components/wa-intersection-observer.md +53 -0
- package/ai/components/wa-known-date.md +53 -0
- package/ai/components/wa-markdown.md +53 -0
- package/ai/components/wa-mutation-observer.md +53 -0
- package/ai/components/wa-number-input.md +55 -0
- package/ai/components/wa-option.md +59 -0
- package/ai/components/wa-otp-input.md +53 -0
- package/ai/components/wa-page.md +53 -0
- package/ai/components/wa-pagination.md +55 -0
- package/ai/components/wa-popover.md +55 -0
- package/ai/components/wa-popup.md +53 -0
- package/ai/components/wa-progress-bar.md +53 -0
- package/ai/components/wa-progress-ring.md +53 -0
- package/ai/components/wa-qr-code.md +53 -0
- package/ai/components/wa-radio-group.md +59 -0
- package/ai/components/wa-radio.md +55 -0
- package/ai/components/wa-random-content.md +53 -0
- package/ai/components/wa-rating.md +55 -0
- package/ai/components/wa-relative-time.md +53 -0
- package/ai/components/wa-resize-observer.md +53 -0
- package/ai/components/wa-scroller.md +53 -0
- package/ai/components/wa-select.md +63 -0
- package/ai/components/wa-skeleton.md +53 -0
- package/ai/components/wa-slider.md +55 -0
- package/ai/components/wa-spinner.md +58 -0
- package/ai/components/wa-split-panel.md +58 -0
- package/ai/components/wa-switch.md +53 -0
- package/ai/components/wa-tab-group.md +69 -0
- package/ai/components/wa-tab-panel.md +60 -0
- package/ai/components/wa-tab.md +59 -0
- package/ai/components/wa-tag.md +59 -0
- package/ai/components/wa-textarea.md +53 -0
- package/ai/components/wa-time-input.md +55 -0
- package/ai/components/wa-toast-item.md +60 -0
- package/ai/components/wa-toast.md +60 -0
- package/ai/components/wa-tooltip.md +55 -0
- package/ai/components/wa-tree-item.md +55 -0
- package/ai/components/wa-tree.md +55 -0
- package/ai/components/wa-zoomable-frame.md +55 -0
- package/ai/components/workbench.md +114 -0
- package/ai/public-api-signatures-v1.md +2597 -190
- package/ai/skill.md +259 -65
- package/ai/webawesome-jsx-signatures-v1.md +9 -2
- package/analyzer/cli.mjs +49 -0
- package/analyzer/component-ownership.d.mts +56 -0
- package/analyzer/component-ownership.mjs +184 -0
- package/analyzer/index.d.mts +49 -0
- package/analyzer/index.mjs +1458 -0
- package/analyzer/loud-pairs.d.mts +49 -0
- package/analyzer/loud-pairs.mjs +357 -0
- package/analyzer/report.schema.json +66 -0
- package/analyzer/selectors.d.mts +21 -0
- package/analyzer/selectors.mjs +212 -0
- package/dist/app-tab.d.ts +41 -4
- package/dist/app-tab.js +3 -1
- package/dist/badge.d.ts +52 -0
- package/dist/badge.js +3 -0
- package/dist/badge.js.map +1 -0
- package/dist/browser/app-tab.js +1 -0
- package/dist/browser/badge.js +3 -0
- package/dist/browser/catalog.js +25 -0
- package/dist/browser/chip.js +3 -0
- package/dist/browser/collapsible-panel.js +7 -0
- package/dist/browser/content-item.js +3 -0
- package/dist/browser/floating-toolbar.js +3 -0
- package/dist/browser/grid.js +3 -0
- package/dist/browser/list-action-row.js +5 -0
- package/dist/browser/list-header.js +8 -0
- package/dist/browser/list-inset-control.js +3 -0
- package/dist/browser/list-inset-text.js +3 -0
- package/dist/browser/list-item.js +5 -0
- package/dist/browser/list.js +3 -0
- package/dist/browser/{panel-header.js → nav-stack.js} +4 -2
- package/dist/browser/pane.js +3 -0
- package/dist/browser/popup-menu.js +3 -0
- package/dist/browser/row.js +3 -0
- package/dist/browser/select.js +2 -0
- package/dist/browser/skeleton.js +3 -0
- package/dist/browser/spacer.js +3 -0
- package/dist/browser/split-view.js +10 -0
- package/dist/browser/state-banner.js +2 -0
- package/dist/browser/sunken-panel.js +3 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/browser/tab-scaffold.js +4 -0
- package/dist/browser/text.js +3 -0
- package/dist/browser/toolbar-text.js +1 -0
- package/dist/browser/value-table.js +1 -0
- package/dist/browser/workbench.js +10 -0
- package/dist/catalog-resources.d.ts +46 -0
- package/dist/catalog-resources.js +22 -0
- package/dist/catalog-resources.js.map +1 -0
- package/dist/catalog.d.ts +90 -0
- package/dist/catalog.js +501 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chip.d.ts +29 -0
- package/dist/chip.js +3 -0
- package/dist/chip.js.map +1 -0
- package/dist/chunk-2G2ZJQYK.js +152 -0
- package/dist/chunk-2G2ZJQYK.js.map +1 -0
- package/dist/chunk-3SXMEK3B.js +43 -0
- package/dist/chunk-3SXMEK3B.js.map +1 -0
- package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
- package/dist/chunk-4R777DUZ.js.map +1 -0
- package/dist/chunk-4SQK27MR.js +202 -0
- package/dist/chunk-4SQK27MR.js.map +1 -0
- package/dist/chunk-5I7QGQVT.js +24 -0
- package/dist/chunk-5I7QGQVT.js.map +1 -0
- package/dist/chunk-5PESG2VP.js +115 -0
- package/dist/chunk-5PESG2VP.js.map +1 -0
- package/dist/chunk-5Q3N6EV7.js +156 -0
- package/dist/chunk-5Q3N6EV7.js.map +1 -0
- package/dist/chunk-6ZXOQEAN.js +27 -0
- package/dist/chunk-6ZXOQEAN.js.map +1 -0
- package/dist/chunk-7JUBXOIV.js +103 -0
- package/dist/chunk-7JUBXOIV.js.map +1 -0
- package/dist/chunk-A3CKOW2R.js +622 -0
- package/dist/chunk-A3CKOW2R.js.map +1 -0
- package/dist/chunk-AHEG27M7.js +66 -0
- package/dist/chunk-AHEG27M7.js.map +1 -0
- package/dist/chunk-AUKT3KMG.js +37 -0
- package/dist/chunk-AUKT3KMG.js.map +1 -0
- package/dist/chunk-AYUHMAI6.js +48 -0
- package/dist/chunk-AYUHMAI6.js.map +1 -0
- package/dist/chunk-BFPBS5Y4.js +250 -0
- package/dist/chunk-BFPBS5Y4.js.map +1 -0
- package/dist/{chunk-MQIZAD4A.js → chunk-C4OYOKWX.js} +138 -22
- package/dist/chunk-C4OYOKWX.js.map +1 -0
- package/dist/chunk-DG6G5EPF.js +35 -0
- package/dist/chunk-DG6G5EPF.js.map +1 -0
- package/dist/chunk-E36EVCKG.js +34 -0
- package/dist/chunk-E36EVCKG.js.map +1 -0
- package/dist/chunk-EAC4CDY7.js +57 -0
- package/dist/chunk-EAC4CDY7.js.map +1 -0
- package/dist/chunk-EZVNC4J6.js +104 -0
- package/dist/chunk-EZVNC4J6.js.map +1 -0
- package/dist/chunk-F4QMLOXJ.js +135 -0
- package/dist/chunk-F4QMLOXJ.js.map +1 -0
- package/dist/chunk-GLDWRCAM.js +49 -0
- package/dist/chunk-GLDWRCAM.js.map +1 -0
- package/dist/chunk-I3Q7KKYM.js +33 -0
- package/dist/chunk-I3Q7KKYM.js.map +1 -0
- package/dist/chunk-IA7TMD4Y.js +288 -0
- package/dist/chunk-IA7TMD4Y.js.map +1 -0
- package/dist/chunk-JCV4GXWB.js +249 -0
- package/dist/chunk-JCV4GXWB.js.map +1 -0
- package/dist/chunk-K47P7QZC.js +17 -0
- package/dist/chunk-K47P7QZC.js.map +1 -0
- package/dist/chunk-KLJKU6ZL.js +109 -0
- package/dist/chunk-KLJKU6ZL.js.map +1 -0
- package/dist/{chunk-56RJXPHG.js → chunk-KROD7KZK.js} +7 -4
- package/dist/chunk-KROD7KZK.js.map +1 -0
- package/dist/chunk-MA73TA6D.js +42 -0
- package/dist/chunk-MA73TA6D.js.map +1 -0
- package/dist/chunk-MERWRTBG.js +45 -0
- package/dist/chunk-MERWRTBG.js.map +1 -0
- package/dist/chunk-MEY33VWB.js +44 -0
- package/dist/chunk-MEY33VWB.js.map +1 -0
- package/dist/chunk-MP2GDBQZ.js +50 -0
- package/dist/chunk-MP2GDBQZ.js.map +1 -0
- package/dist/chunk-N3GKMPDW.js +51 -0
- package/dist/chunk-N3GKMPDW.js.map +1 -0
- package/dist/chunk-NAPE7WUS.js +75 -0
- package/dist/chunk-NAPE7WUS.js.map +1 -0
- package/dist/chunk-NN6GYOA2.js +47 -0
- package/dist/chunk-NN6GYOA2.js.map +1 -0
- package/dist/chunk-NNMLEDMD.js +399 -0
- package/dist/chunk-NNMLEDMD.js.map +1 -0
- package/dist/chunk-NYL63PSD.js +95 -0
- package/dist/chunk-NYL63PSD.js.map +1 -0
- package/dist/chunk-P7D3EMXM.js +52 -0
- package/dist/chunk-P7D3EMXM.js.map +1 -0
- package/dist/chunk-PSHUSWQH.js +18 -0
- package/dist/chunk-PSHUSWQH.js.map +1 -0
- package/dist/chunk-Q6YU3BT7.js +138 -0
- package/dist/chunk-Q6YU3BT7.js.map +1 -0
- package/dist/chunk-RRB26JRJ.js +247 -0
- package/dist/chunk-RRB26JRJ.js.map +1 -0
- package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-SWVW56CV.js +188 -0
- package/dist/chunk-SWVW56CV.js.map +1 -0
- package/dist/chunk-TEYARRAK.js +216 -0
- package/dist/chunk-TEYARRAK.js.map +1 -0
- package/dist/chunk-UCKKT6KO.js +71 -0
- package/dist/chunk-UCKKT6KO.js.map +1 -0
- package/dist/chunk-UIDKY4UB.js +14 -0
- package/dist/chunk-UIDKY4UB.js.map +1 -0
- package/dist/chunk-VCBTX62E.js +135 -0
- package/dist/chunk-VCBTX62E.js.map +1 -0
- package/dist/chunk-VZOFZPSO.js +71 -0
- package/dist/chunk-VZOFZPSO.js.map +1 -0
- package/dist/{chunk-TRNBHPNW.js → chunk-X5QSICJ3.js} +13 -7
- package/dist/chunk-X5QSICJ3.js.map +1 -0
- package/dist/chunk-Y74NWGQW.js +418 -0
- package/dist/chunk-Y74NWGQW.js.map +1 -0
- package/dist/chunk-ZLWQZUGF.js +27 -0
- package/dist/chunk-ZLWQZUGF.js.map +1 -0
- package/dist/collapsible-panel.d.ts +122 -0
- package/dist/collapsible-panel.js +115 -0
- package/dist/collapsible-panel.js.map +1 -0
- package/dist/content-item.d.ts +46 -0
- package/dist/content-item.js +4 -0
- package/dist/content-item.js.map +1 -0
- package/dist/css-values.d.ts +107 -0
- package/dist/css-values.js +3 -0
- package/dist/css-values.js.map +1 -0
- package/dist/device-class.js +33 -5
- package/dist/device-class.js.map +1 -1
- package/dist/disclosure-arrow.d.ts +6 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.d.ts +5 -2
- package/dist/empty-state.js +1 -1
- package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
- package/dist/floating-toolbar.d.ts +51 -0
- package/dist/floating-toolbar.js +3 -0
- package/dist/floating-toolbar.js.map +1 -0
- package/dist/grid.d.ts +42 -0
- package/dist/grid.js +5 -0
- package/dist/grid.js.map +1 -0
- package/dist/help-tags-register.d.ts +13 -0
- package/dist/help-tags-register.js +9 -0
- package/dist/help-tags-register.js.map +1 -0
- package/dist/index.d.ts +35 -14
- package/dist/index.js +43 -22
- package/dist/list-action-row.d.ts +64 -0
- package/dist/list-action-row.js +8 -0
- package/dist/list-action-row.js.map +1 -0
- package/dist/list-header.d.ts +99 -0
- package/dist/list-header.js +10 -0
- package/dist/list-header.js.map +1 -0
- package/dist/list-inset-control.d.ts +22 -0
- package/dist/list-inset-control.js +3 -0
- package/dist/list-inset-control.js.map +1 -0
- package/dist/list-inset-text.d.ts +30 -0
- package/dist/list-inset-text.js +4 -0
- package/dist/list-inset-text.js.map +1 -0
- package/dist/list-item.d.ts +62 -0
- package/dist/list-item.js +8 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list.d.ts +59 -0
- package/dist/list.js +6 -0
- package/dist/list.js.map +1 -0
- package/dist/loading-spinner.d.ts +3 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/lucide-icon.d.ts +3 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/nav-stack.d.ts +60 -10
- package/dist/nav-stack.js +6 -1
- package/dist/pane.d.ts +102 -0
- package/dist/pane.js +4 -0
- package/dist/pane.js.map +1 -0
- package/dist/panel-toolbar-DqwtBxQL.d.ts +63 -0
- package/dist/popup-menu-register.d.ts +9 -0
- package/dist/popup-menu-register.js +31 -0
- package/dist/popup-menu-register.js.map +1 -0
- package/dist/popup-menu.d.ts +99 -0
- package/dist/popup-menu.js +3 -0
- package/dist/popup-menu.js.map +1 -0
- package/dist/resizable-region.d.ts +32 -3
- package/dist/resizable-region.js +1 -1
- package/dist/row.d.ts +48 -0
- package/dist/row.js +6 -0
- package/dist/row.js.map +1 -0
- package/dist/segmented-control.d.ts +13 -8
- package/dist/segmented-control.js +1 -1
- package/dist/select-register.d.ts +5 -1
- package/dist/select-register.js +243 -2
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +101 -8
- package/dist/select.js +4 -1
- package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
- package/dist/sides-BPSWde0A.d.ts +4 -0
- package/dist/skeleton.d.ts +31 -0
- package/dist/skeleton.js +4 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/spacer.d.ts +18 -0
- package/dist/spacer.js +4 -0
- package/dist/spacer.js.map +1 -0
- package/dist/split-view.d.ts +39 -7
- package/dist/split-view.js +120 -10
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +19 -5
- package/dist/state-banner.js +4 -1
- package/dist/styles/app-tab.css +104 -0
- package/dist/styles/badge.css +118 -0
- package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
- package/dist/styles/catalog/components/catalog-example.css +164 -0
- package/dist/styles/catalog/components/catalog-stage.css +55 -0
- package/dist/styles/catalog/components/catalog.css +12 -0
- package/dist/styles/catalog.css +5 -0
- package/dist/styles/chip.css +118 -0
- package/dist/styles/collapsible-panel.css +575 -0
- package/dist/styles/content-item.css +30 -0
- package/dist/styles/document.css +23 -0
- package/dist/styles/floating-toolbar.css +119 -0
- package/dist/styles/foundation.css +178 -40
- package/dist/styles/grid.css +28 -0
- package/dist/styles/layout.css +3 -41
- package/dist/styles/list-action-row.css +257 -0
- package/dist/styles/list-header.css +228 -0
- package/dist/styles/list-inset-control.css +30 -0
- package/dist/styles/list-inset-text.css +29 -0
- package/dist/styles/list-item.css +245 -0
- package/dist/styles/list.css +133 -0
- package/dist/styles/nav-stack.css +158 -50
- package/dist/styles/pane.css +229 -0
- package/dist/styles/popup-menu.css +271 -0
- package/dist/styles/resizable-region.css +429 -4
- package/dist/styles/row.css +111 -0
- package/dist/styles/segmented-control.css +33 -9
- package/dist/styles/select.css +262 -9
- package/dist/styles/skeleton.css +92 -0
- package/dist/styles/spacer.css +11 -0
- package/dist/styles/split-view.css +108 -3
- package/dist/styles/state-banner.css +94 -19
- package/dist/styles/styles.css +14 -4
- package/dist/styles/sunken-panel.css +22 -0
- package/dist/styles/surface-scaffold.css +56 -0
- package/dist/styles/tab-bar.css +132 -9
- package/dist/styles/tab-scaffold.css +113 -3
- package/dist/styles/text.css +65 -0
- package/dist/styles/token-search-field.css +49 -43
- package/dist/styles/toolbar-control-group.css +465 -28
- package/dist/styles/toolbar-text.css +88 -4
- package/dist/styles/toolbar.css +322 -11
- package/dist/styles/value-table.css +34 -4
- package/dist/styles/webawesome.css +348 -10
- package/dist/styles/workbench.css +828 -7
- package/dist/sunken-panel.d.ts +22 -0
- package/dist/sunken-panel.js +3 -0
- package/dist/sunken-panel.js.map +1 -0
- package/dist/surface-scaffold.d.ts +30 -0
- package/dist/surface-scaffold.js +3 -0
- package/dist/surface-scaffold.js.map +1 -0
- package/dist/tab-bar.d.ts +31 -6
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +54 -7
- package/dist/tab-scaffold.js +82 -9
- package/dist/tab-scaffold.js.map +1 -1
- package/dist/text.d.ts +38 -0
- package/dist/text.js +3 -0
- package/dist/text.js.map +1 -0
- package/dist/token-search-field-DvgFLhLL.d.ts +130 -0
- package/dist/token-search-field.d.ts +3 -43
- package/dist/token-search-field.js +1 -1
- package/dist/token-search-model.d.ts +3 -0
- package/dist/token-search-model.js +3 -0
- package/dist/token-search-model.js.map +1 -0
- package/dist/toolbar-control-group.d.ts +65 -7
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +37 -4
- package/dist/toolbar-text.js +3 -1
- package/dist/toolbar.d.ts +56 -7
- package/dist/toolbar.js +1 -1
- package/dist/types-BuHELdXR.d.ts +117 -0
- package/dist/value-table.d.ts +13 -3
- package/dist/value-table.js +3 -1
- package/dist/webawesome.d.ts +8 -1
- package/dist/wire-catalog.d.ts +82 -0
- package/dist/wire-catalog.js +327 -0
- package/dist/wire-catalog.js.map +1 -0
- package/dist/wire-nav-stack.d.ts +4 -1
- package/dist/wire-nav-stack.js +147 -7
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-resizable-regions.d.ts +2 -1
- package/dist/wire-resizable-regions.js +2 -1
- package/dist/wire-scroll-dividers.d.ts +69 -0
- package/dist/wire-scroll-dividers.js +3 -0
- package/dist/wire-scroll-dividers.js.map +1 -0
- package/dist/wire-sidebar.d.ts +63 -0
- package/dist/wire-sidebar.js +231 -0
- package/dist/wire-sidebar.js.map +1 -0
- package/dist/wire-tab-bars.d.ts +19 -2
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-scaffold.js +9 -4
- package/dist/wire-tab-scaffold.js.map +1 -1
- package/dist/wire-token-search-fields.d.ts +65 -3
- 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 +218 -7
- package/dist/workbench.js +13 -15
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +413 -23
- package/docs/app-layouts.md +106 -8
- package/docs/catalog.md +440 -0
- package/docs/collapsible-panel.md +363 -0
- package/docs/component-contract.md +560 -52
- package/docs/component-integration.md +75 -0
- package/docs/component-selection.md +421 -89
- package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
- package/docs/design/templates/empty-state/filtered.svg +1 -0
- package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
- package/docs/design/templates/empty-state/with-action.svg +1 -0
- package/docs/design/templates/empty-state-dark.svg +1 -0
- package/docs/design/templates/empty-state.svg +1 -0
- package/docs/design/templates/list/compact-dark.svg +1 -0
- package/docs/design/templates/list/compact.svg +1 -0
- package/docs/design/templates/list/stack-dark.svg +1 -0
- package/docs/design/templates/list/stack.svg +1 -0
- package/docs/design/templates/list-action-row/default-dark.svg +1 -0
- package/docs/design/templates/list-action-row/default.svg +1 -0
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
- package/docs/design/templates/list-action-row/selected.svg +1 -0
- package/docs/design/templates/list-action-row-dark.svg +1 -0
- package/docs/design/templates/list-action-row.svg +1 -0
- package/docs/design/templates/list-dark.svg +1 -0
- package/docs/design/templates/list-header/action-dark.svg +1 -0
- package/docs/design/templates/list-header/action.svg +1 -0
- package/docs/design/templates/list-header/count-dark.svg +1 -0
- package/docs/design/templates/list-header/count.svg +1 -0
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
- package/docs/design/templates/list-header/inline-action.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
- package/docs/design/templates/list-header-dark.svg +1 -0
- package/docs/design/templates/list-header.svg +1 -0
- package/docs/design/templates/list-item/default-dark.svg +1 -0
- package/docs/design/templates/list-item/default.svg +1 -0
- package/docs/design/templates/list-item/multiline-dark.svg +1 -0
- package/docs/design/templates/list-item/multiline.svg +1 -0
- package/docs/design/templates/list-item/selected-dark.svg +1 -0
- package/docs/design/templates/list-item/selected.svg +1 -0
- package/docs/design/templates/list-item/trailing-dark.svg +1 -0
- package/docs/design/templates/list-item/trailing.svg +1 -0
- package/docs/design/templates/list-item-dark.svg +1 -0
- package/docs/design/templates/list-item.svg +1 -0
- package/docs/design/templates/list.svg +1 -0
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
- package/docs/design/templates/segmented-control/equal.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small.svg +1 -0
- package/docs/design/templates/segmented-control-dark.svg +1 -0
- package/docs/design/templates/segmented-control.svg +1 -0
- package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
- package/docs/design/templates/skeleton/avatar.svg +1 -0
- package/docs/design/templates/skeleton/block-dark.svg +1 -0
- package/docs/design/templates/skeleton/block.svg +1 -0
- package/docs/design/templates/skeleton/lines-dark.svg +1 -0
- package/docs/design/templates/skeleton/lines.svg +1 -0
- package/docs/design/templates/skeleton-dark.svg +1 -0
- package/docs/design/templates/skeleton.svg +1 -0
- package/docs/design/templates/state-banner/danger-dark.svg +1 -0
- package/docs/design/templates/state-banner/danger.svg +1 -0
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
- package/docs/design/templates/state-banner/info-badge.svg +1 -0
- package/docs/design/templates/state-banner/info-dark.svg +1 -0
- package/docs/design/templates/state-banner/info.svg +1 -0
- package/docs/design/templates/state-banner/success-dark.svg +1 -0
- package/docs/design/templates/state-banner/success.svg +1 -0
- package/docs/design/templates/state-banner/warning-dark.svg +1 -0
- package/docs/design/templates/state-banner/warning.svg +1 -0
- package/docs/design/templates/state-banner-dark.svg +1 -0
- package/docs/design/templates/state-banner.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
- package/docs/design/templates/tab-bar-dark.svg +1 -0
- package/docs/design/templates/tab-bar.svg +1 -0
- package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
- package/docs/design/templates/token-search-field/empty.svg +1 -0
- package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
- package/docs/design/templates/token-search-field/tokens.svg +1 -0
- package/docs/design/templates/token-search-field-dark.svg +1 -0
- package/docs/design/templates/token-search-field.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group.svg +1 -0
- package/docs/design/templates/toolbar-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default.svg +1 -0
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/large.svg +1 -0
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/small.svg +1 -0
- package/docs/design/templates/toolbar-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-text.svg +1 -0
- package/docs/design/templates/toolbar.svg +1 -0
- package/docs/design/templates/value-table/details-dark.svg +1 -0
- package/docs/design/templates/value-table/details.svg +1 -0
- package/docs/design/templates/value-table-dark.svg +1 -0
- package/docs/design/templates/value-table.svg +1 -0
- package/docs/design/templates.md +138 -0
- package/docs/design-philosophy.md +48 -20
- package/docs/device-class.md +10 -9
- package/docs/document-baseline.md +38 -0
- package/docs/examples/application-ui-profile.json +60 -0
- package/docs/examples/command-palette-adapter.tsx +69 -17
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/examples/component-composition-extension.json +80 -0
- package/docs/layout.md +409 -59
- package/docs/nav-stack.md +126 -14
- package/docs/recipes.md +137 -54
- package/docs/split-view.md +69 -6
- package/docs/sunken-panel.md +58 -0
- package/docs/surface-scaffold.md +25 -0
- package/docs/tab-scaffold.md +94 -10
- package/docs/type-contracts.md +134 -0
- package/docs/ui-analyzer.md +306 -0
- package/docs/ui-doctor.md +107 -0
- package/docs/ui-evaluator.md +139 -0
- package/docs/ux-demo.md +40 -16
- package/docs/webawesome-theme.md +175 -16
- package/docs/workbench.md +534 -12
- package/doctor/cli.mjs +115 -0
- package/doctor/config.schema.json +68 -0
- package/doctor/eslint-diagnostics.d.mts +24 -0
- package/doctor/eslint-diagnostics.mjs +24 -0
- package/doctor/index.d.mts +116 -0
- package/doctor/index.mjs +1277 -0
- package/doctor/report.schema.json +118 -0
- package/evaluator/cli.mjs +89 -0
- package/evaluator/index.d.mts +90 -0
- package/evaluator/index.mjs +1203 -0
- package/evaluator/report.schema.json +152 -0
- package/llms.txt +423 -42
- package/package.json +241 -37
- package/traversal-exclusions.mjs +27 -0
- package/ux-demo/recipes/app-shell.tsx +205 -17
- package/ux-demo/recipes/collapsible-sidebar.tsx +260 -0
- package/ux-demo/recipes/compact-toolbar.tsx +135 -14
- package/ux-demo/recipes/composer-form.tsx +133 -21
- package/ux-demo/recipes/list-detail-dialog.tsx +282 -0
- package/ux-demo/recipes/list-workspace-states.tsx +183 -11
- package/ux-demo/recipes/loaders.ts +15 -5
- package/ux-demo/recipes/loading-inspector.tsx +204 -0
- package/ux-demo/recipes/mount-recipe.ts +28 -10
- package/ux-demo/recipes/navigation-sidebar.tsx +139 -13
- package/ux-demo/recipes/navigation-stack.tsx +79 -24
- package/ux-demo/recipes/types.ts +23 -2
- package/ux-demo/recipes/workspace-header.tsx +86 -5
- package/dist/browser/menu-action-row.js +0 -3
- package/dist/browser/menu-header.js +0 -5
- package/dist/browser/menu-item.js +0 -3
- package/dist/chunk-24Z2XE6C.js +0 -10
- package/dist/chunk-24Z2XE6C.js.map +0 -1
- package/dist/chunk-2RJBFNB6.js +0 -172
- package/dist/chunk-2RJBFNB6.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-56RJXPHG.js.map +0 -1
- package/dist/chunk-7BR3DO2A.js.map +0 -1
- package/dist/chunk-7LDCTU7D.js +0 -134
- package/dist/chunk-7LDCTU7D.js.map +0 -1
- package/dist/chunk-AQNKJRFH.js +0 -79
- package/dist/chunk-AQNKJRFH.js.map +0 -1
- package/dist/chunk-CTQKI2XL.js +0 -28
- package/dist/chunk-CTQKI2XL.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-EGHL5S4P.js +0 -33
- package/dist/chunk-EGHL5S4P.js.map +0 -1
- package/dist/chunk-KZKSBUKC.js +0 -19
- package/dist/chunk-KZKSBUKC.js.map +0 -1
- package/dist/chunk-M5JRI6MN.js +0 -27
- package/dist/chunk-M5JRI6MN.js.map +0 -1
- package/dist/chunk-MBR3TYNL.js +0 -14
- package/dist/chunk-MBR3TYNL.js.map +0 -1
- package/dist/chunk-MFKMHK5W.js +0 -10
- package/dist/chunk-MFKMHK5W.js.map +0 -1
- package/dist/chunk-MQIZAD4A.js.map +0 -1
- package/dist/chunk-NPPD2A6O.js +0 -40
- package/dist/chunk-NPPD2A6O.js.map +0 -1
- package/dist/chunk-R6JHHBKQ.js +0 -19
- package/dist/chunk-R6JHHBKQ.js.map +0 -1
- package/dist/chunk-RBTVBGRD.js +0 -23
- package/dist/chunk-RBTVBGRD.js.map +0 -1
- package/dist/chunk-S3TPM2LP.js +0 -23
- package/dist/chunk-S3TPM2LP.js.map +0 -1
- package/dist/chunk-TRNBHPNW.js.map +0 -1
- package/dist/chunk-VHW5YNIB.js +0 -17
- package/dist/chunk-VHW5YNIB.js.map +0 -1
- package/dist/chunk-W2FK7ZNY.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-XZXRLY5Q.js +0 -33
- package/dist/chunk-XZXRLY5Q.js.map +0 -1
- package/dist/menu-action-row.d.ts +0 -50
- package/dist/menu-action-row.js +0 -4
- package/dist/menu-action-row.js.map +0 -1
- package/dist/menu-header.d.ts +0 -41
- package/dist/menu-header.js +0 -6
- package/dist/menu-header.js.map +0 -1
- package/dist/menu-item.d.ts +0 -31
- package/dist/menu-item.js +0 -4
- package/dist/menu-item.js.map +0 -1
- package/dist/panel-header.d.ts +0 -26
- package/dist/panel-header.js +0 -6
- package/dist/panel-header.js.map +0 -1
- package/dist/styles/menu-action-row.css +0 -160
- package/dist/styles/menu-header.css +0 -160
- package/dist/styles/menu-item.css +0 -123
- package/dist/styles/panel-header.css +0 -59
- package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
- package/ux-demo/recipes/recipes.css +0 -355
package/docs/workbench.md
CHANGED
|
@@ -8,15 +8,42 @@ sidebar. One of the opt-in app layouts (see
|
|
|
8
8
|
desktop-class devices.
|
|
9
9
|
|
|
10
10
|
```ts
|
|
11
|
-
import { Workbench } from
|
|
12
|
-
import '@kerfjs/ui/workbench.css';
|
|
11
|
+
import { Workbench } from "@kerfjs/ui/workbench";
|
|
13
12
|
```
|
|
14
13
|
|
|
14
|
+
In a browser bundler that honors the `browser` export condition (Vite, esbuild, and
|
|
15
|
+
webpack do by default), the import above also
|
|
16
|
+
loads Workbench's stylesheet and those of the components it renders internally
|
|
17
|
+
(`Pane`, `Toolbar`, `ToolbarControlGroup`, `FloatingToolbar`, `ResizableRegion`,
|
|
18
|
+
`List`, `LucideIcon`). Without that condition, import the manual stylesheets instead:
|
|
19
|
+
`@kerfjs/ui/workbench.css` plus those components' CSS, or `@kerfjs/ui/styles.css`.
|
|
20
|
+
|
|
21
|
+
A top-level `Workbench` needs a definite containing height. Import the opt-in
|
|
22
|
+
`@kerfjs/ui/document.css` baseline and add `.kui-app-root` to the direct mount
|
|
23
|
+
container, or provide an equivalent definite height in application-owned
|
|
24
|
+
layout. The component intentionally uses `height: 100%` rather than `100dvh` so
|
|
25
|
+
it can also be embedded. See [Document baseline](document-baseline.md).
|
|
26
|
+
|
|
15
27
|
## State lives in the app
|
|
16
28
|
|
|
17
29
|
`Workbench` is declarative and the collapse is **pure CSS** — no wire. The app
|
|
18
30
|
owns each panel's `collapsed` flag (usually a signal) and toggles it; the panel
|
|
19
|
-
animates itself.
|
|
31
|
+
animates itself. Panels are fixed-size by default; a panel can opt in to drag
|
|
32
|
+
and keyboard resizing (see [Resizable panels](#resizable-panels)), and
|
|
33
|
+
`wireWorkbench` can make overlay panels transient (see
|
|
34
|
+
[Transient overlays](#transient-overlays)).
|
|
35
|
+
|
|
36
|
+
A collapsed panel renders `inert` and `aria-hidden="true"` on the rail or
|
|
37
|
+
drawer itself, and `inert` on its content, straight from `collapsed`, so
|
|
38
|
+
neither Tab nor assistive technology reaches controls that have slid out of
|
|
39
|
+
view, none of them can scroll back into view, and no empty labeled landmark
|
|
40
|
+
stays behind. The slide-out still animates,
|
|
41
|
+
and the panel's `restoreControl` lives outside the inert content, so it stays
|
|
42
|
+
reachable. Expanding the panel makes its content reachable again in the same
|
|
43
|
+
render. When the panel closes with focus inside it, `wireWorkbench` (given the
|
|
44
|
+
panel's `collapsed` signal) moves focus back out (see
|
|
45
|
+
[Transient overlays](#transient-overlays)); without it, that focus move is the
|
|
46
|
+
app's.
|
|
20
47
|
|
|
21
48
|
```tsx
|
|
22
49
|
const navCollapsed = signal(false);
|
|
@@ -25,23 +52,518 @@ const navCollapsed = signal(false);
|
|
|
25
52
|
id="studio"
|
|
26
53
|
label="Studio"
|
|
27
54
|
main={<Editor />}
|
|
28
|
-
leftRail={{
|
|
29
|
-
|
|
30
|
-
|
|
55
|
+
leftRail={{
|
|
56
|
+
content: <Navigator />,
|
|
57
|
+
label: "Navigator",
|
|
58
|
+
collapsed: navCollapsed.value,
|
|
59
|
+
size: 280,
|
|
60
|
+
}}
|
|
61
|
+
rightRail={{
|
|
62
|
+
content: <Inspector />,
|
|
63
|
+
label: "Inspector",
|
|
64
|
+
collapsed: inspectorCollapsed.value,
|
|
65
|
+
}}
|
|
66
|
+
bottomDrawer={{
|
|
67
|
+
content: <Console />,
|
|
68
|
+
label: "Console",
|
|
69
|
+
collapsed: consoleCollapsed.value,
|
|
70
|
+
}}
|
|
31
71
|
/>;
|
|
32
72
|
```
|
|
33
73
|
|
|
34
|
-
Each `WorkbenchPanel` takes `content`, an optional `
|
|
74
|
+
Each `WorkbenchPanel` takes `content`, an optional `toolbar` and `footer` (see
|
|
75
|
+
[Panel toolbars](#panel-toolbars)), an optional `collapsed`, an optional
|
|
35
76
|
`size` (rail width or drawer height in px, overriding the CSS default —
|
|
36
77
|
`--kui-workbench-rail-width` 280px, `--kui-workbench-drawer-height` 220px), and
|
|
37
|
-
an optional `label`.
|
|
78
|
+
an optional `label`. Common shell behavior is configured rather than restyled:
|
|
79
|
+
|
|
80
|
+
- `separator: "auto" | "hidden"` controls the owned dock-edge separator;
|
|
81
|
+
- `collapseMotion: "slide" | "fade-slide" | "none"` keeps the track change
|
|
82
|
+
instant while choosing composited content motion;
|
|
83
|
+
- `contentOverflow: "clip" | "auto" | "visible"` lets a drawer temporarily
|
|
84
|
+
expose an open popup without a descendant override;
|
|
85
|
+
- `presentation: "inline" | "overlay" | "hidden"` supports compact overlays
|
|
86
|
+
or a responsive replacement. An overlay rail spans the Workbench height at
|
|
87
|
+
its side and an overlay drawer spans the work-area column at the bottom,
|
|
88
|
+
each exactly at its configured size (its separator border included, as in
|
|
89
|
+
flow) up to the viewport-relative overlay maximum; the content fills the
|
|
90
|
+
panel inside its border, so it is clamped with it;
|
|
91
|
+
- `responsiveOverlayAt: "narrow" | "compact" | "never"` presents a rail or the
|
|
92
|
+
bottom drawer as an overlay below a Workbench container breakpoint — 704px
|
|
93
|
+
or less for `narrow`, 448px or less for `compact`, the breakpoints of
|
|
94
|
+
`ResizableRegion`'s `responsiveFillAt` — and inline above it. **Rails
|
|
95
|
+
default to `narrow`**, so on a small screen a sidebar covers the work area
|
|
96
|
+
(and an open drawer) instead of squeezing it; pass `never` to keep a rail
|
|
97
|
+
inline. The drawer stays inline unless it opts in. On a compact (448px or
|
|
98
|
+
less) Workbench an overlay rail fills the Workbench less a dismiss strip on
|
|
99
|
+
the side away from its edge — `--kui-workbench-overlay-dismiss-margin`,
|
|
100
|
+
44px, one touch target — so a press beside it closes it;
|
|
101
|
+
`compactOverlay: "full"` (per rail) fills the Workbench instead, which
|
|
102
|
+
usually wants app-level handling of its own. Pass each rail's `collapsed`
|
|
103
|
+
signal to `wireWorkbench` so only one overlay is open at a time and a press
|
|
104
|
+
outside closes it. The CSS
|
|
105
|
+
decides, so the app needs no `deviceClass` check for presentation; a
|
|
106
|
+
collapsed overlay drops its surface and shadow so nothing covers the work
|
|
107
|
+
area, and the work area keeps the safe-area inset of the edge the overlay
|
|
108
|
+
covers. When overlays meet, the order is fixed rather than by which opened
|
|
109
|
+
last: both rails stack above the drawer, as inline rails span the
|
|
110
|
+
Workbench's full height beside the drawer's column, and the right rail
|
|
111
|
+
stacks above the left. Rails take `--kui-workbench-overlay-z` (41) and the
|
|
112
|
+
drawer one less. Restore controls take `--kui-workbench-restore-z`, which
|
|
113
|
+
defaults to two less than the overlay z-index (39), so they sit beneath
|
|
114
|
+
every overlay: an open overlay covers another panel's restore control as
|
|
115
|
+
it covers the rest of the work area, and a collapsed overlay, which drops
|
|
116
|
+
its pointer events, leaves the control beneath it usable. While a rail
|
|
117
|
+
overlay is open (static, or a responsive one whose breakpoint applies), the
|
|
118
|
+
work area's floating controls — restore corners and any `FloatingToolbar`
|
|
119
|
+
in `main` — are also hidden outright (out of the tab order and the
|
|
120
|
+
accessibility tree), so they can never paint over the rail whatever
|
|
121
|
+
stacking context the app gives the work area; they return as it closes.
|
|
122
|
+
The rail's own floating controls stay, and a drawer overlay hides nothing;
|
|
123
|
+
- `restoreControl` places an application-owned restore affordance in a
|
|
124
|
+
corner of the Workbench itself while the panel is collapsed. Prefer a
|
|
125
|
+
`toolbar.toggle`, which the Workbench relocates for you; keep
|
|
126
|
+
`restoreControl` for a custom affordance. `restorePosition` chooses the
|
|
127
|
+
corner, inset by
|
|
128
|
+
`--kui-workbench-restore-inset` (16px) plus the unsafe area of each edge the
|
|
129
|
+
corner reaches. A rail's control sits in the Workbench's corner; the
|
|
130
|
+
drawer's sits in the corner of the work-area column it restores into, so it
|
|
131
|
+
never lands on an expanded rail. A collapsed rail's control floats the
|
|
132
|
+
same inset above the top edge of an expanded inline bottom drawer, which
|
|
133
|
+
spans the column reaching that corner once the rail collapses, so it never
|
|
134
|
+
covers the drawer's content; it returns to the corner when the drawer
|
|
135
|
+
collapses (the drawer publishes its edge as a CSS anchor scoped to its own
|
|
136
|
+
Workbench; without anchor positioning the control keeps the corner). An
|
|
137
|
+
overlay drawer publishes no edge: an open one covers the control, as every
|
|
138
|
+
open overlay does. Because it is anchored to the Workbench
|
|
139
|
+
rather than the viewport, an embedded Workbench never floats it over page
|
|
140
|
+
chrome outside it, and it scrolls with the Workbench. Compose it from the
|
|
141
|
+
package controls — a `single` `ToolbarControlGroup` around one icon button
|
|
142
|
+
carrying `collapsiblePanelToggleIcon(side, true)` — rather than a bare
|
|
143
|
+
button. To give it `FloatingToolbar`'s toolbar role and floating look, wrap
|
|
144
|
+
that group in a `FloatingToolbar` whose `position` matches the corner: the
|
|
145
|
+
corner owns the inset (it zeroes the toolbar's default inset), so omit
|
|
146
|
+
`inset` there and the toolbar floats from the corner instead of doubling it.
|
|
147
|
+
|
|
148
|
+
- `resizable: true | { min, max }` opts the panel in to drag and keyboard
|
|
149
|
+
resizing, driven by `wireWorkbench` (off by default).
|
|
150
|
+
|
|
151
|
+
The same policy props are available on `ResizableRegion` and
|
|
152
|
+
`CollapsiblePanel`, so a resizable application shell does not need to reach
|
|
153
|
+
into `.kui-resizable-region__content`.
|
|
154
|
+
|
|
155
|
+
## Panel toolbars
|
|
156
|
+
|
|
157
|
+
A panel's controls follow it open and closed when the Workbench composes the
|
|
158
|
+
toolbars. Give a panel a `toolbar` and the work area a `mainToolbar` (and, for
|
|
159
|
+
a drawer, optionally a `mainBottomToolbar`); the Workbench renders each as a
|
|
160
|
+
standard `Toolbar` over a `Pane`, and moves groups between them as panels open
|
|
161
|
+
and close. A panel's `toolbar` has these parts:
|
|
162
|
+
|
|
163
|
+
- `title` — the panel's `ToolbarText` (the quiet default size in a rail).
|
|
164
|
+
- `leading`, `center`, and `trailing` — the open panel's toolbar zones. Put
|
|
165
|
+
`ToolbarControlGroup`s in any order in these zones. Mark a group with
|
|
166
|
+
`relocateOnCollapse` to make it available in the work area while the panel
|
|
167
|
+
is closed; unmarked groups remain in the inert panel. Pass marked groups
|
|
168
|
+
directly or in arrays, including nested arrays, rather than JSX fragments
|
|
169
|
+
so their render-time annotation remains available.
|
|
170
|
+
- `toggle: { action, name, showLabel?, hideLabel? }` — the standard collapse
|
|
171
|
+
toggle, which the Workbench renders: the per-side panel glyph,
|
|
172
|
+
`aria-controls` naming the panel, `aria-expanded`, a "Show …"/"Hide …"
|
|
173
|
+
label (or your localized `showLabel` / `hideLabel`), and the `data-action`
|
|
174
|
+
the app handles. It is always the last group.
|
|
175
|
+
|
|
176
|
+
While a panel is closed, marked groups follow their open-panel zone order
|
|
177
|
+
(`leading`, `center`, `trailing`), followed by its toggle:
|
|
178
|
+
|
|
179
|
+
| Panel | Where they go |
|
|
180
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
181
|
+
| Left rail | The leading edge of `mainToolbar`, before its `title` |
|
|
182
|
+
| Right rail | The trailing edge of `mainToolbar`, after its `trailing` groups, so the toggle is the toolbar's last group |
|
|
183
|
+
| Bottom drawer | The trailing edge of `mainBottomToolbar`; without one, a `FloatingToolbar` in the work area's bottom-end corner |
|
|
184
|
+
|
|
185
|
+
A rail with no `mainToolbar` floats its groups in its corner the same way, so
|
|
186
|
+
a closed panel can always be reopened. An open overlay panel carries its own
|
|
187
|
+
toggle, so it never depends on a control it covers. An app's own
|
|
188
|
+
`restoreControl` still wins over the floating fallback.
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
<Workbench
|
|
192
|
+
id="studio"
|
|
193
|
+
label="Studio"
|
|
194
|
+
mainToolbar={{ label: "Editor", title: <ToolbarText text="Editor" size="xlarge" /> }}
|
|
195
|
+
main={<Editor />}
|
|
196
|
+
leftRail={{
|
|
197
|
+
label: "Navigator",
|
|
198
|
+
toolbar: {
|
|
199
|
+
label: "Navigator",
|
|
200
|
+
title: <ToolbarText text="Navigator" />,
|
|
201
|
+
leading: <NewFileGroup />,
|
|
202
|
+
trailing: <ToolbarControlGroup relocateOnCollapse label="Search files"><SearchButton /></ToolbarControlGroup>,
|
|
203
|
+
toggle: { action: "toggle-navigator", name: "navigator" },
|
|
204
|
+
},
|
|
205
|
+
content: <Files />,
|
|
206
|
+
collapsed: navCollapsed.value,
|
|
207
|
+
}}
|
|
208
|
+
/>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The work area's `Pane` can carry more fixed chrome: `mainHeader` renders under
|
|
212
|
+
`mainToolbar` (supporting copy) and `mainFooter` over `mainBottomToolbar` (a status
|
|
213
|
+
line or a resource toolbar), each divided from the scrolling `main`.
|
|
214
|
+
`mainHeaderPlacement` and `mainFooterPlacement` (`"fixed"` by default, or
|
|
215
|
+
`"scroll"`) let that header or footer chrome scroll away with `main` instead —
|
|
216
|
+
useful where large text would leave pinned chrome little room. `"auto"` keeps
|
|
217
|
+
it pinned while the work area is tall enough and lets it scroll with `main`
|
|
218
|
+
when the work area is short (the Pane's `chromePlacement="auto"`; it applies to
|
|
219
|
+
the pinned header and footer together).
|
|
220
|
+
|
|
221
|
+
Every toolbar the Workbench composes — `mainToolbar`, `mainBottomToolbar`, and
|
|
222
|
+
each panel's `toolbar` — takes the `Toolbar`'s configuration (`ToolbarConfig`):
|
|
223
|
+
`dividerSides`, `centerAlign`, `responsive`, `responsiveAt`, and
|
|
224
|
+
`safeAreaEdges`. Configure the toolbar through these props rather than styling
|
|
225
|
+
it. No toolbar draws a divider by default: each `Pane` draws one line under
|
|
226
|
+
its header chrome and one over its footer chrome, wherever that chrome ends,
|
|
227
|
+
only while its content is scrolled beneath it (see
|
|
228
|
+
[Scroll dividers](./layout.md#scroll-dividers) — call `wireScrollDividers`
|
|
229
|
+
once at the app root). Set `dividerSides` only for a permanent separator edge,
|
|
230
|
+
or `chromeDividers: "always"` on the pane for a line that never hides.
|
|
231
|
+
`responsive: "wrap"` keeps a long title whole and wraps its actions
|
|
232
|
+
below it. `mainBottomToolbar` also takes a `center`. A panel's
|
|
233
|
+
`restorePosition` also places its floating restore controls.
|
|
234
|
+
|
|
235
|
+
The `Pane`s and `List`s the Workbench composes around your content are
|
|
236
|
+
configurable the same way:
|
|
237
|
+
|
|
238
|
+
- `mainPane` (`PaneConfig`: `contentElement`, `contentLabel`, `separators`,
|
|
239
|
+
`safeAreaEdges`, `chromeDividers`) configures the work area's `Pane`, which exists whenever the
|
|
240
|
+
work area has a toolbar, `mainHeader`, or `mainFooter`;
|
|
241
|
+
- a panel's `pane` configures the `Pane` a `toolbar` panel's `content` renders
|
|
242
|
+
in — for example `{ contentElement: "nav", contentLabel: "Files" }` for a
|
|
243
|
+
navigator rail;
|
|
244
|
+
- `mainHeaderList` / `mainFooterList` (`ListConfig`: `gap`, `hAlign`,
|
|
245
|
+
`vAlign`, `dividerSides`, `textInsets`, `controlInsets`) configure the
|
|
246
|
+
`List`s holding `mainHeader` / `mainFooter`.
|
|
247
|
+
|
|
248
|
+
An omitted or `undefined` field keeps the default, including the scroll
|
|
249
|
+
dividers described above.
|
|
250
|
+
|
|
251
|
+
Size a rail so its title and groups fit at its narrowest (a resizable rail's
|
|
252
|
+
`min`); a toolbar that cannot hold them drops the title rather than
|
|
253
|
+
truncating it. Relocated content renders in both places while the panel is
|
|
254
|
+
closed (the panel's copy is inert), so give it no `id`s. With `wireWorkbench`
|
|
255
|
+
given the panel's `collapsed` signal, focus follows the toggle: closing a
|
|
256
|
+
panel from its own toggle focuses the relocated toggle in the work area, and
|
|
257
|
+
opening it from there focuses the panel's own toggle. A panel's optional
|
|
258
|
+
`footer` renders below its content, for a sidebar's bottom toolbar. Without a
|
|
259
|
+
`toolbar` or `mainToolbar`, `content` and `main` render exactly as given.
|
|
260
|
+
|
|
261
|
+
## Resizable panels
|
|
262
|
+
|
|
263
|
+
Resizing is **opt-in per panel**. Give a panel `resizable` — `true` for the
|
|
264
|
+
default limits (rails 180–480px, drawer 120–480px) or `{ min, max }` — and
|
|
265
|
+
render its `size` from an app-owned signal. The panel then owns a separator on
|
|
266
|
+
its inner edge (the left rail's end, the right rail's start, the drawer's top)
|
|
267
|
+
with the same focusable `role="separator"` contract as a `ResizableRegion`
|
|
268
|
+
handle. `wireWorkbench` drives it:
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
import { wireWorkbench } from "@kerfjs/ui/wire-workbench";
|
|
272
|
+
|
|
273
|
+
const navSize = signal(280);
|
|
274
|
+
const consoleSize = signal(200);
|
|
275
|
+
|
|
276
|
+
<Workbench
|
|
277
|
+
id="studio"
|
|
278
|
+
label="Studio"
|
|
279
|
+
main={<Editor />}
|
|
280
|
+
mainMinSize={320} // the default: the editor never drops below 320px wide
|
|
281
|
+
mainMinHeight={120} // the default: the drawer leaves it 120px of height
|
|
282
|
+
leftRail={{
|
|
283
|
+
content: <Navigator />,
|
|
284
|
+
label: "Navigator",
|
|
285
|
+
collapsed: navCollapsed.value,
|
|
286
|
+
size: navSize.value,
|
|
287
|
+
resizable: { min: 200, max: 420 },
|
|
288
|
+
responsiveOverlayAt: "narrow", // an overlay when the Workbench is 704px or narrower
|
|
289
|
+
}}
|
|
290
|
+
bottomDrawer={{
|
|
291
|
+
content: <Console />,
|
|
292
|
+
label: "Console",
|
|
293
|
+
size: consoleSize.value,
|
|
294
|
+
resizable: true,
|
|
295
|
+
}}
|
|
296
|
+
/>;
|
|
297
|
+
|
|
298
|
+
// once, after mount:
|
|
299
|
+
const stop = wireWorkbench(root, {
|
|
300
|
+
id: "studio",
|
|
301
|
+
panels: {
|
|
302
|
+
leftRail: {
|
|
303
|
+
size: navSize,
|
|
304
|
+
storageKey: "studio.nav-width",
|
|
305
|
+
collapsed: navCollapsed, // a transient overlay: takes focus, closes on Escape / outside press
|
|
306
|
+
},
|
|
307
|
+
bottomDrawer: { size: consoleSize, storageKey: "studio.console-height" },
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
- **Pointer:** dragging the separator resizes the panel live (the wire marks
|
|
313
|
+
it `data-resizing` and suppresses content motion) and commits the final
|
|
314
|
+
size to the signal on release.
|
|
315
|
+
- **Keyboard:** focus the separator; arrow keys resize by `step` (16px),
|
|
316
|
+
Shift+arrow by `largeStep` (64px), Home/End jump to `min`/`max`. The
|
|
317
|
+
separator's `aria-valuenow`/`aria-valuemin`/`aria-valuemax` report the size
|
|
318
|
+
and limits.
|
|
319
|
+
- **Limits:** every size — dragged, typed, restored from storage, or passed
|
|
320
|
+
by the app — is clamped to `min`/`max` when rendered.
|
|
321
|
+
- **Work-area minimum:** beside its inline rails, fixed or resizable, the work
|
|
322
|
+
area keeps at least `mainMinSize` px of width (a `Workbench` prop, default
|
|
323
|
+
320; `0` turns it off), and above an inline bottom drawer at least
|
|
324
|
+
`mainMinHeight` px of height (default 120; `0` turns it off). A dragged or
|
|
325
|
+
keyed rail stops growing where the work area would drop below its width,
|
|
326
|
+
and the drawer where it would drop below its height, so wide rails or a tall
|
|
327
|
+
drawer cannot crowd out the editor; `aria-valuemax` reports that reachable
|
|
328
|
+
maximum. When the Workbench itself narrows, the rails shrink in proportion
|
|
329
|
+
to their sizes, and when it gets shorter the drawer shrinks (their content
|
|
330
|
+
follows the shown size) while the work area holds its minimum; a squeezed
|
|
331
|
+
panel can still be made smaller, never larger, and never below its own
|
|
332
|
+
`min`. Two fixed 280px rails in a 720px Workbench show 200px each rather
|
|
333
|
+
than leaving the editor 160px. Each minimum applies only to a Workbench with a
|
|
334
|
+
panel on its axis, and never exceeds the Workbench itself.
|
|
335
|
+
- **Squeezed below `min`:** when the Workbench is too narrow for a rail's
|
|
336
|
+
`min` beside the work-area minimum, the rail shows less than its `min` (a
|
|
337
|
+
172px Navigator whose `min` is 180). Its separator then reports that shown
|
|
338
|
+
width in `aria-valuenow`, and `aria-valuemin`/`aria-valuemax` pin to the
|
|
339
|
+
same value: the WAI-ARIA window splitter's value is the separator's actual
|
|
340
|
+
position, and the range must contain it, so a screen reader hears the width
|
|
341
|
+
on screen rather than a configured limit the layout cannot honor — and a
|
|
342
|
+
range that does not move, because the separator cannot move a rail the
|
|
343
|
+
container holds. A pinned separator commits nothing: arrow keys, Home/End,
|
|
344
|
+
and drags leave the rail's remembered size (and its storage) alone, so a
|
|
345
|
+
rail remembered at 280px returns at 280px, with the configured range, once
|
|
346
|
+
there is room.
|
|
347
|
+
- **Small Workbenches:** inline panels have no shrink floor of their own, by
|
|
348
|
+
design; the work area's minimums win, so in a very small Workbench a rail or
|
|
349
|
+
the drawer can become a sliver. Do not add your own `min-width` /
|
|
350
|
+
`min-height` to hold a panel open. Give the panel
|
|
351
|
+
`responsiveOverlayAt: "narrow"` (704px of Workbench width or less) or
|
|
352
|
+
`"compact"` (448px or less) instead: below that breakpoint it presents as a
|
|
353
|
+
full-size overlay over the work area rather than squeezing beside it (see
|
|
354
|
+
the catalog's resizable and responsive-drawer Workbench examples).
|
|
355
|
+
- **Collapse:** `collapsed` never changes a size. A collapsed panel keeps its
|
|
356
|
+
size (its content slides out at that width), its separator leaves the tab
|
|
357
|
+
order, and expanding it returns it at the size it had.
|
|
358
|
+
- **Persistence:** with a `storageKey`, the size is loaded from `storage`
|
|
359
|
+
(default `localStorage`) at wire-up and saved on every change, like
|
|
360
|
+
`wireSidebar`'s collapsed state.
|
|
361
|
+
- **Overlays never resize:** an overlay or hidden panel — including a rail
|
|
362
|
+
whose `responsiveOverlayAt` breakpoint currently applies — hides its
|
|
363
|
+
separator and is never resizable, and it leaves the work-area minimum to the
|
|
364
|
+
rails still in flow. With `responsiveOverlayAt` no device check is needed;
|
|
365
|
+
otherwise pass `deviceClass` and resizing is suspended while `compact` is
|
|
366
|
+
true, where rails present as overlay drawers or are replaced.
|
|
367
|
+
- `wireWorkbench` drives only the panels it is given, matched by the
|
|
368
|
+
Workbench `id`, so it never double-drives a `ResizableRegion` (or another
|
|
369
|
+
Workbench) under the same root. `onResize({ panel, size, source })` reports
|
|
370
|
+
each committed resize.
|
|
371
|
+
|
|
372
|
+
## Transient overlays
|
|
373
|
+
|
|
374
|
+
An overlay panel covers the work area, so it should open only when the user
|
|
375
|
+
asks for it and close as easily as it opened. Give `wireWorkbench` a panel's
|
|
376
|
+
app-owned `collapsed` signal (`size` is optional, so a panel need not be
|
|
377
|
+
resizable) and it treats the panel as a transient overlay whenever it
|
|
378
|
+
presents as one, mirroring `wireSidebar`'s compact overlay:
|
|
379
|
+
|
|
380
|
+
- **Collapsed on entering the breakpoint:** when a panel's
|
|
381
|
+
`responsiveOverlayAt` breakpoint begins to apply — at wire-up, when the
|
|
382
|
+
Workbench first renders, or when it narrows across the breakpoint — the
|
|
383
|
+
wiring remembers the panel's inline `collapsed` state and collapses it, so
|
|
384
|
+
nothing covers the work area until the user opens it. When the breakpoint
|
|
385
|
+
stops applying (and on disposal) the remembered inline state comes back.
|
|
386
|
+
These presentation changes skip the collapse motion.
|
|
387
|
+
- **Focus moves in, and Tab stays in:** a panel that opens while it presents
|
|
388
|
+
as an overlay takes focus on its first focusable control (typically the
|
|
389
|
+
close control in its header), because it covers the work area and the
|
|
390
|
+
control that opened it. While it is open, Tab and Shift+Tab cycle through
|
|
391
|
+
its controls and never reach the covered work area; Escape, its own close
|
|
392
|
+
control, or an outside press leaves it. This is the ARIA dialog pattern
|
|
393
|
+
`wireSidebar`'s compact overlay follows. A panel opening inline never moves
|
|
394
|
+
focus.
|
|
395
|
+
- **Escape** closes the open overlay panel that holds focus, else the most
|
|
396
|
+
recently opened one. An Escape another handler already handled
|
|
397
|
+
(`defaultPrevented`) is left alone.
|
|
398
|
+
- **Outside press:** a pointer press that starts and ends outside an open
|
|
399
|
+
overlay panel closes it. The app's own toggle still works: its click closes
|
|
400
|
+
the panel before the wiring looks, and the press that opens a panel never
|
|
401
|
+
closes it.
|
|
402
|
+
- **Focus:** when a panel closes with focus inside it — whatever closed it,
|
|
403
|
+
including the app's own control inside the panel — focus returns to the
|
|
404
|
+
control that had it when the panel opened (typically its toggle; one inside
|
|
405
|
+
another panel that has closed since is skipped), else to
|
|
406
|
+
the first focusable control in the panel's `restoreControl`, else to a
|
|
407
|
+
focusable control outside the panel whose `aria-controls` names the panel
|
|
408
|
+
(or an element inside it). The last is what a panel already open at
|
|
409
|
+
wire-up relies on, since nothing opened it: give the app's toggle
|
|
410
|
+
`aria-controls` naming the panel. A pointer press inside the panel that
|
|
411
|
+
drops focus to the page counts as focus inside: Safari never focuses a
|
|
412
|
+
clicked button, so pressing the panel's own Hide control blurs the focused
|
|
413
|
+
control before the click closes it, and focus still returns. Focus the user
|
|
414
|
+
has moved to another element since is left alone. Each panel's `id` derives from the
|
|
415
|
+
Workbench's — `<id>-left-rail`, `<id>-right-rail`, `<id>-bottom-drawer`:
|
|
416
|
+
|
|
417
|
+
```tsx
|
|
418
|
+
<button
|
|
419
|
+
data-action="toggle-navigator"
|
|
420
|
+
aria-controls="editor-left-rail"
|
|
421
|
+
aria-expanded={String(!navCollapsed.value)}
|
|
422
|
+
aria-label={navCollapsed.value ? "Show navigator" : "Hide navigator"}
|
|
423
|
+
>
|
|
424
|
+
<LucideIcon {...collapsiblePanelToggleIcon("left", navCollapsed.value)} />
|
|
425
|
+
</button>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
An open overlay can cover the control that opened it: a narrow Workbench's
|
|
429
|
+
right-rail overlay spans the full height at the end edge, over the trailing
|
|
430
|
+
end of the work area's toolbar, where its toggle usually sits. Escape and an
|
|
431
|
+
outside press still close it, but neither is a visible, pointer-reachable
|
|
432
|
+
control. So give every panel that may present as an overlay its own close
|
|
433
|
+
control, as a `CollapsiblePanel` puts its collapse toggle in its own header:
|
|
434
|
+
render the panel content as a `Pane` whose header `Toolbar` holds the title
|
|
435
|
+
and a `single`, borderless `ToolbarControlGroup` around one icon button
|
|
436
|
+
carrying `collapsiblePanelToggleIcon(side, false)`. The work area's toggle
|
|
437
|
+
stays the always-visible way to show the panel. The catalog's resizable
|
|
438
|
+
example does this for both rails.
|
|
439
|
+
|
|
440
|
+
The drawer works the same way. The catalog's responsive overlay drawer
|
|
441
|
+
example is the whole pattern for a bottom drawer:
|
|
442
|
+
|
|
443
|
+
```tsx
|
|
444
|
+
const outputCollapsed = signal(false); // open inline by default
|
|
445
|
+
|
|
446
|
+
<Workbench
|
|
447
|
+
id="editor"
|
|
448
|
+
label="Editor"
|
|
449
|
+
main={<Editor />} // its toolbar toggles `outputCollapsed`
|
|
450
|
+
bottomDrawer={{
|
|
451
|
+
label: "Output",
|
|
452
|
+
content: <OutputPane />, // a Pane whose header holds its close control
|
|
453
|
+
collapsed: outputCollapsed.value,
|
|
454
|
+
size: 180,
|
|
455
|
+
responsiveOverlayAt: "narrow",
|
|
456
|
+
}}
|
|
457
|
+
/>;
|
|
458
|
+
|
|
459
|
+
wireWorkbench(root, {
|
|
460
|
+
id: "editor",
|
|
461
|
+
panels: { bottomDrawer: { collapsed: outputCollapsed } },
|
|
462
|
+
});
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Above 704px of Workbench width the drawer takes its own track below the
|
|
466
|
+
editor. At 704px or less it overlays the bottom of the full-height editor,
|
|
467
|
+
starts hidden, and closes from its own header, on Escape, or on a press
|
|
468
|
+
outside it; widening the Workbench again brings it back inline in the state
|
|
469
|
+
it had before.
|
|
470
|
+
|
|
471
|
+
Escape and outside-press dismissal apply to static `presentation: "overlay"`
|
|
472
|
+
panels too; entering and leaving the collapsed state around a breakpoint is
|
|
473
|
+
only for `responsiveOverlayAt`, because a static presentation is the app's
|
|
474
|
+
choice. Inline panels are never touched. Pass `dismissOverlays: false` to
|
|
475
|
+
leave every `collapsed` write, and all focus handling, to the app.
|
|
476
|
+
|
|
477
|
+
Overlays are exclusive by default, like `wireSidebar`'s compact overlays:
|
|
478
|
+
opening a panel while it presents as an overlay closes every other open
|
|
479
|
+
overlay panel, the bottom drawer included. At a narrow width two rails are
|
|
480
|
+
wider than the Workbench, so without this the right rail would cover the
|
|
481
|
+
navigator's own close control. Panels presenting inline are never closed by
|
|
482
|
+
it, so a wide Workbench keeps both rails open. Pass `exclusiveOverlays: false`
|
|
483
|
+
to let overlays stay open together; they then stack in the fixed order above,
|
|
484
|
+
and Tab stays in the one that holds focus (else the most recently opened
|
|
485
|
+
one).
|
|
486
|
+
|
|
487
|
+
Where the browser supports `overflow-clip-margin`, the 20px hit target
|
|
488
|
+
straddles the panel's separator line like a `ResizableRegion` handle;
|
|
489
|
+
elsewhere it sits just inside the panel's inner edge, because the panel clips
|
|
490
|
+
its sliding content.
|
|
491
|
+
|
|
492
|
+
## Resizable application-shell migration
|
|
493
|
+
|
|
494
|
+
An application such as Hot Sheet can replace its shell descendant overrides
|
|
495
|
+
with state-derived props:
|
|
496
|
+
|
|
497
|
+
```tsx
|
|
498
|
+
<ResizableRegion
|
|
499
|
+
id="terminal-drawer"
|
|
500
|
+
label="Terminal drawer"
|
|
501
|
+
axis="vertical"
|
|
502
|
+
edge="start"
|
|
503
|
+
size={drawerSize.value}
|
|
504
|
+
min={180}
|
|
505
|
+
max={520}
|
|
506
|
+
collapsed={!drawerVisible.value}
|
|
507
|
+
separator={magnified.value ? "hidden" : "auto"}
|
|
508
|
+
collapseMotion="fade-slide"
|
|
509
|
+
contentOverflow={createMenuOpen.value ? "visible" : "clip"}
|
|
510
|
+
presentation={mobile.value ? "overlay" : "inline"}
|
|
511
|
+
restoreControl={
|
|
512
|
+
<ToolbarControlGroup label="Terminals" single>
|
|
513
|
+
<button data-action="show-drawer" aria-label="Show terminals">
|
|
514
|
+
<LucideIcon {...collapsiblePanelToggleIcon("bottom", true)} />
|
|
515
|
+
</button>
|
|
516
|
+
</ToolbarControlGroup>
|
|
517
|
+
}
|
|
518
|
+
>
|
|
519
|
+
<TerminalDrawer />
|
|
520
|
+
</ResizableRegion>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
`wireResizableRegions` marks the active region with `data-resizing` and the
|
|
524
|
+
package CSS suppresses content motion during pointer resize. It applies the
|
|
525
|
+
live size to both the track and the slide-motion content, so content fills the
|
|
526
|
+
region throughout a drag, including any safe-area edge extent, and a later
|
|
527
|
+
collapse slides it out at the resized width. A collapsed,
|
|
528
|
+
overlay, or hidden region is not resizeable. Together these policies replace
|
|
529
|
+
app CSS for separator suppression, instant-track/composited-content collapse,
|
|
530
|
+
popup overflow, mobile overlay/hidden replacement, resize-transition guards,
|
|
531
|
+
and safe-area restore placement. The app still owns the signals and decides
|
|
532
|
+
when each policy applies.
|
|
533
|
+
|
|
534
|
+
## Public styling boundary
|
|
535
|
+
|
|
536
|
+
The component subpath's browser build loads `workbench.css`; import
|
|
537
|
+
`@kerfjs/ui/workbench.css` manually only without the `browser` condition. Applications may
|
|
538
|
+
set `--kui-workbench-rail-width` and `--kui-workbench-drawer-height` on a
|
|
539
|
+
Workbench instance. The supported composition classes are `.kui-workbench`,
|
|
540
|
+
`.kui-workbench__rail`, `.kui-workbench__rail--left`,
|
|
541
|
+
`.kui-workbench__rail--right`, `.kui-workbench__center`,
|
|
542
|
+
`.kui-workbench__main`, `.kui-workbench__drawer`,
|
|
543
|
+
`.kui-workbench__panel-content`, `.kui-workbench__handle`,
|
|
544
|
+
`.kui-workbench__handle-icon`, and `.kui-workbench__restore`; these exact hooks are cataloged for tools that
|
|
545
|
+
must classify public application selectors. Prefer the component props and two
|
|
546
|
+
size tokens before selecting internal anatomy, and do not target its data
|
|
547
|
+
attributes or descendant tags as styling contracts.
|
|
548
|
+
|
|
549
|
+
## Safe areas
|
|
550
|
+
|
|
551
|
+
Each rail and the drawer grows by the unsafe inset of the screen edge it docks
|
|
552
|
+
to, so its surface and separator paint through while its content keeps the
|
|
553
|
+
configured size and is padded for the edges it touches. The main area pads for
|
|
554
|
+
the edges it reaches, inside its scroller: an expanded inline rail or drawer
|
|
555
|
+
takes that edge away, and collapsing it (or presenting it as an overlay) hands
|
|
556
|
+
the edge back. A region whose only child is a `Pane` or layout lets that child
|
|
557
|
+
own the insets. See [Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
|
|
38
558
|
|
|
39
559
|
## How the collapse animates
|
|
40
560
|
|
|
41
561
|
Collapsing snaps the panel's flex track to zero in a single reflow (so the work
|
|
42
562
|
area relayouts once, not per frame) while the panel's fixed-size content slides
|
|
43
563
|
out via a composited `transform` — a rail slides horizontally, the drawer
|
|
44
|
-
vertically — clipped by the shell's overflow.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
564
|
+
vertically — clipped by the shell's overflow. The drawer content is positioned
|
|
565
|
+
against the shell's stable bottom edge, so opening and closing move monotonically
|
|
566
|
+
through the transform rather than inheriting a changing normal-flow origin. It
|
|
567
|
+
honors `prefers-reduced-motion` (the slide collapses to instant). On smaller
|
|
568
|
+
device classes, present the rails' contents through a `NavStack` or overlay
|
|
569
|
+
drawers rather than shrinking the three-panel shell.
|