@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
|
@@ -18,25 +18,250 @@ package delivery paths, Web Awesome's installed manifest, AI guidance, and
|
|
|
18
18
|
documentation links. Nuanced prose in this contract and the selection guide
|
|
19
19
|
remains authored rather than generated.
|
|
20
20
|
|
|
21
|
+
### Markdown component reference (AI entry point)
|
|
22
|
+
|
|
23
|
+
[`ai/components/README.md`](../ai/components/README.md) and one
|
|
24
|
+
`ai/components/<id>.md` page per catalog entry are the assistant-facing view of
|
|
25
|
+
both catalogs. An assistant reads the index, then only the pages it uses,
|
|
26
|
+
instead of loading the full JSON. Each page merges the entry's selection facts
|
|
27
|
+
(purpose, use/avoid, alternatives), delivery (JavaScript subpath, CSS,
|
|
28
|
+
registration, wiring helpers), a link into `public-api-signatures-v1.md` for
|
|
29
|
+
exact props, composition (parents, contexts, zones with their JSX prop and
|
|
30
|
+
cardinality, children), state and wiring ownership including wiring-owned
|
|
31
|
+
state attributes, geometry, accessibility obligations, public class and token
|
|
32
|
+
hooks framed as a styling boundary (components own their styles; configure
|
|
33
|
+
through props rather than overriding internals), and `KUI-C###` diagnostics
|
|
34
|
+
with their conditions. `scripts/sync-component-docs.mjs` renders them only from
|
|
35
|
+
`component-catalog.json` and `component-composition.json` (plus the signature
|
|
36
|
+
file's module headings for anchors), sorted and Prettier-formatted;
|
|
37
|
+
`check:catalog` rejects a stale, missing, or orphaned page. The JSON files stay
|
|
38
|
+
the canonical tool-facing sources.
|
|
39
|
+
|
|
40
|
+
### Composition catalog
|
|
41
|
+
|
|
42
|
+
[`component-composition.json`](../ai/component-composition.json) adds a formal,
|
|
43
|
+
machine-evaluable composition layer beside `component-catalog.json` without
|
|
44
|
+
changing its selection and delivery contract; it is a generated companion, not
|
|
45
|
+
a newer version of that catalog. Every component-catalog entry projects once,
|
|
46
|
+
in order, under the stable qualified key `package:id`. Each composition entry
|
|
47
|
+
explicitly covers parents/contexts,
|
|
48
|
+
named zones and cardinality, optional explicit JSX prop bindings, child concepts, state ownership, required wiring,
|
|
49
|
+
responsive ownership, layout and geometry, accessibility obligations, public
|
|
50
|
+
CSS boundaries, diagnostics, and provenance. A wrapper entry may add
|
|
51
|
+
`rendersAs`: the cataloged roots it renders (any one of them, or nothing), so
|
|
52
|
+
composition checks treat its elements as each root rather than as an unknown
|
|
53
|
+
child. A placement with listed parent constraints produces one `KUI-L201`
|
|
54
|
+
diagnostic even when both the wrapper and a rendered root reject that parent.
|
|
55
|
+
When one catalog entry exports another JSX component with different placement,
|
|
56
|
+
`jsxExports` gives that export its own parent contract. The extra export does
|
|
57
|
+
not stand for the entry's root when a parent zone is checked.
|
|
58
|
+
Generated `boundaries.rootClass` prefers the public `kui-<entry-id>` class when
|
|
59
|
+
present, so a sibling export's class cannot become the entry's root class.
|
|
60
|
+
|
|
61
|
+
`boundaries.placeableClasses` names the subset of `publicClasses` an
|
|
62
|
+
application may write onto its own elements (layout utilities, the document
|
|
63
|
+
root, item geometry on another carrier); absent means none, and every other
|
|
64
|
+
public class is the component's rendered anatomy. `boundaries.rootElement`
|
|
65
|
+
names the element a component renders around its own placeable classes
|
|
66
|
+
(`content-item`: `div`), so a plain element of that tag carrying them is still
|
|
67
|
+
the component recreated. `eslint-plugin-kerfjs`'s `ui-public-boundaries`
|
|
68
|
+
reports both as `KUI-L103` with the export to render — for `@kerfjs/ui` and for
|
|
69
|
+
every consumer catalog a `.kerf-ui-profile.json` declares, whatever the class
|
|
70
|
+
prefix. `create-kerf-component` packages declare the same fields in
|
|
71
|
+
`kerf.components.json`.
|
|
72
|
+
|
|
73
|
+
An entry's optional `cssValueProps` makes CSS-adjacent prop grammar equally
|
|
74
|
+
machine-evaluable. Each path records the property grammar, finite shorthands,
|
|
75
|
+
canonical versus exceptional spacing choices, standalone and expression-only
|
|
76
|
+
helpers, raw/unsafe policy, and serialization examples. Nested paths use the
|
|
77
|
+
bounded `items[].property` form. Consumer catalogs can publish the same facts;
|
|
78
|
+
ESLint, `kerf-ui-analyze`, and `kerf-ui-doctor` then issue the same stable
|
|
79
|
+
`KUI-L013`–`KUI-L017` feedback for application and third-party components.
|
|
80
|
+
|
|
81
|
+
`wiring.stateAttributes` lists the **wiring-owned state attributes**: the
|
|
82
|
+
`data-*` attributes a wiring helper writes at runtime, such as
|
|
83
|
+
`data-handle-inset` and `data-resizing`, which `wireResizableRegions` puts on a
|
|
84
|
+
`ResizableRegion`. Each entry names the attribute, the element that carries it
|
|
85
|
+
(`on`), the `helper` that writes it, and what it means. An application must not
|
|
86
|
+
render, remove, or treat these attributes as its own state; tools use the list
|
|
87
|
+
to tell them apart from app-authored attributes. They are declared once, on the
|
|
88
|
+
helper's wiring item in the component catalog, and the composition catalog
|
|
89
|
+
flattens them. `check:catalog`
|
|
90
|
+
reads each `wire*` helper's source and fails when its declarations differ from
|
|
91
|
+
the `data-*` attributes it actually writes. First-party entries always carry
|
|
92
|
+
the list, empty when their helpers write none; it is optional in extension
|
|
93
|
+
catalogs.
|
|
94
|
+
|
|
95
|
+
The generator starts with permissive defaults. An `any` mode records that the
|
|
96
|
+
catalog has no defensible prohibition; it does not claim every composition is
|
|
97
|
+
recommended. Objective rules live in
|
|
98
|
+
`component-composition-rules.json` and may carry stable `KUI-C###`
|
|
99
|
+
diagnostics. A tool reports a diagnostic only after proving its exact `when`
|
|
100
|
+
condition. Subjective choice, product policy, and visual taste remain prose.
|
|
101
|
+
|
|
102
|
+
Kerf UI calls component content positions **named `SafeHtml` prop slots**.
|
|
103
|
+
Use `children` for one homogeneous primary region; use explicit named
|
|
104
|
+
`SafeHtml` props for semantic positions or replacement content such as
|
|
105
|
+
`header`, `footer`, `leading`, `trailing`, `icon`, and `action`. These are typed
|
|
106
|
+
function-component props, not native web-component `<slot>` elements and not a
|
|
107
|
+
generic `slots={{...}}` object. A composition zone declares `jsx.prop` only when tooling
|
|
108
|
+
can soundly bind that zone to one public JSX prop; `children` is spelled
|
|
109
|
+
explicitly. Zones without that binding remain guidance and are never guessed
|
|
110
|
+
from their ids. Static tools inspect only visible JSX structure and leave
|
|
111
|
+
dynamic `SafeHtml` expressions to runtime and accessibility evaluation.
|
|
112
|
+
|
|
113
|
+
### Native named-slot assignment
|
|
114
|
+
|
|
115
|
+
Every public visual component with one stable conceptual root accepts an
|
|
116
|
+
explicit `slot?: string` prop and forwards it to that root on every render
|
|
117
|
+
branch. Use it when a Kerf component is a light-DOM child of a custom element,
|
|
118
|
+
for example `StateBanner({ title: 'Ready', slot: 'status' })`. Omitting the prop
|
|
119
|
+
omits the attribute.
|
|
120
|
+
|
|
121
|
+
This contract does not open a generic native-attribute bag: components still
|
|
122
|
+
accept only their documented props and narrow extension-attribute objects.
|
|
123
|
+
`ResizableRegion` and `CollapsiblePanel` are deliberately excluded because each
|
|
124
|
+
can return a region plus a sibling restore control, leaving no single root that
|
|
125
|
+
can truthfully own native slot assignment. Their single-root controls and all
|
|
126
|
+
alternate-root branches of supported components retain the contract.
|
|
127
|
+
|
|
128
|
+
Component-catalog consumers continue unchanged. Composition-aware consumers
|
|
129
|
+
read `component-catalog.json` for selection/delivery and
|
|
130
|
+
`component-composition.json` for composition. `npm run catalog:sync` projects every new component,
|
|
131
|
+
recipe, and supported Web Awesome entry, and the completeness gate prevents
|
|
132
|
+
silent omissions. Downstream catalogs use the composition extension schema and types,
|
|
133
|
+
retain their own package identity, and qualify cross-catalog references. See
|
|
134
|
+
the checked
|
|
135
|
+
[`component-composition-extension.json`](./examples/component-composition-extension.json)
|
|
136
|
+
application-owned example.
|
|
137
|
+
|
|
138
|
+
### Compile-time contract boundary
|
|
139
|
+
|
|
140
|
+
The versioned
|
|
141
|
+
[`compile-time-contracts-v1.json`](../ai/compile-time-contracts-v1.json)
|
|
142
|
+
artifact maps stable `KUI-T###` ids to public imports, emitted symbols, and
|
|
143
|
+
catalog identities. Its positive/negative fixture compiles against both source
|
|
144
|
+
and a freshly packed package, so source declarations and shipped declarations
|
|
145
|
+
cannot silently diverge. See [Compile-time contracts](./type-contracts.md) for
|
|
146
|
+
the full audit, migration guidance, and the relationships deliberately left to
|
|
147
|
+
runtime/catalog checks because TypeScript cannot prove them.
|
|
148
|
+
|
|
149
|
+
### Application UI profile
|
|
150
|
+
|
|
151
|
+
The component catalogs describe what packages provide; an application profile
|
|
152
|
+
describes which supported choices a project has approved. A workspace may
|
|
153
|
+
check in `.kerf-ui-profile.json` conforming to
|
|
154
|
+
[`application-ui-profile.schema.json`](../ai/application-ui-profile.schema.json).
|
|
155
|
+
Keep package-qualified catalog locations and recurring-concept preferences,
|
|
156
|
+
allowed color schemes and density, public semantic-token overrides,
|
|
157
|
+
layout/responsive conventions, and narrow rule exceptions there. Product
|
|
158
|
+
records, copy, permissions, user preferences, and transport state do not belong
|
|
159
|
+
in this policy file.
|
|
160
|
+
|
|
161
|
+
Every catalog location names a composition artifact. `selection` is optional
|
|
162
|
+
for consumer packages whose generated metadata declares component-catalog
|
|
163
|
+
selection guidance not applicable; `@kerfjs/ui` retains its required
|
|
164
|
+
`component-catalog.json` selection artifact. This
|
|
165
|
+
lets a generated `component-composition.json` participate directly without a
|
|
166
|
+
fabricated compatibility file.
|
|
167
|
+
|
|
168
|
+
Discovery and precedence are deterministic:
|
|
169
|
+
|
|
170
|
+
1. Load `application-ui-profile.defaults.json` from `@kerfjs/ui`.
|
|
171
|
+
2. Load `.kerf-ui-profile.json` at the workspace root when present.
|
|
172
|
+
3. Walk from the workspace root toward the target directory and load each
|
|
173
|
+
directory-local profile in parent-to-child order.
|
|
174
|
+
|
|
175
|
+
Later scalar and object-map values win. Catalogs merge by package; preferences
|
|
176
|
+
and token overrides merge by key; exceptions merge by stable id. Lists such as
|
|
177
|
+
allowed themes/densities replace the earlier list rather than accumulating.
|
|
178
|
+
Every resolved field retains its source file. The shipped
|
|
179
|
+
`application-ui-profile.mjs` API implements discovery, merge, loading, and
|
|
180
|
+
validation and reports actionable originating file + JSON-path diagnostics for stale
|
|
181
|
+
catalogs, unknown component/rule/token references, preference conflicts, and
|
|
182
|
+
broad exceptions. Each raw layer is validated against the catalogs effective at
|
|
183
|
+
that exact precedence point before merge, so a broken parent catalog, stale
|
|
184
|
+
parent reference, invalid value, or unknown field cannot disappear merely
|
|
185
|
+
because a child profile replaces it. The shipped
|
|
186
|
+
`application-ui-profile-sync.cjs` projects the same merge and validation contract
|
|
187
|
+
for synchronous hosts such as ESLint rules; it deliberately performs no async
|
|
188
|
+
I/O.
|
|
189
|
+
See the
|
|
190
|
+
[`application-ui-profile.json`](./examples/application-ui-profile.json) example.
|
|
191
|
+
|
|
192
|
+
The package defaults avoid every `Discouraged` Web Awesome entry — each
|
|
193
|
+
`webawesome` catalog entry whose `recommendation` is not `supported`, except the
|
|
194
|
+
encouraged `wa-popup` primitive — under a concept whose `preferred` value is the
|
|
195
|
+
Kerf component that wraps or replaces it (`command-menu` → `PopupMenu`,
|
|
196
|
+
`value-selection` → `Select`, `application-tabs` → `TabBar`, `icon` →
|
|
197
|
+
`LucideIcon`, `resizable-pane` → `ResizableRegion`, `exclusive-choice` →
|
|
198
|
+
`SegmentedControl`, `hierarchy-navigation` → `List`, `embedded-media` →
|
|
199
|
+
`ContentItem`). `eslint-plugin-kerfjs` `ui-preferences` (`KUI-L301`, also run by
|
|
200
|
+
`kerf-ui-doctor`) therefore reports a Discouraged element written directly as a
|
|
201
|
+
JSX tag (`<wa-dropdown>`) as well as through an imported component. A declared
|
|
202
|
+
component's own source file is exempt, because that wrapper is the sanctioned
|
|
203
|
+
owner of the element it renders. A unit test holds the avoid set and the
|
|
204
|
+
catalog's Discouraged set equal in both directions, so neither can drift. A
|
|
205
|
+
product that genuinely needs one of these elements records a narrow `KUI-L301`
|
|
206
|
+
profile exception for the file that renders it.
|
|
207
|
+
|
|
208
|
+
Catalog detail footers use one standard resource vocabulary and order. Build
|
|
209
|
+
them with `catalogResources()` from `@kerfjs/ui/catalog-resources`: `Demo source`
|
|
210
|
+
first, optional `Component source` and `Design template`, then `Guidance`.
|
|
211
|
+
Third-party entries use the typed `integrationGuidance` kind, which renders
|
|
212
|
+
`Integration guidance`, and omit `Component source` when the implementation is
|
|
213
|
+
not owned by the catalog's project. Prefer these semantic kinds over local labels
|
|
214
|
+
such as “View source” or “Read UI guidance”; the helper makes that convention a
|
|
215
|
+
compile-time choice while still returning ordinary `CatalogResource[]` values.
|
|
216
|
+
|
|
21
217
|
## Ownership boundaries
|
|
22
218
|
|
|
219
|
+
### Geometry ownership metadata
|
|
220
|
+
|
|
221
|
+
The canonical [`component-catalog.json`](../ai/component-catalog.json) records
|
|
222
|
+
the margin, border, and padding owner for every component and composition under
|
|
223
|
+
`geometry`. Read it before adding a wrapper or local spacing rule:
|
|
224
|
+
|
|
225
|
+
- `self` means the entry's public visual contract supplies that geometry.
|
|
226
|
+
- `parent` means the embedding layout must supply it.
|
|
227
|
+
- `child` means composed descendants supply it; the entry's outer shell does not.
|
|
228
|
+
- `none` means that dimension is intentionally absent from the standard contract.
|
|
229
|
+
- `conditional` means a variant, part, or configuration changes ownership; the
|
|
230
|
+
accompanying `notes` explain the boundary.
|
|
231
|
+
|
|
232
|
+
The values describe public ownership, including themed shadow parts, rather
|
|
233
|
+
than merely asking whether a CSS declaration appears on the host element.
|
|
234
|
+
Recipes are exempt because they arrange entries whose individual ownership is
|
|
235
|
+
already cataloged.
|
|
236
|
+
|
|
237
|
+
Downstream packages and applications should publish the same contract for their
|
|
238
|
+
reusable visual components. Use
|
|
239
|
+
[`component-catalog-extension.schema.json`](../ai/component-catalog-extension.schema.json)
|
|
240
|
+
and copy the structure of the checked
|
|
241
|
+
[`component-catalog-extension.json`](./examples/component-catalog-extension.json)
|
|
242
|
+
example. Keep app and Kerf entries as package-qualified inputs, then let people
|
|
243
|
+
or AI tools search their combined entries and compare `geometry` before adding
|
|
244
|
+
wrappers or insets. Do not add app-owned entries to Kerf's canonical catalog or
|
|
245
|
+
claim Kerf delivery paths for them.
|
|
246
|
+
|
|
23
247
|
- Components own semantic markup, stable anatomy, documented variants, ARIA projection, and package CSS hooks.
|
|
24
248
|
- Applications own signals/stores, product copy, domain-state mapping, persistence, routing, permissions, and transport.
|
|
25
249
|
- Actions are `data-action` strings. Wire them at a stable root with `delegate()` or `delegateActions()` and retain the disposer.
|
|
26
250
|
- A reusable component never owns per-instance mutable module state.
|
|
27
|
-
- Consumers
|
|
251
|
+
- Consumers configure presentation through component props and documented `--kui-*` semantic tokens. Foundation tokens provide opinionated neutral, brand/info, non-status pop, success, warning, and danger fill/border/foreground roles. Application stylesheets must not select package component classes or descendants. If genuinely new structure needs CSS, encapsulate that structure and its stylesheet in an application-owned component; configure any nested Kerf components through their public APIs.
|
|
28
252
|
|
|
29
|
-
`
|
|
30
|
-
`
|
|
253
|
+
`ListItem.rootAttributes`, `ListActionRow.rootAttributes`,
|
|
254
|
+
`ListHeader.rootAttributes`, `AppTab.rootAttributes`,
|
|
255
|
+
`CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` accept
|
|
31
256
|
application-owned `data-*` metadata without
|
|
32
|
-
adding product fields to the shared API. A `
|
|
33
|
-
`trailingActionAttributes`, and a `
|
|
257
|
+
adding product fields to the shared API. A `ListActionRow` trailing action uses
|
|
258
|
+
`trailingActionAttributes`, and a `ListHeader` action/disclosure uses
|
|
34
259
|
`triggerAttributes`, for `data-*`, native popover target/action attributes, and
|
|
35
260
|
the corresponding `aria-controls`/`aria-haspopup` relationship. These slots do
|
|
36
261
|
not accept roles or component-owned action, selection, disclosure, accessible
|
|
37
262
|
name, disabled, or icon fields. Extension objects are filtered at runtime,
|
|
38
263
|
including case-insensitive rejection of protected `data-*` names, and the
|
|
39
|
-
component writes its protected attributes after the accepted metadata. Typed,
|
|
264
|
+
component or helper writes its protected attributes after the accepted metadata. Typed,
|
|
40
265
|
structurally widened, and JavaScript callers therefore cannot replace its
|
|
41
266
|
contract.
|
|
42
267
|
|
|
@@ -46,10 +271,10 @@ component continues to own the named close button or focusable separator, and
|
|
|
46
271
|
`wireTabBars()` / `wireResizableRegions()` continue to own transient behavior
|
|
47
272
|
and disposal.
|
|
48
273
|
|
|
49
|
-
`
|
|
50
|
-
`
|
|
274
|
+
`ListItem.trailing`, `ListActionRow.label`, `ListActionRow.icon`, and
|
|
275
|
+
`ListActionRow.trailingActionIcon` are dormant SafeHtml slots. They must not
|
|
51
276
|
contain controls. When a row needs an independently interactive trailing
|
|
52
|
-
region, `
|
|
277
|
+
region, `ListActionRow` owns the noninteractive root and the two sibling native
|
|
53
278
|
buttons; the application owns their delegated behavior and controlled state.
|
|
54
279
|
Both row components align a leading icon with the first label line when
|
|
55
280
|
`multiline` allows the label to wrap; additional lines extend below that fixed
|
|
@@ -58,37 +283,143 @@ visual anchor.
|
|
|
58
283
|
### Public CSS anatomy
|
|
59
284
|
|
|
60
285
|
The `publicClasses` array on each entry in
|
|
61
|
-
[`component-catalog.json`](../ai/component-catalog.json)
|
|
62
|
-
anatomy
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`
|
|
75
|
-
|
|
76
|
-
|
|
286
|
+
[`component-catalog.json`](../ai/component-catalog.json) identifies stable
|
|
287
|
+
anatomy for diagnostics, tooling, browser assertions, and package-owned
|
|
288
|
+
composition. It is not an application customization API. Applications choose
|
|
289
|
+
documented props and tokens; package components may compose other components
|
|
290
|
+
only through those public contracts, never by styling a child's classes from a
|
|
291
|
+
parent stylesheet.
|
|
292
|
+
|
|
293
|
+
Inside the package, a component never styles another component or writes
|
|
294
|
+
another component's variables. When a child must adapt to a composing parent,
|
|
295
|
+
the child styles itself in that context from its own stylesheet: the parent's
|
|
296
|
+
class and state appear only in an ancestor compound, the styled compound is
|
|
297
|
+
the child's own class (or one of the child's own unclassed internals below
|
|
298
|
+
it), and the child reads context values the parent provides under the
|
|
299
|
+
parent's name. `ResizableRegion` widens its edge extent by the unsafe inset a
|
|
300
|
+
split `SplitView` provides, and a `Skeleton` derives its fill from a solid
|
|
301
|
+
`Badge`'s on-solid color, both in their own stylesheets; an `AppTab` rounds its
|
|
302
|
+
outer corners in a segmented `TabBar` and shares a fill-allocated strip from
|
|
303
|
+
`app-tab.css`. A `PopupMenu` sizes
|
|
304
|
+
its trigger and applies a group's `menuInset` in its own stylesheet, and an
|
|
305
|
+
icon-only `Select` reads the control slot a `ToolbarControlGroup` provides
|
|
306
|
+
(`--_kui-toolbar-control-group-slot-*`). A parent may still style its own
|
|
307
|
+
elements keyed on a child's state, naming the child by class inside `:has()`
|
|
308
|
+
(`:has(> .kui-select[open])`, or `TabBar` insetting a segmented strip that
|
|
309
|
+
holds compact tabs), and it keeps styling raw native and raw Web
|
|
310
|
+
Awesome children no kerf component owns, excluding kerf children by class
|
|
311
|
+
(`wa-dropdown:not(.kui-popup-menu)`). `npm run check:css-ownership` enforces
|
|
312
|
+
this in every component stylesheet (a `src/*.css` with a same-basename
|
|
313
|
+
component), deriving the component names, the Web Awesome tags each component
|
|
314
|
+
renders, and its composed children from `src/*.tsx`:
|
|
315
|
+
|
|
316
|
+
- **Foreign classes.** Another component's class or `[data-component]` may
|
|
317
|
+
appear only in an ancestor compound or inside `:has()` / `:not()`; the
|
|
318
|
+
styled compound is the stylesheet's own class.
|
|
319
|
+
- **Owned Web Awesome tags.** Kerf components are named by class, never by a
|
|
320
|
+
`wa-*` tag they render. A tag another component renders (`wa-dropdown`,
|
|
321
|
+
`wa-select`, `wa-option`, a `PopupMenu`'s trigger `wa-button`) — as the
|
|
322
|
+
subject, or as an ancestor whose internals the rule reaches — must be scoped
|
|
323
|
+
to that component by its class or excluded with `:not()`. A direct child
|
|
324
|
+
that cannot be the owner's internal
|
|
325
|
+
(`.kui-toolbar-control-group > wa-button`) needs no exclusion.
|
|
326
|
+
- **Variables.** A stylesheet writes only its own `--_kui-<self>-*` private
|
|
327
|
+
variables, and never overrides a public `--kui-<other>-*` token that another
|
|
328
|
+
component reads. Shared foundation tokens (`--kui-layout-*`,
|
|
329
|
+
`--kui-color-*`, …) are not any one component's. Context a parent provides
|
|
330
|
+
is named after the parent.
|
|
331
|
+
- **Context on any child.** Custom properties set on a subject that can be any
|
|
332
|
+
element (`.kui-x > *`, `> :not(…)`) also land on composed components' roots.
|
|
333
|
+
- **Hook classes.** A class the component places on a composed kerf child's
|
|
334
|
+
root (`<ToolbarText className="kui-nav-stack__title">`, a class NavStack once styled) may not be styled;
|
|
335
|
+
the child styles itself in that context instead.
|
|
336
|
+
|
|
337
|
+
The documented exceptions live with their reasons in
|
|
338
|
+
`scripts/lib/css-ownership.mjs`, and an exception that stops matching fails the
|
|
339
|
+
check, so the list only shrinks. The layout regions' inherited edge-inset
|
|
340
|
+
context (`--kui-edge-inset-*` handed to a sole Pane or layout child and cleared
|
|
341
|
+
for any other content, and a Toolbar clearing it for its zones) is the one
|
|
342
|
+
design exception; the others name the open fix ticket.
|
|
343
|
+
|
|
344
|
+
Applications and component packages built on the package follow the same
|
|
345
|
+
rules, and the downstream tools enforce them against the composition catalog
|
|
346
|
+
instead of package source: `kerf-ui-analyze` / `kerf-ui-doctor` report a rule
|
|
347
|
+
whose subject is another package's component (`KUI-L019`), another
|
|
348
|
+
component's private `--_*` variable (`KUI-L020`), an override of a token a
|
|
349
|
+
typed prop sets (`KUI-L021`), and a hook class on a component's root
|
|
350
|
+
(`KUI-L022`); `eslint-plugin-kerfjs`'s `ui-component-ownership` reports
|
|
351
|
+
`KUI-L020` / `KUI-L021` in script. Both share the selector parsing in
|
|
352
|
+
`analyzer/selectors.mjs` with `check:css-ownership`, and
|
|
353
|
+
`check:css-ownership` fails when a component renders a Web Awesome tag the
|
|
354
|
+
catalog does not list, so `KUI-L019` keeps covering every tag a kerf component
|
|
355
|
+
renders. Each finding names the configuration to use and routes a missing
|
|
356
|
+
prop to a component-gap report (see [the analyzer guide](./ui-analyzer.md#component-ownership-kui-l019kui-l022)).
|
|
357
|
+
|
|
358
|
+
The composition catalog additionally requires `boundaries.rootClass` to be
|
|
359
|
+
either one exact member of `publicClasses` or `null` when the entry has no
|
|
360
|
+
rendered class root. Runtime geometry tooling uses this explicit field; array
|
|
361
|
+
order never implies root ownership.
|
|
362
|
+
|
|
363
|
+
Do not select a component root or descendant by class, element name, id, or
|
|
364
|
+
attribute. Selectors such as `.workspace .kui-toolbar`,
|
|
365
|
+
`.kui-state-banner span`, and `.kui-list-item [data-state]` cross the ownership
|
|
366
|
+
boundary. If no prop or token expresses a recurring need, add the configuration
|
|
367
|
+
to the owning component instead of inferring it from rendered markup.
|
|
368
|
+
|
|
369
|
+
`Badge` owns the complete visual treatment for compact status, count, category,
|
|
370
|
+
and metadata labels. Configure its semantic `tone`, `appearance`, `shape`, and
|
|
371
|
+
`size`; do not recreate or override badge anatomy in an application or consuming
|
|
372
|
+
component. Use `label` when visible content is abbreviated and `ariaHidden` only
|
|
373
|
+
when a surrounding component already includes the same value in its accessible name.
|
|
374
|
+
Every tone's text and solid fill use that tone's `--kui-color-{tone}-on-fill`
|
|
375
|
+
token (`neutral` uses the text colors), the foreground tuned to clear WCAG AA
|
|
376
|
+
(4.5:1) on the tone's fills in light and dark mode.
|
|
377
|
+
|
|
378
|
+
`ListItem` renders its leading icon and nested SVG at a root-scaled 18px by
|
|
379
|
+
default while retaining the row's 44px minimum interactive target. Multiline
|
|
380
|
+
rows align that 18px visual with the first inherited text line. The row clips
|
|
381
|
+
descendant painting to its rounded root so labels, status, and dormant trailing
|
|
382
|
+
content cannot escape its visible boundary. Rows with descriptions grow enough
|
|
383
|
+
to keep their owned two-line label stack readable; use `multiline` when the
|
|
384
|
+
primary label should wrap rather than truncate. A single-line row ends its
|
|
385
|
+
primary label and description with an ellipsis before the trailing status
|
|
386
|
+
slot, even when the label is one long word; a `multiline` row wraps instead,
|
|
387
|
+
breaking a word wider than the label column (a long component or file name)
|
|
388
|
+
rather than letting it run under the trailing slot. A string label in a
|
|
389
|
+
`multiline` row gets line-break opportunities at its camelCase and acronym
|
|
390
|
+
boundaries, so `QuickTicketComposer` wraps as `QuickTicket` / `Composer`
|
|
391
|
+
rather than mid-word; breaking anywhere is only the last resort for a single
|
|
392
|
+
word that is still too wide. The text and accessible name are unchanged. `ListActionRow` labels
|
|
393
|
+
follow the same single-line and `multiline` rules before the trailing action.
|
|
394
|
+
|
|
395
|
+
`DisclosureArrow` uses an 18px root-scaled visual by default. Pass its typed
|
|
396
|
+
`size` prop when a consumer needs another size. Kerf `Select` uses a separate Web Awesome expand
|
|
77
397
|
glyph contract, `--kui-disclosure-icon-scale: .5`; changing one contract does
|
|
78
398
|
not implicitly change the other. Direction changes take the shortest rotation
|
|
79
399
|
path; a 180-degree closed-to-open tie uses counterclockwise rotation.
|
|
80
400
|
|
|
81
|
-
In `
|
|
401
|
+
In `ListHeader` toggle mode, omitting `actionIcon` composes the production
|
|
82
402
|
`DisclosureArrow` and derives its visual direction from `expanded`. The app
|
|
83
403
|
must update that controlled state and reveal or hide real content. Passing a
|
|
84
404
|
custom `actionIcon` replaces the default rather than layering or rotating both.
|
|
85
|
-
The root fills the available inline width after its standard margins
|
|
86
|
-
|
|
87
|
-
|
|
405
|
+
The root fills the available inline width after its standard margins by
|
|
406
|
+
default. Set `inline` when it must shrink-wrap beside surrounding content; that
|
|
407
|
+
presentation removes the root margin, border, and padding while retaining the
|
|
408
|
+
title and optional action's own control geometry. A separate action stays at
|
|
409
|
+
the logical end while the visible glyph defaults to 18px through
|
|
410
|
+
`--kui-list-header-action-icon-size`.
|
|
88
411
|
|
|
89
412
|
`StateBanner` exposes instance-level `--kui-state-banner-background`,
|
|
90
413
|
`--kui-state-banner-border`, `--kui-state-banner-foreground`,
|
|
91
|
-
`--kui-state-banner-detail
|
|
414
|
+
`--kui-state-banner-detail` and action background variables. Its optional
|
|
415
|
+
badge composes `Badge` beside the title and follows the banner tone by default. The
|
|
416
|
+
title, badge, and detail flow as inline text: a wrapping title keeps the badge one item
|
|
417
|
+
gap after its last word, and a detail that does not fit whole beside them moves to its
|
|
418
|
+
own line and truncates at the full copy width (below 576px it always takes its own
|
|
419
|
+
line). The title and detail both use the tone's `--kui-color-{tone}-on-fill`
|
|
420
|
+
foreground (`info` uses `brand`) at full strength, clearing WCAG AA over the tone's fill in light and dark
|
|
421
|
+
mode; the detail reads as secondary through its smaller, regular-weight type, and
|
|
422
|
+
only the neutral tone quiets it, to `--kui-color-neutral-on-quiet`. Its five built-in
|
|
92
423
|
tones can be rethemed globally with
|
|
93
424
|
`--kui-state-banner-{tone}-{background|border|foreground}`. Toolbar control,
|
|
94
425
|
segmented-control, app-tab, and tab-bar colors likewise use their public
|
|
@@ -96,39 +427,117 @@ segmented-control, app-tab, and tab-bar colors likewise use their public
|
|
|
96
427
|
hover, and selected-state variables, so rounded, pill, and toolbar presentations
|
|
97
428
|
remain opinionated but locally overridable.
|
|
98
429
|
|
|
430
|
+
Inset hover and selection surfaces follow the outer control shape instead of
|
|
431
|
+
choosing an independent radius. `--kui-layout-highlight-inset` is the full
|
|
432
|
+
distance between those edges; the inner radius is the outer radius minus that
|
|
433
|
+
inset. `ToolbarControlGroup` publishes its derived radius to nested toolbar
|
|
434
|
+
`SegmentedControl` choices, keeping both direct buttons and exclusive-choice
|
|
435
|
+
highlights concentric when the group switches between pill and rounded shapes.
|
|
436
|
+
|
|
99
437
|
`ResizableRegion` owns the Hot Sheet 2 split treatment: a persistent 1px
|
|
100
|
-
separator with a compact grip that appears on hover or keyboard focus.
|
|
438
|
+
separator with a compact grip that appears on hover or keyboard focus. The grip
|
|
439
|
+
is drawn centered on the separator line even though the pointer target is wider
|
|
440
|
+
than the line, so the handle never reads as offset into a pane. Override
|
|
101
441
|
`--kui-resizable-region-separator-color`,
|
|
102
442
|
`--kui-resizable-region-handle-color`, or
|
|
103
443
|
`--kui-resizable-region-handle-active-color` on a region when its containing
|
|
104
444
|
surface needs a different contrast level.
|
|
105
445
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
446
|
+
`Pane` defines one structural model for sidebars, main areas, inspectors, and
|
|
447
|
+
dialogs. Its `.kui-pane` root is unpadded and contains an optional vertical
|
|
448
|
+
header, one scrolling vertical `.kui-pane__content`, and an optional footer.
|
|
449
|
+
Logical-edge separator lines are independently opt-in and default off.
|
|
450
|
+
`@kerfjs/ui/layout.css` retains the pane roles and supplies the related content
|
|
451
|
+
geometry classes.
|
|
452
|
+
`List` is the corresponding layout-only vertical stack: its children stretch by
|
|
453
|
+
default, while `gap`, `flex`, and `scrollable` opt into typed spacing,
|
|
454
|
+
flex growth, and vertical scroll ownership. `Row.flex` uses the same typed flex
|
|
455
|
+
participation contract on the horizontal counterpart. `dividerSides` accepts canonical
|
|
456
|
+
physical top/right/bottom/left combinations such as `tr` and `trbl`; the stack
|
|
457
|
+
adds no list semantics, margin, or padding of its own. Use a direct finite
|
|
458
|
+
spacing shorthand such as `gap="2xs"`, or pass a `CssLength` created by the
|
|
459
|
+
CSS-free `@kerfjs/ui/css-values` helpers: `space('m')`, `rem(0.25)`,
|
|
460
|
+
`lengthVar('--app-gap')`, or `calc(plus(rem(0.25), pct(10)))`. `plus` returns a
|
|
461
|
+
non-standalone `CssLengthExpression`; only `calc` turns it into a complete
|
|
462
|
+
length. `remify(18)` is the runtime twin of source CSS's `remify(18px)`: it
|
|
463
|
+
takes a pixel count and returns a `CssLength` in rem (`1.125rem`) against the
|
|
464
|
+
same fixed 16px baseline. Raw CSS strings, and the source-only `remify(4px)`
|
|
465
|
+
string form, are not valid runtime props. The `CssLength` name intentionally includes percentages for UI dimension
|
|
466
|
+
props. Its opaque string brand improves authoring correctness; it is not a CSS
|
|
467
|
+
sanitizer or security boundary.
|
|
468
|
+
`Row.flex` and `List.flex` likewise accept their boolean default, finite keywords, or `CssFlex`
|
|
469
|
+
from `flex(grow, shrink, basis)`. `Skeleton` width/height use `CssSize`, radius
|
|
470
|
+
uses `CssLength`, and `SelectChoice.color` uses `CssForegroundColor` from
|
|
471
|
+
`uiColor()` with a foreground token such as `success-on-quiet`, or from
|
|
472
|
+
`foregroundColorVar()`. Fill tokens such as `success` are pale background tints
|
|
473
|
+
and do not type-check there. Never exchange these property grammars. List rows expose
|
|
474
|
+
`className`, public tokens, and semantic props instead of unrestricted `style`
|
|
475
|
+
declarations.
|
|
109
476
|
`.kui-content` gives major children 24px vertical separation.
|
|
110
|
-
`.kui-content-item` gives
|
|
111
|
-
8px
|
|
112
|
-
|
|
477
|
+
`ContentItem` (`@kerfjs/ui/content-item`, rendering `.kui-content-item`) gives
|
|
478
|
+
one child 8px inline margin, a real 1px border, 8px padding, and 12px corners;
|
|
479
|
+
the border stays transparent unless `frame="framed"`, so framing never changes
|
|
480
|
+
geometry. `shape="pill"` selects the 22px radius.
|
|
113
481
|
|
|
114
482
|
`ToolbarControlGroup` is the unit of toolbar organization, even for dormant
|
|
115
483
|
text. Each group reserves `calc(2px + remify(42px))`, or 44px, with 8px between
|
|
116
|
-
groups and inside items.
|
|
484
|
+
groups and inside items. For an ordinary icon/action control inside a group, use
|
|
485
|
+
a plain `<button>` — the group styles `> button` fully, and it keeps the group
|
|
486
|
+
free of a Web Awesome dependency and shadow DOM. Use `ToolbarActionLink` when
|
|
487
|
+
the action must retain native anchor navigation; the group owns its geometry,
|
|
488
|
+
hover, and focus treatment. Set `overflow="scroll"` when a row of controls must
|
|
489
|
+
stay inside the available toolbar width. Set `visibility="compact-only"` for a
|
|
490
|
+
group that replaces wider toolbar controls below the Toolbar's compact container
|
|
491
|
+
breakpoint; do not hide the group with an application class. Reach for
|
|
492
|
+
`wa-button` only when you need
|
|
493
|
+
a Web Awesome feature; a popup menu is a `PopupMenu`, which renders its own
|
|
494
|
+
trigger. Nothing wraps inside a group: an icon sits beside its label on one
|
|
495
|
+
row, and a group's controls never break onto a second line — the group sizes
|
|
496
|
+
to its content and the enclosing `Toolbar`'s responsive policy relocates whole
|
|
497
|
+
groups. For a compact mixed-content group, set `nestedDropdown`; a
|
|
498
|
+
text-and-caret trigger grows to its intrinsic width while an icon-only trigger
|
|
499
|
+
can remain square. A compact icon `<button>` is a 32px circle, so a selected
|
|
500
|
+
compact segment never becomes an oval. An icon-only `Select` joins a group as
|
|
501
|
+
one more segment with its siblings' inset, radius, hover, and focus ring; only a
|
|
502
|
+
lone Select grows the group to its icon-and-caret pill. Set `menuInset` to configure the dropdown menu surface
|
|
503
|
+
without application `::part(menu)` CSS; the default `standard` keeps each menu's
|
|
504
|
+
own inset (8px for a raw `wa-dropdown`, the Select listbox's 4px for a
|
|
505
|
+
`PopupMenu`), while `compact` and `list-zero` apply to every nested menu. A
|
|
506
|
+
`PopupMenu` and a `Select` draw one popup: the same caret that turns to face the
|
|
507
|
+
open popup, fade-in surface, surface inset, row height and padding, reserved
|
|
508
|
+
check column, current-row fill, and group titles, all read from one private
|
|
509
|
+
popup-choice contract in `foundation.css`. Compact mixed controls retain the standard
|
|
510
|
+
item padding, omit an internal separator, and let the raised selected item paint
|
|
511
|
+
over the outer border instead of shrinking to an inset highlight. The Web
|
|
512
|
+
Awesome trigger's shadow base owns max-content sizing, so icons, localized text,
|
|
513
|
+
and the shadow caret determine the width without a fixed host measurement.
|
|
514
|
+
The enclosing `Toolbar` owns zone alignment and responsive topology: use
|
|
515
|
+
`centerAlign="stretch"` when the center group should consume its track, and
|
|
516
|
+
choose `responsive="stack"` with `responsiveAt="compact" | "narrow"`,
|
|
517
|
+
`responsive="wrap"` for a heading whose title must stay whole, or
|
|
518
|
+
`responsive="center-priority"` instead of selecting its zone classes from a
|
|
519
|
+
parent stylesheet. No policy clips an action: the trailing zone, and a stacked
|
|
520
|
+
center zone, wrap whole groups onto another row. The center zone never
|
|
521
|
+
compresses below its content width, so when the leading identity, center, and
|
|
522
|
+
trailing zones share a row that is too narrow, the leading title is what gives
|
|
523
|
+
way: it truncates with an ellipsis (as a platform toolbar's title does) instead
|
|
524
|
+
of the center group painting over it. When everything fits, the center group
|
|
525
|
+
keeps its place, centered in the track between the leading and trailing zones.
|
|
526
|
+
`ListHeader` similarly separates its dormant title and
|
|
117
527
|
optional count or badge from its optional 44px action. Use the mutually
|
|
118
528
|
exclusive `count`/`countLabel` pair for non-negative safe-integer section
|
|
119
529
|
quantities; reserve `badge` for non-count `SafeHtml`. Do not concatenate counts
|
|
120
|
-
into the section label.
|
|
530
|
+
into the section label. Set `width="content"` to shrink-wrap while retaining
|
|
531
|
+
normal header geometry; `inline` is the separate zero-outer-geometry mode. Do
|
|
532
|
+
not add padding to pane shells,
|
|
121
533
|
double child-owned geometry with wrapper insets, or create competing scroll
|
|
122
534
|
owners. The [layout contract](./layout.md) lists the public roles and tokens.
|
|
123
535
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
when no icon is passed. The optional summary is a separate row aligned below the
|
|
130
|
-
title, so it cannot pull the icon group out of vertical alignment with the
|
|
131
|
-
title and action row.
|
|
536
|
+
Panel, dialog, and page headings are direct `Toolbar` compositions. The leading
|
|
537
|
+
zone holds an optional icon `ToolbarControlGroup` and a direct extra-large
|
|
538
|
+
`ToolbarText`; app actions belong in a trailing `ToolbarControlGroup`. Omit the
|
|
539
|
+
icon group when it has no content. Supporting copy is app-owned content below
|
|
540
|
+
the toolbar so it cannot pull the icon or actions out of alignment.
|
|
132
541
|
|
|
133
542
|
`ValueTable` composes typed `ValueTableRow` entries. A row owns its `dt`/`dd`
|
|
134
543
|
semantics and may receive a leading `SafeHtml` icon. Every row keeps 8px of
|
|
@@ -139,6 +548,16 @@ padding + 24px icon + 8px gap) and 8px from the right edge for an icon-bearing
|
|
|
139
548
|
row. Applications own the values, formatting, and whether an icon is decorative
|
|
140
549
|
or meaningfully labeled.
|
|
141
550
|
|
|
551
|
+
A row follows the settings-style key/value priority: the value keeps its
|
|
552
|
+
content and the label gives way. The label and value are two content-sized
|
|
553
|
+
columns that share the row's free space equally, each stopping once its content
|
|
554
|
+
fits. A short value therefore stays whole on one line beside any label, and a
|
|
555
|
+
long label takes the remaining width, wrapping at its spaces and ending a word
|
|
556
|
+
wider than its column (a long component or file name) in an ellipsis before the
|
|
557
|
+
value rather than running under it. A short label keeps its width beside a
|
|
558
|
+
long value, which wraps; when both are long they split the row, so neither is
|
|
559
|
+
starved.
|
|
560
|
+
|
|
142
561
|
## Imports and side effects
|
|
143
562
|
|
|
144
563
|
Every component has an explicit JS and CSS subpath. In CSS-aware browser builds,
|
|
@@ -161,27 +580,98 @@ render, hands in its own via `collapsible.signals`, drives it through
|
|
|
161
580
|
`handle.open`/`handle.close`, or disables any individual behavior — so transient
|
|
162
581
|
UI is consistent by default without every app reinventing it.
|
|
163
582
|
|
|
583
|
+
A public subpath that exposes several visual components is a folder-backed
|
|
584
|
+
surface. Put each component in its own source file and give each visual
|
|
585
|
+
component exactly one owned stylesheet alongside it. Keep the public
|
|
586
|
+
compatibility entrypoints implementation-free: the JavaScript/TypeScript
|
|
587
|
+
entrypoint only re-exports the folder modules, and the CSS entrypoint only
|
|
588
|
+
imports their owner stylesheets. A shared public name is not permission to put
|
|
589
|
+
several component implementations or visual contracts back into one file.
|
|
590
|
+
|
|
164
591
|
`wireTokenSearchFields` is a deliberate exception, not the rule for `wire…`
|
|
165
|
-
helpers. Its collapse behavior was
|
|
592
|
+
helpers. Its collapse behavior was _rich and error-prone_ — reveal, focus
|
|
166
593
|
transfer, Escape, empty-blur collapse, focus return — the kind of transient chrome
|
|
167
594
|
apps kept reimplementing inconsistently, so the helper owns it. Everywhere else the
|
|
168
595
|
app's state is **domain or persisted, not transient chrome, and stays app-owned**: a
|
|
169
596
|
`NavStack`'s view stack is navigation history, a `TabBar`/`TabScaffold`'s selection
|
|
170
597
|
and tab order are data, a `ResizableRegion`'s committed size and a
|
|
171
598
|
`Workbench`/`SplitView` rail's `collapsed` flag are persisted layout preferences.
|
|
172
|
-
Each helper already owns only the
|
|
599
|
+
Each helper already owns only the _ephemeral mechanics_ around that state —
|
|
173
600
|
`wireNavStack` the push/pop animation, `wireTabBars` the overflow autoscroll and
|
|
174
601
|
drag preview, `wireResizableRegions` the live drag preview — and reports committed
|
|
175
|
-
changes through callbacks. A `
|
|
602
|
+
changes through callbacks. A `ListHeader` `toggle` disclosure's `expanded` is
|
|
176
603
|
likewise app-owned: it is a one-line boolean the app already tracks and must read to
|
|
177
604
|
render the section body, so a managed helper would remove no real complexity. Reach
|
|
178
605
|
for a managed default only when the transient behavior is substantial enough that
|
|
179
606
|
hand-rolling it produces genuine, inconsistent variation.
|
|
180
607
|
|
|
608
|
+
TabBar itself owns the inline geometry around those mechanics. Its tab list is
|
|
609
|
+
the only shrinking, horizontally scrolling region; `leading`, `trailing`, and
|
|
610
|
+
`end` action regions remain fixed. Set `trailingPlacement="adjacent"` when the
|
|
611
|
+
trailing action belongs immediately after the final tab and use `end` for a
|
|
612
|
+
separate action pinned to the far edge. Applications own the action content,
|
|
613
|
+
but must not restyle TabBar descendants to recreate that allocation.
|
|
614
|
+
|
|
181
615
|
CSS, the generated wrappers that make it
|
|
182
616
|
reachable, and the registration module are the package's only declared side
|
|
183
617
|
effects.
|
|
184
618
|
|
|
619
|
+
A value-bearing component's `placeholder` prop is a first-class loading mode: the
|
|
620
|
+
component renders its own real chrome (labels, icon and action affordances,
|
|
621
|
+
container geometry) while replacing each **value** slot with a subtle, deliberately
|
|
622
|
+
unanimated `Skeleton` block and disabling its own interactive controls
|
|
623
|
+
(`aria-busy`, dropped `data-action`, disabled buttons). Only unknown values become
|
|
624
|
+
skeletons; nothing else may change. Sizes, shapes, typography, color, and opacity stay
|
|
625
|
+
identical to the populated component, so a parent composes a faithful loading view —
|
|
626
|
+
an inspector, a detail pane — from placeholder children without hand-rebuilding
|
|
627
|
+
markup. The application still owns the loading lifecycle (when to pass `placeholder`)
|
|
628
|
+
and which slots are unknown; the standalone `Skeleton` covers custom slots. A
|
|
629
|
+
`Skeleton` is `inline-block` so it sits in a text line; pass `block` to lay it out
|
|
630
|
+
as `display: block` where it stands in for a box, such as an icon, so it takes no
|
|
631
|
+
line of its own and centers in its slot. It is a
|
|
632
|
+
placeholder, not progress: use `LoadingSpinner` for known busy activity, and never
|
|
633
|
+
animate the skeleton.
|
|
634
|
+
|
|
635
|
+
A placeholder is loading, not unavailable, so it keeps the `disabled` attribute (its
|
|
636
|
+
controls stay inert and out of the keyboard order) but never shows disabled chrome.
|
|
637
|
+
`skeleton.css`, which every component that renders a skeleton loads, neutralizes generic
|
|
638
|
+
disabled styling under `[data-placeholder="true"]` — including Web Awesome's native
|
|
639
|
+
`button:disabled { opacity: 0.5; cursor: not-allowed }` when `webawesome.css` is
|
|
640
|
+
loaded — to full opacity and the non-interactive `default` cursor. That opacity reset
|
|
641
|
+
carries zero specificity, so a component's own opacity (a control hidden until
|
|
642
|
+
interaction) still wins, and each component excludes placeholders from its own
|
|
643
|
+
disabled tone and hover feedback — including hover reveals: a `ListActionRow` with
|
|
644
|
+
`trailingActionVisibility="interaction"` keeps its trailing action hidden when its
|
|
645
|
+
placeholder is hovered, as the resting live row does. The cursor is the one intentional difference from the
|
|
646
|
+
live state: a placeholder is not clickable, so it never advertises a pointer.
|
|
647
|
+
|
|
648
|
+
A control the author disabled is different: it will be unavailable once loaded, so its
|
|
649
|
+
placeholder keeps the live disabled tone. Each such control carries the component-owned
|
|
650
|
+
`data-kui-disabled="true"` marker whenever its own disabled prop is set, independent of
|
|
651
|
+
`placeholder` — `ListItem` and `ListActionRow` `disabled`, `trailingActionDisabled`,
|
|
652
|
+
a `SegmentedControl` choice's `disabled`, and `ListHeader` `actionDisabled` (on the
|
|
653
|
+
action or disclosure toggle). The placeholder reset skips the marker and components key
|
|
654
|
+
their disabled tone on it, so only the `placeholder`-only `disabled` attribute is
|
|
655
|
+
neutralized. That tone is each component's own, never Web Awesome's native
|
|
656
|
+
`button:disabled`, so an author-disabled control is dimmed with or without
|
|
657
|
+
`webawesome.css`. The marker is reserved: the extension-attribute channels
|
|
658
|
+
(`rootAttributes`, `trailingActionAttributes`, `triggerAttributes`) cannot set it. A
|
|
659
|
+
disabled placeholder still shows the `default` cursor, never `not-allowed`.
|
|
660
|
+
Chrome a component draws itself from a known prop stays live, even inside a slot that
|
|
661
|
+
also holds values. `ListItem`'s trailing slot has three inputs: the `busy` spinner is
|
|
662
|
+
component-owned chrome and stays live, while `status` text and author-supplied
|
|
663
|
+
`trailing` content are values and each become a skeleton (the component cannot tell an
|
|
664
|
+
author's chevron from a count, so all `trailing` content is treated as a value).
|
|
665
|
+
`ListActionRow`'s status line follows the same split: its `busy` spinner stays live and
|
|
666
|
+
only the `status` text becomes a skeleton.
|
|
667
|
+
`SegmentedControl` is the one placeholder without a skeleton: its choices are known
|
|
668
|
+
chrome and only the selection is unknown, so it renders every choice's live label or
|
|
669
|
+
icon at its live geometry, selects none, and neutralizes its own disabled chrome.
|
|
670
|
+
`tests/browser/placeholder-fixture.spec.ts` enforces the rule: it renders every
|
|
671
|
+
placeholder component live and as a placeholder from identical props and diffs each
|
|
672
|
+
element's geometry and computed chrome, excluding only the value slots, and checks that
|
|
673
|
+
every author-disabled control is dimmed in both renders.
|
|
674
|
+
|
|
185
675
|
Package source styles express root-scaled geometry with `remify(<px>)`; the
|
|
186
676
|
build converts it against the 16px authoring baseline and exposes only ordinary
|
|
187
677
|
`rem` CSS. Literal pixels remain for intentional hairlines, and `em` remains
|
|
@@ -197,7 +687,25 @@ Kerf JSX declaration boundary for every catalog-supported `wa-*` tag.
|
|
|
197
687
|
Consumers register only the individual Web Awesome modules they render and can
|
|
198
688
|
override `--wa-*` values after the theme import. The shared `--wa-*` values feed
|
|
199
689
|
both Web Awesome controls and Kerf's `--kui-*` foundation aliases, preventing a
|
|
200
|
-
second application palette.
|
|
690
|
+
second application palette. Without the theme, every foundation color token,
|
|
691
|
+
every elevation token (`--kui-shadow-*`), and the focus-ring color fall back to
|
|
692
|
+
the same value the theme assigns, including its `light-dark()` pair, so
|
|
693
|
+
surfaces (including the dark `surface-raised`), links (`text-link` is the brand
|
|
694
|
+
on-quiet text color, not the brand fill), tone text, fills, and raised-surface
|
|
695
|
+
shadows keep their light and dark appearance and contrast either way. The
|
|
696
|
+
theme's elevation shadows are scheme-aware: light keeps the soft Hot Sheet 2
|
|
697
|
+
alphas, and dark raises them (`--wa-shadow-s` 14% to 50% black, `-m` 11% to
|
|
698
|
+
40%, `-l` 9% to 32%) so a raised surface still separates from a near-black
|
|
699
|
+
page.
|
|
700
|
+
Kerf owns the light `brand`, `success`, and `warning` `on-quiet` values in that
|
|
701
|
+
theme layer: each keeps its hue but is dark enough to clear WCAG AA (4.5:1) on
|
|
702
|
+
the lowered page background (`--kui-color-surface-lowered`, `#f2f2f7`), not
|
|
703
|
+
only on the white surface, so toned text reads on every background a page
|
|
704
|
+
paints. It likewise owns every tone's loud pair: each `on-loud` text color
|
|
705
|
+
clears AA on its `fill-loud` in both schemes. Light brand and danger keep white
|
|
706
|
+
text on a slightly deeper fill of the same hue (`#0075db`, `#eb0005`); success
|
|
707
|
+
keeps its bright green with dark text, as warning does; the dark-mode brand and
|
|
708
|
+
danger fills keep their color with dark text.
|
|
201
709
|
|
|
202
710
|
`Select` owns its custom-element reconciliation seam. It gives each slotted
|
|
203
711
|
option icon a stable key and leaves the upgraded Web Awesome-owned slot subtree
|
|
@@ -216,4 +724,4 @@ Keep product adapters outside the package: connection-state maps, ticket empty-s
|
|
|
216
724
|
|
|
217
725
|
## Testing contract
|
|
218
726
|
|
|
219
|
-
Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
|
|
727
|
+
Each behavior has focused unit coverage and a real-browser flow through the production-backed catalog. Consumer bundle tests enforce subpath CSS reachability, transitive component styles, root/SSR isolation, optional registration boundaries, and the CSS-only Web Awesome theme boundary. `npm run check:css-ownership` rejects application selectors into Kerf or Web Awesome components, a non-minimal catalog compatibility stylesheet, or a return of the shared recipe stylesheet. Visual evidence supplements—never replaces—keyboard, focus, state, and event assertions.
|