@kerfjs/ui 4.5.0-beta.1 → 5.0.0-beta.100
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 +461 -116
- package/ai/application-ui-diagnostic-ids-v1.json +23 -1
- package/ai/application-ui-profile-sync.cjs +21 -2
- package/ai/application-ui-profile.d.ts +4 -0
- package/ai/application-ui-profile.defaults.json +63 -8
- package/ai/application-ui-profile.mjs +28 -1
- package/ai/application-ui-profile.schema.json +10 -0
- package/ai/catalog-authoring.json +13 -4
- package/ai/catalog-authoring.schema.json +52 -8
- package/ai/compile-time-contracts-v1.json +63 -16
- package/ai/compile-time-contracts-v1.schema.json +4 -1
- package/ai/component-catalog-extension.schema.json +25 -0
- package/ai/component-catalog.json +5585 -1175
- 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-catalog-v2-overrides.json → component-composition-rules.json} +281 -49
- package/ai/component-composition.d.ts +132 -0
- package/ai/component-composition.json +8729 -0
- package/ai/component-composition.schema.json +412 -0
- package/ai/components/README.md +185 -0
- package/ai/components/anchored-surface.md +99 -0
- package/ai/components/application-tabs.md +65 -0
- package/ai/components/badge.md +76 -0
- package/ai/components/chip.md +76 -0
- package/ai/components/choice-chips.md +87 -0
- package/ai/components/collapsible-panel.md +103 -0
- package/ai/components/column-track.md +78 -0
- package/ai/components/combobox.md +88 -0
- package/ai/components/composer.md +83 -0
- package/ai/components/content-item.md +98 -0
- package/ai/components/content-swap.md +78 -0
- package/ai/components/corner-status.md +88 -0
- package/ai/components/disclosure-arrow.md +77 -0
- package/ai/components/document-baseline.md +77 -0
- package/ai/components/edge-activity-indicator.md +81 -0
- package/ai/components/empty-state.md +80 -0
- package/ai/components/feedback.md +71 -0
- package/ai/components/file-picker.md +88 -0
- package/ai/components/floating-toolbar.md +82 -0
- package/ai/components/foundation.md +65 -0
- package/ai/components/framed-list.md +80 -0
- package/ai/components/grid.md +101 -0
- package/ai/components/headers.md +63 -0
- package/ai/components/icon-button.md +82 -0
- package/ai/components/icon-toggle-button.md +80 -0
- package/ai/components/layout.md +75 -0
- package/ai/components/list-action-row.md +108 -0
- package/ai/components/list-header.md +91 -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 +108 -0
- package/ai/components/list.md +125 -0
- package/ai/components/loading-spinner.md +73 -0
- package/ai/components/lucide-icon.md +97 -0
- package/ai/components/nav-stack.md +115 -0
- package/ai/components/pane.md +115 -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 +116 -0
- package/ai/components/skeleton.md +84 -0
- package/ai/components/spacer.md +86 -0
- package/ai/components/split-button.md +80 -0
- package/ai/components/split-view.md +105 -0
- package/ai/components/state-banner.md +96 -0
- package/ai/components/summary-row.md +85 -0
- package/ai/components/sunken-panel.md +79 -0
- package/ai/components/surface-scaffold.md +105 -0
- package/ai/components/tab-bar.md +114 -0
- package/ai/components/tab-navigator.md +100 -0
- package/ai/components/tabs.md +95 -0
- package/ai/components/text.md +90 -0
- package/ai/components/token-search-field.md +107 -0
- package/ai/components/toolbar-control-group.md +125 -0
- package/ai/components/toolbar-text.md +100 -0
- package/ai/components/toolbar.md +103 -0
- package/ai/components/value-table.md +80 -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 +60 -0
- package/ai/components/wa-button.md +59 -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 +120 -0
- package/ai/public-api-signatures-v1.md +3851 -441
- package/ai/skill.md +402 -70
- package/ai/webawesome-jsx-signatures-v1.md +9 -2
- package/analyzer/cli.mjs +5 -2
- package/analyzer/component-ownership.d.mts +72 -0
- package/analyzer/component-ownership.mjs +429 -0
- package/analyzer/index.d.mts +8 -0
- package/analyzer/index.mjs +1687 -49
- package/analyzer/loud-pairs.d.mts +49 -0
- package/analyzer/loud-pairs.mjs +357 -0
- package/analyzer/selectors.d.mts +21 -0
- package/analyzer/selectors.mjs +212 -0
- package/catalog-projection-cli.mjs +96 -0
- package/catalog-projection.d.mts +55 -0
- package/catalog-projection.mjs +62 -0
- package/dist/anchored-surface.d.ts +69 -0
- package/dist/anchored-surface.js +3 -0
- package/dist/anchored-surface.js.map +1 -0
- package/dist/app-tab.d.ts +39 -4
- package/dist/app-tab.js +2 -1
- package/dist/badge.d.ts +83 -0
- package/dist/badge.js +4 -0
- package/dist/badge.js.map +1 -0
- package/dist/browser/anchored-surface.js +3 -0
- package/dist/browser/badge.js +3 -0
- package/dist/browser/catalog.js +28 -0
- package/dist/browser/chip.js +3 -0
- package/dist/browser/choice-chips.js +3 -0
- package/dist/browser/collapsible-panel.js +9 -0
- package/dist/browser/column-track.js +3 -0
- package/dist/browser/combobox.js +3 -0
- package/dist/browser/composer.js +4 -0
- package/dist/browser/content-item.js +3 -0
- package/dist/browser/content-swap.js +3 -0
- package/dist/browser/corner-status.js +3 -0
- package/dist/browser/edge-activity-indicator.js +3 -0
- package/dist/browser/file-picker.js +3 -0
- package/dist/browser/framed-list.js +3 -0
- package/dist/browser/grid.js +3 -0
- package/dist/browser/icon-button.js +4 -0
- package/dist/browser/icon-toggle-button.js +4 -0
- package/dist/browser/list-action-row.js +2 -0
- package/dist/browser/list-header.js +3 -1
- package/dist/browser/list-item.js +1 -0
- package/dist/browser/nav-stack.js +11 -0
- package/dist/browser/popup-menu.js +3 -0
- package/dist/browser/row.js +3 -0
- package/dist/browser/segmented-control.js +0 -1
- package/dist/browser/select.js +2 -1
- package/dist/browser/spacer.js +3 -0
- package/dist/browser/split-button.js +5 -0
- package/dist/browser/split-view.js +13 -0
- package/dist/browser/state-banner.js +1 -0
- package/dist/browser/summary-row.js +3 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/browser/tab-navigator.js +4 -0
- package/dist/browser/text.js +3 -0
- package/dist/browser/toolbar-control-group.js +1 -0
- package/dist/browser/workbench.js +14 -0
- package/dist/catalog-resources.d.ts +17 -1
- package/dist/catalog-resources.js +5 -5
- package/dist/catalog-resources.js.map +1 -1
- package/dist/catalog.d.ts +123 -121
- package/dist/catalog.js +598 -269
- package/dist/catalog.js.map +1 -1
- package/dist/chip.d.ts +69 -0
- package/dist/chip.js +3 -0
- package/dist/chip.js.map +1 -0
- package/dist/choice-chips.d.ts +82 -0
- package/dist/choice-chips.js +3 -0
- package/dist/choice-chips.js.map +1 -0
- package/dist/chunk-2GOCOLQL.js +270 -0
- package/dist/chunk-2GOCOLQL.js.map +1 -0
- package/dist/chunk-2MSPNRWJ.js +82 -0
- package/dist/chunk-2MSPNRWJ.js.map +1 -0
- package/dist/chunk-34U4ANDJ.js +119 -0
- package/dist/chunk-34U4ANDJ.js.map +1 -0
- package/dist/chunk-3GLYIIFR.js +230 -0
- package/dist/chunk-3GLYIIFR.js.map +1 -0
- package/dist/{chunk-Y6LYKFXY.js → chunk-3VXDSIBJ.js} +7 -4
- package/dist/chunk-3VXDSIBJ.js.map +1 -0
- package/dist/chunk-3WYREXW4.js +120 -0
- package/dist/chunk-3WYREXW4.js.map +1 -0
- package/dist/chunk-4UB5Z3ZZ.js +68 -0
- package/dist/chunk-4UB5Z3ZZ.js.map +1 -0
- package/dist/chunk-6C6DLP3W.js +31 -0
- package/dist/chunk-6C6DLP3W.js.map +1 -0
- package/dist/chunk-7IUEBNCO.js +108 -0
- package/dist/chunk-7IUEBNCO.js.map +1 -0
- package/dist/{chunk-QO55FN2Y.js → chunk-AN5IWMTM.js} +7 -3
- package/dist/chunk-AN5IWMTM.js.map +1 -0
- package/dist/chunk-AV7CPAPT.js +82 -0
- package/dist/chunk-AV7CPAPT.js.map +1 -0
- package/dist/{chunk-PX3YSS5C.js → chunk-B53PS2LE.js} +5 -3
- package/dist/chunk-B53PS2LE.js.map +1 -0
- package/dist/chunk-CA7LNX3J.js +44 -0
- package/dist/chunk-CA7LNX3J.js.map +1 -0
- package/dist/chunk-CEJ5FK6G.js +288 -0
- package/dist/chunk-CEJ5FK6G.js.map +1 -0
- package/dist/chunk-CMETHPKR.js +175 -0
- package/dist/chunk-CMETHPKR.js.map +1 -0
- package/dist/chunk-CMLPFIC5.js +46 -0
- package/dist/chunk-CMLPFIC5.js.map +1 -0
- package/dist/{chunk-RKVQEH4J.js → chunk-CVD5IZGB.js} +10 -5
- package/dist/chunk-CVD5IZGB.js.map +1 -0
- package/dist/chunk-CXZXHZTR.js +514 -0
- package/dist/chunk-CXZXHZTR.js.map +1 -0
- package/dist/chunk-D5RGM3XA.js +38 -0
- package/dist/chunk-D5RGM3XA.js.map +1 -0
- package/dist/{chunk-KWWR5VMS.js → chunk-DZJ4GBSP.js} +19 -5
- package/dist/chunk-DZJ4GBSP.js.map +1 -0
- package/dist/chunk-EIET4QLK.js +51 -0
- package/dist/chunk-EIET4QLK.js.map +1 -0
- package/dist/chunk-ELCMSQNJ.js +49 -0
- package/dist/chunk-ELCMSQNJ.js.map +1 -0
- package/dist/chunk-EOO6PYGF.js +162 -0
- package/dist/chunk-EOO6PYGF.js.map +1 -0
- package/dist/chunk-ETCWQLJV.js +85 -0
- package/dist/chunk-ETCWQLJV.js.map +1 -0
- package/dist/chunk-FDZNYD4C.js +138 -0
- package/dist/chunk-FDZNYD4C.js.map +1 -0
- package/dist/chunk-FR76ZJQC.js +90 -0
- package/dist/chunk-FR76ZJQC.js.map +1 -0
- package/dist/chunk-G3J7JDP6.js +29 -0
- package/dist/chunk-G3J7JDP6.js.map +1 -0
- package/dist/chunk-GS2QD3N7.js +14 -0
- package/dist/chunk-GS2QD3N7.js.map +1 -0
- package/dist/chunk-HGV7J4T6.js +86 -0
- package/dist/chunk-HGV7J4T6.js.map +1 -0
- package/dist/chunk-HLDRH23D.js +84 -0
- package/dist/chunk-HLDRH23D.js.map +1 -0
- package/dist/chunk-HQZYKJ56.js +302 -0
- package/dist/chunk-HQZYKJ56.js.map +1 -0
- package/dist/chunk-HZPHCSCS.js +95 -0
- package/dist/chunk-HZPHCSCS.js.map +1 -0
- package/dist/chunk-IKS72C6P.js +53 -0
- package/dist/chunk-IKS72C6P.js.map +1 -0
- package/dist/chunk-IM3GKYOG.js +202 -0
- package/dist/chunk-IM3GKYOG.js.map +1 -0
- package/dist/{chunk-JRKSK2HX.js → chunk-INI4WDWC.js} +53 -7
- package/dist/chunk-INI4WDWC.js.map +1 -0
- package/dist/chunk-IQSRHXZR.js +164 -0
- package/dist/chunk-IQSRHXZR.js.map +1 -0
- package/dist/{chunk-M7JBER5U.js → chunk-JOR5LGYE.js} +18 -4
- package/dist/chunk-JOR5LGYE.js.map +1 -0
- package/dist/chunk-K4AT3V3J.js +545 -0
- package/dist/chunk-K4AT3V3J.js.map +1 -0
- package/dist/chunk-KCS6NJ3O.js +82 -0
- package/dist/chunk-KCS6NJ3O.js.map +1 -0
- package/dist/{chunk-SRSJO5QE.js → chunk-KH4KEMSP.js} +34 -3
- package/dist/chunk-KH4KEMSP.js.map +1 -0
- package/dist/chunk-LL45C7BB.js +122 -0
- package/dist/chunk-LL45C7BB.js.map +1 -0
- package/dist/chunk-LOSRXZAH.js +100 -0
- package/dist/chunk-LOSRXZAH.js.map +1 -0
- package/dist/{chunk-7KEUJIIC.js → chunk-MF6ZUUJZ.js} +93 -11
- package/dist/chunk-MF6ZUUJZ.js.map +1 -0
- package/dist/chunk-MHMWQ7RB.js +19 -0
- package/dist/chunk-MHMWQ7RB.js.map +1 -0
- package/dist/chunk-MJ5RU6XT.js +173 -0
- package/dist/chunk-MJ5RU6XT.js.map +1 -0
- package/dist/chunk-MXNIVEVL.js +48 -0
- package/dist/chunk-MXNIVEVL.js.map +1 -0
- package/dist/{chunk-IJBSZ4NX.js → chunk-NS2TBYM4.js} +8 -5
- package/dist/chunk-NS2TBYM4.js.map +1 -0
- package/dist/chunk-PIVY32AE.js +140 -0
- package/dist/chunk-PIVY32AE.js.map +1 -0
- package/dist/chunk-PYBBYSZ3.js +526 -0
- package/dist/chunk-PYBBYSZ3.js.map +1 -0
- package/dist/chunk-QDSZTQXL.js +28 -0
- package/dist/chunk-QDSZTQXL.js.map +1 -0
- package/dist/chunk-QH5KOFNS.js +39 -0
- package/dist/chunk-QH5KOFNS.js.map +1 -0
- package/dist/chunk-QIG4IGUP.js +139 -0
- package/dist/chunk-QIG4IGUP.js.map +1 -0
- package/dist/chunk-QLA25V2K.js +493 -0
- package/dist/chunk-QLA25V2K.js.map +1 -0
- package/dist/chunk-QROYYGWU.js +52 -0
- package/dist/chunk-QROYYGWU.js.map +1 -0
- package/dist/chunk-QYMJHS4K.js +36 -0
- package/dist/chunk-QYMJHS4K.js.map +1 -0
- package/dist/chunk-RHD7RKGI.js +176 -0
- package/dist/chunk-RHD7RKGI.js.map +1 -0
- package/dist/chunk-S2XULQEK.js +52 -0
- package/dist/chunk-S2XULQEK.js.map +1 -0
- package/dist/{chunk-LPOMRC4C.js → chunk-S3ECMF23.js} +11 -3
- package/dist/chunk-S3ECMF23.js.map +1 -0
- package/dist/chunk-S4Y3YTAI.js +35 -0
- package/dist/chunk-S4Y3YTAI.js.map +1 -0
- package/dist/chunk-S4ZGTDSG.js +18 -0
- package/dist/chunk-S4ZGTDSG.js.map +1 -0
- package/dist/{chunk-PSKN344N.js → chunk-T4WJ5VGP.js} +63 -12
- package/dist/chunk-T4WJ5VGP.js.map +1 -0
- package/dist/chunk-TDMHA7C3.js +251 -0
- package/dist/chunk-TDMHA7C3.js.map +1 -0
- package/dist/{chunk-Y45PPBDV.js → chunk-TGLUDQP2.js} +47 -14
- package/dist/chunk-TGLUDQP2.js.map +1 -0
- package/dist/chunk-TLMMFQWM.js +222 -0
- package/dist/chunk-TLMMFQWM.js.map +1 -0
- package/dist/chunk-U6QYTMDB.js +85 -0
- package/dist/chunk-U6QYTMDB.js.map +1 -0
- package/dist/chunk-UMKV7YVQ.js +20 -0
- package/dist/chunk-UMKV7YVQ.js.map +1 -0
- package/dist/chunk-VFYO3UGZ.js +45 -0
- package/dist/chunk-VFYO3UGZ.js.map +1 -0
- package/dist/chunk-W4IK7AWD.js +73 -0
- package/dist/chunk-W4IK7AWD.js.map +1 -0
- package/dist/chunk-WVS6CUCT.js +48 -0
- package/dist/chunk-WVS6CUCT.js.map +1 -0
- package/dist/chunk-Y6KT7ZTR.js +109 -0
- package/dist/chunk-Y6KT7ZTR.js.map +1 -0
- package/dist/chunk-YMUIQRWK.js +44 -0
- package/dist/chunk-YMUIQRWK.js.map +1 -0
- package/dist/chunk-YOA5W5ZH.js +807 -0
- package/dist/chunk-YOA5W5ZH.js.map +1 -0
- package/dist/chunk-YQ2AC4E2.js +59 -0
- package/dist/chunk-YQ2AC4E2.js.map +1 -0
- package/dist/chunk-ZKKO4MHC.js +25 -0
- package/dist/chunk-ZKKO4MHC.js.map +1 -0
- package/dist/chunk-ZNROKDSZ.js +54 -0
- package/dist/chunk-ZNROKDSZ.js.map +1 -0
- package/dist/collapsible-panel.d.ts +96 -17
- package/dist/collapsible-panel.js +104 -27
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/column-track.d.ts +41 -0
- package/dist/column-track.js +4 -0
- package/dist/column-track.js.map +1 -0
- package/dist/combobox.d.ts +40 -0
- package/dist/combobox.js +3 -0
- package/dist/combobox.js.map +1 -0
- package/dist/composer.d.ts +62 -0
- package/dist/composer.js +5 -0
- package/dist/composer.js.map +1 -0
- package/dist/content-item.d.ts +116 -0
- package/dist/content-item.js +4 -0
- package/dist/content-item.js.map +1 -0
- package/dist/content-swap.d.ts +34 -0
- package/dist/content-swap.js +3 -0
- package/dist/content-swap.js.map +1 -0
- package/dist/corner-status.d.ts +36 -0
- package/dist/corner-status.js +3 -0
- package/dist/corner-status.js.map +1 -0
- package/dist/css-values.d.ts +127 -0
- package/dist/css-values.js +3 -0
- package/dist/css-values.js.map +1 -0
- package/dist/device-class.js +1 -1
- package/dist/device-class.js.map +1 -1
- package/dist/disclosure-arrow.d.ts +6 -1
- package/dist/disclosure-arrow.js +2 -1
- package/dist/edge-activity-indicator.d.ts +28 -0
- package/dist/edge-activity-indicator.js +3 -0
- package/dist/edge-activity-indicator.js.map +1 -0
- package/dist/empty-state.d.ts +5 -2
- package/dist/empty-state.js +2 -1
- package/dist/extension-attributes-mu8MFUl0.d.ts +13 -0
- package/dist/file-picker.d.ts +47 -0
- package/dist/file-picker.js +3 -0
- package/dist/file-picker.js.map +1 -0
- package/dist/flex-alignment-4ms8ZbV8.d.ts +5 -0
- package/dist/floating-toolbar.d.ts +29 -6
- package/dist/floating-toolbar.js +1 -1
- package/dist/framed-list.d.ts +47 -0
- package/dist/framed-list.js +4 -0
- package/dist/framed-list.js.map +1 -0
- package/dist/grid.d.ts +58 -0
- package/dist/grid.js +6 -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/icon-button.d.ts +46 -0
- package/dist/icon-button.js +6 -0
- package/dist/icon-button.js.map +1 -0
- package/dist/icon-toggle-button.d.ts +42 -0
- package/dist/icon-toggle-button.js +6 -0
- package/dist/icon-toggle-button.js.map +1 -0
- package/dist/index.d.ts +59 -20
- package/dist/index.js +66 -29
- package/dist/list-action-row.d.ts +69 -12
- package/dist/list-action-row.js +5 -1
- package/dist/list-header.d.ts +36 -2
- package/dist/list-header.js +4 -1
- package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
- package/dist/list-inset-control.d.ts +10 -4
- package/dist/list-inset-control.js +1 -1
- package/dist/list-inset-text.d.ts +17 -12
- package/dist/list-inset-text.js +2 -1
- package/dist/list-item.d.ts +49 -5
- package/dist/list-item.js +4 -1
- package/dist/list.d.ts +121 -12
- package/dist/list.js +5 -1
- package/dist/loading-spinner.d.ts +12 -2
- package/dist/loading-spinner.js +2 -1
- package/dist/lucide-icon.d.ts +15 -3
- package/dist/lucide-icon.js +2 -1
- package/dist/nav-stack-VXTumzKa.d.ts +158 -0
- package/dist/nav-stack.d.ts +15 -38
- package/dist/nav-stack.js +13 -1
- package/dist/pane.d.ts +111 -7
- package/dist/pane.js +2 -1
- package/dist/panel-toolbar-vg6Ir5Dy.d.ts +77 -0
- package/dist/popup-menu-register.d.ts +10 -0
- package/dist/popup-menu-register.js +336 -0
- package/dist/popup-menu-register.js.map +1 -0
- package/dist/popup-menu.d.ts +125 -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 +53 -0
- package/dist/row.js +7 -0
- package/dist/row.js.map +1 -0
- package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
- package/dist/segmented-control.d.ts +7 -4
- package/dist/segmented-control.js +1 -2
- package/dist/select-register.js +255 -3
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +95 -6
- package/dist/select.js +4 -1
- package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
- package/dist/semantic-tone-CdW013KF.d.ts +4 -0
- package/dist/sides-BPSWde0A.d.ts +4 -0
- package/dist/skeleton.d.ts +14 -7
- package/dist/skeleton.js +2 -1
- package/dist/spacer.d.ts +18 -0
- package/dist/spacer.js +4 -0
- package/dist/spacer.js.map +1 -0
- package/dist/split-button.d.ts +57 -0
- package/dist/split-button.js +7 -0
- package/dist/split-button.js.map +1 -0
- package/dist/split-view.d.ts +63 -6
- package/dist/split-view.js +88 -9
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +37 -6
- package/dist/state-banner.js +4 -1
- package/dist/styles/anchored-surface.css +41 -0
- package/dist/styles/app-tab.css +232 -0
- package/dist/styles/badge.css +145 -0
- package/dist/styles/catalog/components/catalog-example-stack.css +14 -0
- package/dist/styles/catalog/components/catalog-example.css +204 -0
- package/dist/styles/catalog/components/catalog-stage.css +61 -0
- package/dist/styles/catalog/components/catalog.css +26 -0
- package/dist/styles/catalog.css +5 -575
- package/dist/styles/chip.css +208 -0
- package/dist/styles/choice-chips.css +154 -0
- package/dist/styles/collapsible-panel.css +450 -16
- package/dist/styles/column-track.css +57 -0
- package/dist/styles/combobox.css +113 -0
- package/dist/styles/components/actions/floating-toolbar/floating-toolbar.css +119 -0
- package/dist/styles/components/actions/icon-button/icon-button.css +22 -0
- package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +83 -0
- package/dist/styles/components/actions/popup-menu/popup-menu.css +370 -0
- package/dist/styles/components/actions/split-button/split-button.css +95 -0
- package/dist/styles/components/actions/toolbar/toolbar.css +443 -0
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +1069 -0
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +269 -0
- package/dist/styles/components/collections/framed-list/framed-list.css +47 -0
- package/dist/styles/components/collections/list/list.css +250 -0
- package/dist/styles/components/collections/list-action-row/list-action-row.css +466 -0
- package/dist/styles/components/collections/list-header/list-header.css +229 -0
- package/dist/styles/components/collections/list-inset-control/list-inset-control.css +30 -0
- package/dist/styles/components/collections/list-inset-text/list-inset-text.css +29 -0
- package/dist/styles/components/collections/list-item/list-item.css +461 -0
- package/dist/styles/components/collections/summary-row/summary-row.css +161 -0
- package/dist/styles/components/data-display/value-table/value-table.css +183 -0
- package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +41 -0
- package/dist/styles/components/feedback/badge/badge.css +145 -0
- package/dist/styles/components/feedback/chip/chip.css +208 -0
- package/dist/styles/components/feedback/corner-status/corner-status.css +60 -0
- package/dist/styles/components/feedback/edge-activity-indicator/edge-activity-indicator.css +127 -0
- package/dist/styles/components/feedback/empty-state/empty-state.css +47 -0
- package/dist/styles/components/feedback/loading-spinner/loading-spinner.css +25 -0
- package/dist/styles/components/feedback/skeleton/skeleton.css +92 -0
- package/dist/styles/components/feedback/state-banner/state-banner.css +297 -0
- package/dist/styles/components/forms/choice-chips/choice-chips.css +154 -0
- package/dist/styles/components/forms/combobox/combobox.css +113 -0
- package/dist/styles/components/forms/composer/composer.css +100 -0
- package/dist/styles/components/forms/file-picker/file-picker.css +81 -0
- package/dist/styles/components/forms/segmented-control/segmented-control.css +196 -0
- package/dist/styles/components/forms/select/select.css +455 -0
- package/dist/styles/components/forms/token-search-field/token-search-field.css +432 -0
- package/dist/styles/components/layout/collapsible-panel/collapsible-panel.css +580 -0
- package/dist/styles/components/layout/column-track/column-track.css +57 -0
- package/dist/styles/components/layout/content-swap/content-swap.css +154 -0
- package/dist/styles/components/layout/grid/grid.css +88 -0
- package/dist/styles/components/layout/pane/pane.css +382 -0
- package/dist/styles/components/layout/resizable-region/resizable-region.css +545 -0
- package/dist/styles/components/layout/row/row.css +114 -0
- package/dist/styles/components/layout/spacer/spacer.css +11 -0
- package/dist/styles/components/layout/split-view/split-view.css +146 -0
- package/dist/styles/components/layout/workbench/workbench.css +1086 -0
- package/dist/styles/components/media/lucide-icon/lucide-icon.css +15 -0
- package/dist/styles/components/navigation/app-tab/app-tab.css +384 -0
- package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +23 -0
- package/dist/styles/components/navigation/nav-stack/nav-stack.css +342 -0
- package/dist/styles/components/navigation/tab-bar/tab-bar.css +197 -0
- package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +325 -0
- package/dist/styles/components/surfaces/content-item/content-item.css +138 -0
- package/dist/styles/components/surfaces/sunken-panel/sunken-panel.css +31 -0
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +425 -0
- package/dist/styles/components/typography/text/text.css +220 -0
- package/dist/styles/composer.css +100 -0
- package/dist/styles/content-item.css +138 -0
- package/dist/styles/content-swap.css +154 -0
- package/dist/styles/corner-status.css +60 -0
- package/dist/styles/document.css +98 -0
- package/dist/styles/edge-activity-indicator.css +127 -0
- package/dist/styles/file-picker.css +81 -0
- package/dist/styles/floating-toolbar.css +87 -6
- package/dist/styles/foundation.css +254 -53
- package/dist/styles/framed-list.css +47 -0
- package/dist/styles/grid.css +88 -0
- package/dist/styles/icon-button.css +22 -0
- package/dist/styles/icon-toggle-button.css +83 -0
- package/dist/styles/layout.css +1 -21
- package/dist/styles/list-action-row.css +323 -17
- package/dist/styles/list-header.css +128 -59
- package/dist/styles/list-inset-control.css +25 -2
- package/dist/styles/list-inset-text.css +27 -12
- package/dist/styles/list-item.css +371 -33
- package/dist/styles/list.css +214 -7
- package/dist/styles/loading-spinner.css +4 -0
- package/dist/styles/lucide-icon.css +9 -0
- package/dist/styles/nav-stack.css +280 -49
- package/dist/styles/pane.css +322 -2
- package/dist/styles/popup-menu.css +370 -0
- package/dist/styles/resizable-region.css +438 -4
- package/dist/styles/row.css +114 -0
- package/dist/styles/segmented-control.css +34 -3
- package/dist/styles/select.css +338 -23
- package/dist/styles/skeleton.css +64 -3
- package/dist/styles/spacer.css +11 -0
- package/dist/styles/split-button.css +95 -0
- package/dist/styles/split-view.css +114 -3
- package/dist/styles/state-banner.css +141 -42
- package/dist/styles/styles.css +22 -1
- package/dist/styles/summary-row.css +161 -0
- package/dist/styles/sunken-panel.css +13 -4
- package/dist/styles/surface-scaffold.css +425 -0
- package/dist/styles/tab-bar.css +161 -9
- package/dist/styles/tab-navigator.css +325 -0
- package/dist/styles/text.css +220 -0
- package/dist/styles/token-search-field.css +202 -59
- package/dist/styles/toolbar-control-group.css +886 -42
- package/dist/styles/toolbar-text.css +184 -7
- package/dist/styles/toolbar.css +363 -17
- package/dist/styles/value-table.css +115 -7
- package/dist/styles/webawesome.css +282 -20
- package/dist/styles/workbench.css +999 -7
- package/dist/summary-row.d.ts +56 -0
- package/dist/summary-row.js +4 -0
- package/dist/summary-row.js.map +1 -0
- package/dist/sunken-panel.d.ts +23 -4
- package/dist/sunken-panel.js +2 -1
- package/dist/surface-scaffold-register.d.ts +9 -0
- package/dist/surface-scaffold-register.js +151 -0
- package/dist/surface-scaffold-register.js.map +1 -0
- package/dist/surface-scaffold.d.ts +170 -0
- package/dist/surface-scaffold.js +4 -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-navigator.d.ts +114 -0
- package/dist/tab-navigator.js +102 -0
- package/dist/tab-navigator.js.map +1 -0
- package/dist/text.d.ts +98 -0
- package/dist/text.js +3 -0
- package/dist/text.js.map +1 -0
- package/dist/token-search-field.d.ts +3 -59
- package/dist/token-search-field.js +2 -1
- package/dist/token-search-model-aYR0YAei.d.ts +184 -0
- 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 +87 -4
- package/dist/toolbar-control-group.js +3 -1
- package/dist/toolbar-text.d.ts +46 -12
- package/dist/toolbar-text.js +2 -1
- package/dist/toolbar.d.ts +71 -9
- package/dist/toolbar.js +1 -1
- package/dist/types-CVgIwSdq.d.ts +189 -0
- package/dist/value-table.d.ts +30 -4
- package/dist/value-table.js +2 -1
- package/dist/webawesome.d.ts +8 -1
- package/dist/wire-catalog.d.ts +88 -13
- package/dist/wire-catalog.js +240 -206
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-comboboxes.d.ts +26 -0
- package/dist/wire-comboboxes.js +3 -0
- package/dist/wire-comboboxes.js.map +1 -0
- package/dist/wire-composers.d.ts +16 -0
- package/dist/wire-composers.js +3 -0
- package/dist/wire-composers.js.map +1 -0
- package/dist/wire-content-items.d.ts +11 -0
- package/dist/wire-content-items.js +139 -0
- package/dist/wire-content-items.js.map +1 -0
- package/dist/wire-corner-status.d.ts +11 -0
- package/dist/wire-corner-status.js +3 -0
- package/dist/wire-corner-status.js.map +1 -0
- package/dist/wire-file-pickers.d.ts +26 -0
- package/dist/wire-file-pickers.js +3 -0
- package/dist/wire-file-pickers.js.map +1 -0
- package/dist/wire-list-focus-scroll.d.ts +16 -0
- package/dist/wire-list-focus-scroll.js +3 -0
- package/dist/wire-list-focus-scroll.js.map +1 -0
- package/dist/wire-list-reorder.d.ts +41 -0
- package/dist/wire-list-reorder.js +3 -0
- package/dist/wire-list-reorder.js.map +1 -0
- package/dist/wire-nav-stack.d.ts +4 -1
- package/dist/wire-nav-stack.js +312 -16
- 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 +87 -0
- package/dist/wire-scroll-dividers.js +3 -0
- package/dist/wire-scroll-dividers.js.map +1 -0
- package/dist/wire-sidebar.d.ts +24 -4
- package/dist/wire-sidebar.js +122 -19
- package/dist/wire-sidebar.js.map +1 -1
- package/dist/wire-tab-bars.d.ts +1 -0
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-navigator.d.ts +13 -0
- package/dist/wire-tab-navigator.js +153 -0
- package/dist/wire-tab-navigator.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +5 -1
- package/dist/wire-token-search-fields.js +2 -1
- package/dist/wire-toolbar-visibility.d.ts +13 -0
- package/dist/wire-toolbar-visibility.js +3 -0
- package/dist/wire-toolbar-visibility.js.map +1 -0
- package/dist/wire-workbench.d.ts +116 -0
- package/dist/wire-workbench.js +6 -0
- package/dist/wire-workbench.js.map +1 -0
- package/dist/workbench.d.ts +253 -10
- package/dist/workbench.js +20 -62
- package/dist/workbench.js.map +1 -1
- package/docs/accessibility.md +617 -32
- package/docs/anchored-surface.md +101 -0
- package/docs/app-layouts.md +159 -10
- package/docs/apple-hig.md +2 -0
- package/docs/catalog.md +403 -110
- package/docs/collapsible-panel.md +272 -16
- package/docs/component-contract.md +700 -79
- package/docs/component-integration.md +75 -0
- package/docs/component-selection.md +908 -79
- package/docs/composer.md +143 -0
- package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -0
- package/docs/design/templates/choice-chips/color-palette.svg +1 -0
- package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -0
- package/docs/design/templates/choice-chips/compact-icons.svg +1 -0
- package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
- package/docs/design/templates/choice-chips/multiple.svg +1 -0
- package/docs/design/templates/choice-chips-dark.svg +1 -0
- package/docs/design/templates/choice-chips.svg +1 -0
- package/docs/design/templates/composer/chat-dark.svg +1 -0
- package/docs/design/templates/composer/chat.svg +1 -0
- package/docs/design/templates/composer/prompt-dark.svg +1 -0
- package/docs/design/templates/composer/prompt.svg +1 -0
- package/docs/design/templates/composer-dark.svg +1 -0
- package/docs/design/templates/composer.svg +1 -0
- package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
- package/docs/design/templates/empty-state/filtered.svg +1 -1
- package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
- package/docs/design/templates/empty-state/with-action.svg +1 -1
- package/docs/design/templates/empty-state-dark.svg +1 -1
- package/docs/design/templates/empty-state.svg +1 -1
- package/docs/design/templates/list/compact-dark.svg +1 -1
- package/docs/design/templates/list/compact.svg +1 -1
- package/docs/design/templates/list/stack-dark.svg +1 -1
- package/docs/design/templates/list/stack.svg +1 -1
- package/docs/design/templates/list-action-row/default-dark.svg +1 -1
- package/docs/design/templates/list-action-row/default.svg +1 -1
- package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
- package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
- package/docs/design/templates/list-action-row/selected.svg +1 -1
- package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -0
- package/docs/design/templates/list-action-row/trailing-menu.svg +1 -0
- package/docs/design/templates/list-action-row-dark.svg +1 -1
- package/docs/design/templates/list-action-row.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-header/action-dark.svg +1 -1
- package/docs/design/templates/list-header/action.svg +1 -1
- package/docs/design/templates/list-header/count-dark.svg +1 -1
- package/docs/design/templates/list-header/count.svg +1 -1
- 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/size-l-dark.svg +1 -0
- package/docs/design/templates/list-header/size-l.svg +1 -0
- package/docs/design/templates/list-header/size-m-dark.svg +1 -0
- package/docs/design/templates/list-header/size-m.svg +1 -0
- package/docs/design/templates/list-header/size-xl-dark.svg +1 -0
- package/docs/design/templates/list-header/size-xl.svg +1 -0
- package/docs/design/templates/list-header/size-xs-dark.svg +1 -0
- package/docs/design/templates/list-header/size-xs.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -1
- package/docs/design/templates/list-header/toggle-collapsed.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/list-item/default-dark.svg +1 -1
- package/docs/design/templates/list-item/default.svg +1 -1
- package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
- package/docs/design/templates/list-item/icon-tile.svg +1 -0
- package/docs/design/templates/list-item/multiline-dark.svg +1 -1
- package/docs/design/templates/list-item/multiline.svg +1 -1
- package/docs/design/templates/list-item/selected-dark.svg +1 -1
- package/docs/design/templates/list-item/selected.svg +1 -1
- package/docs/design/templates/list-item/trailing-dark.svg +1 -1
- package/docs/design/templates/list-item/trailing.svg +1 -1
- package/docs/design/templates/list-item-dark.svg +1 -1
- package/docs/design/templates/list-item.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
- package/docs/design/templates/segmented-control/equal.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small.svg +1 -1
- package/docs/design/templates/segmented-control-dark.svg +1 -1
- package/docs/design/templates/segmented-control.svg +1 -1
- package/docs/design/templates/skeleton-dark.svg +1 -1
- package/docs/design/templates/skeleton.svg +1 -1
- package/docs/design/templates/state-banner/danger-dark.svg +1 -1
- package/docs/design/templates/state-banner/danger.svg +1 -1
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
- package/docs/design/templates/state-banner/info-badge.svg +1 -1
- package/docs/design/templates/state-banner/info-dark.svg +1 -1
- package/docs/design/templates/state-banner/info.svg +1 -1
- package/docs/design/templates/state-banner/strip-dark.svg +1 -0
- package/docs/design/templates/state-banner/strip.svg +1 -0
- package/docs/design/templates/state-banner/success-dark.svg +1 -1
- package/docs/design/templates/state-banner/success.svg +1 -1
- package/docs/design/templates/state-banner/warning-dark.svg +1 -1
- package/docs/design/templates/state-banner/warning.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
- package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
- package/docs/design/templates/tab-bar-dark.svg +1 -1
- package/docs/design/templates/tab-bar.svg +1 -1
- package/docs/design/templates/token-search-field/empty-dark.svg +1 -1
- package/docs/design/templates/token-search-field/empty.svg +1 -1
- package/docs/design/templates/token-search-field/tokens-dark.svg +1 -1
- package/docs/design/templates/token-search-field/tokens.svg +1 -1
- package/docs/design/templates/token-search-field-dark.svg +1 -1
- package/docs/design/templates/token-search-field.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
- package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
- package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
- package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -1
- package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -1
- package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default.svg +1 -1
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/large.svg +1 -1
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/small.svg +1 -1
- package/docs/design/templates/toolbar-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-text.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/design/templates/value-table/details-dark.svg +1 -1
- package/docs/design/templates/value-table/details.svg +1 -1
- package/docs/design/templates/value-table-dark.svg +1 -1
- package/docs/design/templates/value-table.svg +1 -1
- package/docs/design/templates.md +19 -9
- package/docs/design-philosophy.md +58 -11
- package/docs/device-class.md +2 -1
- package/docs/document-baseline.md +93 -0
- package/docs/examples/application-ui-profile.json +8 -8
- package/docs/examples/command-palette-adapter.tsx +9 -7
- package/docs/examples/component-catalog-extension.json +8 -1
- package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +8 -9
- package/docs/layout.md +764 -40
- package/docs/nav-stack.md +275 -11
- package/docs/recipes.md +125 -69
- package/docs/split-view.md +94 -5
- package/docs/sunken-panel.md +54 -1
- package/docs/surface-scaffold.md +270 -0
- package/docs/tab-navigator.md +255 -0
- package/docs/type-contracts.md +57 -22
- package/docs/ui-analyzer.md +334 -14
- package/docs/ui-doctor.md +207 -10
- package/docs/ui-evaluator.md +17 -0
- package/docs/ux-demo.md +47 -16
- package/docs/webawesome-theme.md +148 -14
- package/docs/workbench.md +600 -11
- package/docs/writing.md +152 -0
- package/doctor/cli.mjs +5 -0
- package/doctor/component-style-checks.mjs +457 -0
- package/doctor/config.schema.json +26 -0
- package/doctor/copy-capitalization-checks.mjs +591 -0
- package/doctor/eslint-diagnostics.d.mts +16 -0
- package/doctor/eslint-diagnostics.mjs +17 -0
- package/doctor/index.d.mts +6 -0
- package/doctor/index.mjs +214 -47
- package/evaluator/index.mjs +73 -8
- package/llms.txt +702 -56
- package/package.json +256 -25
- package/scripts/component-catalog-extension-validation.mjs +28 -0
- package/traversal-exclusions.mjs +60 -1
- package/ux-demo/recipes/app-shell.tsx +181 -189
- package/ux-demo/recipes/collapsible-sidebar.tsx +177 -139
- package/ux-demo/recipes/compact-toolbar.tsx +120 -101
- package/ux-demo/recipes/composer-form.tsx +86 -62
- package/ux-demo/recipes/list-detail-dialog.tsx +219 -114
- package/ux-demo/recipes/list-workspace-states.tsx +95 -80
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +157 -117
- package/ux-demo/recipes/mount-recipe.ts +0 -5
- package/ux-demo/recipes/navigation-sidebar.tsx +98 -83
- package/ux-demo/recipes/navigation-stack.tsx +42 -29
- package/ux-demo/recipes/types.ts +14 -1
- package/ux-demo/recipes/workspace-header.tsx +77 -51
- package/vite-ux-review.d.mts +83 -0
- package/vite-ux-review.mjs +120 -0
- package/ai/component-catalog-extension-v2.d.ts +0 -7
- package/ai/component-catalog-extension-v2.schema.json +0 -7
- package/ai/component-catalog-v2.d.ts +0 -67
- package/ai/component-catalog-v2.json +0 -4675
- package/ai/component-catalog-v2.schema.json +0 -246
- package/dist/browser/panel-header.js +0 -7
- package/dist/chunk-5VTB2BKP.js +0 -35
- package/dist/chunk-5VTB2BKP.js.map +0 -1
- package/dist/chunk-6WTETUZ6.js +0 -21
- package/dist/chunk-6WTETUZ6.js.map +0 -1
- package/dist/chunk-7KEUJIIC.js.map +0 -1
- package/dist/chunk-7XRDUG4Y.js +0 -58
- package/dist/chunk-7XRDUG4Y.js.map +0 -1
- package/dist/chunk-B3A3IVO5.js +0 -83
- package/dist/chunk-B3A3IVO5.js.map +0 -1
- package/dist/chunk-DPDBVKNA.js +0 -113
- package/dist/chunk-DPDBVKNA.js.map +0 -1
- package/dist/chunk-FEAMR7S4.js +0 -68
- package/dist/chunk-FEAMR7S4.js.map +0 -1
- package/dist/chunk-FEY65TBV.js +0 -15
- package/dist/chunk-FEY65TBV.js.map +0 -1
- package/dist/chunk-IJBSZ4NX.js.map +0 -1
- package/dist/chunk-J5BFYY7Q.js +0 -35
- package/dist/chunk-J5BFYY7Q.js.map +0 -1
- package/dist/chunk-JRKSK2HX.js.map +0 -1
- package/dist/chunk-KWWR5VMS.js.map +0 -1
- package/dist/chunk-LPOMRC4C.js.map +0 -1
- package/dist/chunk-M7JBER5U.js.map +0 -1
- package/dist/chunk-NENBUYX5.js +0 -79
- package/dist/chunk-NENBUYX5.js.map +0 -1
- package/dist/chunk-NWSEP5RT.js +0 -117
- package/dist/chunk-NWSEP5RT.js.map +0 -1
- package/dist/chunk-OJWWHFH3.js +0 -426
- package/dist/chunk-OJWWHFH3.js.map +0 -1
- package/dist/chunk-PSKN344N.js.map +0 -1
- package/dist/chunk-PX3YSS5C.js.map +0 -1
- package/dist/chunk-QO55FN2Y.js.map +0 -1
- package/dist/chunk-R7ZWUN64.js +0 -38
- package/dist/chunk-R7ZWUN64.js.map +0 -1
- package/dist/chunk-RKVQEH4J.js.map +0 -1
- package/dist/chunk-SRSJO5QE.js.map +0 -1
- package/dist/chunk-SYDMYBPG.js +0 -31
- package/dist/chunk-SYDMYBPG.js.map +0 -1
- package/dist/chunk-TB6DY7H5.js +0 -25
- package/dist/chunk-TB6DY7H5.js.map +0 -1
- package/dist/chunk-UFZKLBCF.js +0 -108
- package/dist/chunk-UFZKLBCF.js.map +0 -1
- package/dist/chunk-UKKSMZYT.js +0 -281
- package/dist/chunk-UKKSMZYT.js.map +0 -1
- package/dist/chunk-W2FK7ZNY.js +0 -26
- package/dist/chunk-W2FK7ZNY.js.map +0 -1
- package/dist/chunk-W5L2JSBY.js +0 -40
- package/dist/chunk-W5L2JSBY.js.map +0 -1
- package/dist/chunk-Y45PPBDV.js.map +0 -1
- package/dist/chunk-Y6LYKFXY.js.map +0 -1
- package/dist/divider-sides-267FA7sY.d.ts +0 -4
- package/dist/panel-header.d.ts +0 -42
- package/dist/panel-header.js +0 -7
- package/dist/panel-header.js.map +0 -1
- package/dist/styles/panel-header.css +0 -64
- package/dist/styles/tab-scaffold.css +0 -84
- package/dist/tab-scaffold.d.ts +0 -30
- package/dist/tab-scaffold.js +0 -51
- package/dist/tab-scaffold.js.map +0 -1
- package/dist/wire-tab-scaffold.d.ts +0 -11
- package/dist/wire-tab-scaffold.js +0 -21
- package/dist/wire-tab-scaffold.js.map +0 -1
- package/docs/design/templates/panel-header/icon-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-actions.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +0 -1
- package/docs/design/templates/panel-header/icon-summary-actions.svg +0 -1
- package/docs/design/templates/panel-header/no-icon-dark.svg +0 -1
- package/docs/design/templates/panel-header/no-icon.svg +0 -1
- package/docs/design/templates/panel-header/page-heading-dark.svg +0 -1
- package/docs/design/templates/panel-header/page-heading.svg +0 -1
- package/docs/design/templates/panel-header/title-only-dark.svg +0 -1
- package/docs/design/templates/panel-header/title-only.svg +0 -1
- package/docs/design/templates/panel-header-dark.svg +0 -1
- package/docs/design/templates/panel-header.svg +0 -1
- package/docs/tab-scaffold.md +0 -50
- package/ux-demo/recipes/recipes.css +0 -448
package/llms.txt
CHANGED
|
@@ -13,26 +13,103 @@ Import each component from its own subpath (`@kerfjs/ui/list-item`, `@kerfjs/ui/
|
|
|
13
13
|
…); the browser build pulls that component's reachable CSS automatically, so do not
|
|
14
14
|
maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
15
15
|
|
|
16
|
+
The sunken/lowered background is semi-transparent: Web Awesome's
|
|
17
|
+
`--wa-color-surface-lowered` is mirrored by `--kui-color-surface-lowered` and
|
|
18
|
+
used by `--kui-color-neutral-fill-quiet`. `SunkenPanel`, sunken
|
|
19
|
+
`Pane`/`Workbench`/`TabNavigator` surfaces, and Web Awesome
|
|
20
|
+
`appearance="sunken"` use that tint by default through their optional
|
|
21
|
+
`--kui-sunken-panel-background` / `--kui-wa-sunken-background` override tokens.
|
|
22
|
+
Each layer composites over its backdrop. Intentional nested layers create
|
|
23
|
+
depth; avoid a wrapper or extra background that paints the same visual surface
|
|
24
|
+
twice. Check contrast in both color schemes over the actual backdrop. See
|
|
25
|
+
[contextual transparency](./docs/webawesome-theme.md#contextual-transparency).
|
|
26
|
+
|
|
27
|
+
For arbitrary interactive help or popup content, use `openAnchoredSurface` or
|
|
28
|
+
`openAnchoredSurfaceAt` from `@kerfjs/ui/anchored-surface`; see
|
|
29
|
+
[AnchoredSurface](./docs/anchored-surface.md). The app owns content and actions.
|
|
30
|
+
Inside a native `<dialog>`, `wa-dialog`, or `wa-drawer`, the surface stays
|
|
31
|
+
interactive and closes with the dialog. It keeps an 8px viewport gutter
|
|
32
|
+
(`viewportMargin`) and fits its height to the room beside the anchor, scrolling
|
|
33
|
+
its content, so do not add media queries or `max-height` overrides.
|
|
34
|
+
`tone: 'dark'` gives a popup anchored to dark media chrome the inverse tone of a
|
|
35
|
+
`ToolbarControlGroup tone="dark"`; its content inherits the matching colors.
|
|
36
|
+
For a public subpath containing several visual components, use a folder with one
|
|
37
|
+
component per source file and one owned stylesheet per visual component. Keep its
|
|
38
|
+
compatibility entrypoints implementation-free: JavaScript/TypeScript only re-exports
|
|
39
|
+
the folder modules, and CSS only imports their owner stylesheets.
|
|
40
|
+
|
|
41
|
+
### Shared semantic tones
|
|
42
|
+
|
|
43
|
+
Use `ToolbarText tone="dark"` on a loud or photo-backed toolbar surface to
|
|
44
|
+
match dark control groups. It applies to read-only headings and actionable
|
|
45
|
+
titles at every size; default tone retains existing identity and heading colors.
|
|
46
|
+
|
|
47
|
+
`SemanticTone` is the shared color-role type for `Badge`, `Chip`, `StateBanner`,
|
|
48
|
+
and semantic `ContentItem` appearances: `neutral`, `info`, `pop`, `success`,
|
|
49
|
+
`warning`, and `danger`. Import it as a type from `@kerfjs/ui`,
|
|
50
|
+
`@kerfjs/ui/badge`, `@kerfjs/ui/state-banner`, or `@kerfjs/ui/content-item`.
|
|
51
|
+
Use `info` for the role backed by the existing `--kui-color-brand-*` tokens.
|
|
52
|
+
Migrate Badge/Chip `tone="brand"` to `tone="info"`; `BadgeTone` and
|
|
53
|
+
`StateBannerTone` remain deprecated aliases of `SemanticTone`.
|
|
54
|
+
|
|
55
|
+
## The rule: components own their styles
|
|
56
|
+
|
|
57
|
+
Configure components through their typed props (size, density, inset,
|
|
58
|
+
presentation, `ToolbarConfig`, `PaneConfig`, …); never restyle one from outside.
|
|
59
|
+
No application or parent CSS may select a `.kui-*` class, a `[data-component]`
|
|
60
|
+
root, a `wa-*` element a Kerf component renders, or its `::part()`s, and no
|
|
61
|
+
writing another component's `--_kui-*` / `--kui-*` variables where a prop
|
|
62
|
+
exists. When a component adapts inside another, it styles itself in that
|
|
63
|
+
context in its own stylesheet. A missing prop is a component gap to report,
|
|
64
|
+
not a reason to override — and your own components follow the same rule.
|
|
65
|
+
|
|
16
66
|
## How to build a screen (retrieval order)
|
|
17
67
|
|
|
68
|
+
First make the design decision: state what the user must read or do, find the
|
|
69
|
+
Kerf or consuming-app component whose purpose and interaction match, and
|
|
70
|
+
configure it. Compose `Toolbar`, `List`, `Row`, `Grid`, `ContentItem`, and the
|
|
71
|
+
other primitives before creating markup or CSS. A local component should own a
|
|
72
|
+
real domain behavior or new structure; a wrapper made only to re-space or
|
|
73
|
+
re-skin an existing component is the wrong choice. Ask what each `div`, `span`,
|
|
74
|
+
fragment, class, and CSS rule contributes. Remove it if a component already
|
|
75
|
+
owns the semantics, surface, inset, scrollport, or gap. Use the spacing scale
|
|
76
|
+
to show relationships, keep useful negative space, and align neighboring text
|
|
77
|
+
and control edges. Check the result against adjacent screens at wide and narrow
|
|
78
|
+
widths. The concrete [decision pass](./docs/component-selection.md#decision-pass-before-jsx-or-css)
|
|
79
|
+
explains when to reuse, compose, extend, or use native HTML.
|
|
80
|
+
|
|
18
81
|
1. **Pick the component from the interface need**, not by appearance — read
|
|
19
82
|
[component-selection.md](./docs/component-selection.md) (the problem→component
|
|
20
83
|
matrix, with imports, wiring, ownership, and alternatives).
|
|
21
84
|
2. **Get exact signatures before emitting code** — read
|
|
22
85
|
[public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) (real prop names,
|
|
23
86
|
callback shapes, disposer return types).
|
|
24
|
-
3. **
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
87
|
+
3. **Look up each component you use** in the
|
|
88
|
+
[component reference index](./ai/components/README.md) — one line per
|
|
89
|
+
entry — then read only those `ai/components/<id>.md` pages (1–7 KB each):
|
|
90
|
+
use/avoid, imports and side effects, a link to exact props, legal parents,
|
|
91
|
+
zones with their JSX prop and child count, app- and wiring-owned state,
|
|
92
|
+
geometry, accessibility, the styling boundary (configure through props;
|
|
93
|
+
never override internals), and `KUI-C###` diagnostics. Do not load the
|
|
94
|
+
large JSON catalogs just to choose or compose components; the pages are
|
|
95
|
+
generated from them.
|
|
96
|
+
**Tools and mechanical checks** use the JSON sources instead: the
|
|
97
|
+
[Machine-readable component catalog](./ai/component-catalog.json) (ids,
|
|
98
|
+
exports, variants, `publicClasses`, relationships, side effects, and
|
|
99
|
+
geometry ownership) — the canonical checked-in source; its schema is
|
|
100
|
+
alongside it. Also load the
|
|
28
101
|
consuming application's catalog extension when present; generate one from the
|
|
29
102
|
[Consumer catalog extension schema](./ai/component-catalog-extension.schema.json)
|
|
30
103
|
when app-owned components must participate in selection or alignment.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
104
|
+
A tool loads the [Composition catalog](./ai/component-composition.json) — a
|
|
105
|
+
generated composition layer beside the component catalog, not a replacement
|
|
106
|
+
for it — to mechanically evaluate parents, contexts, zones/cardinality,
|
|
107
|
+
children, state, wiring (including the wiring-owned `stateAttributes` an app
|
|
108
|
+
must never render or remove), responsive/layout/accessibility rules, and
|
|
109
|
+
public boundaries. The component catalog stays the selection and delivery
|
|
110
|
+
surface; the composition layer joins catalogs by `package:id`. Consumer
|
|
111
|
+
composition catalogs use
|
|
112
|
+
[the composition extension schema](./ai/component-composition-extension.schema.json).
|
|
36
113
|
Load [compile-time contracts](./ai/compile-time-contracts-v1.json) for stable
|
|
37
114
|
`KUI-T###` ids, exact declaration symbols, and the boundary between rejected
|
|
38
115
|
source states and relationships that still require runtime/catalog checks.
|
|
@@ -45,14 +122,44 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
45
122
|
child; synchronous hosts use [application-ui-profile-sync.cjs](./ai/application-ui-profile-sync.cjs).
|
|
46
123
|
See the
|
|
47
124
|
[workspace profile example](./docs/examples/application-ui-profile.json).
|
|
125
|
+
A zone's optional `jsx.prop` is its only authoritative JSX binding; never
|
|
126
|
+
infer one from the zone id. Use `children` for one homogeneous primary
|
|
127
|
+
region and explicit named content prop slots for semantic positions or
|
|
128
|
+
replacement content. These slots use the recursive `KerfUiContent` type:
|
|
129
|
+
`SafeHtml`, runtime-empty boolean/nullish values, and readonly nested arrays.
|
|
130
|
+
Put conditionals and mapped component arrays directly in them; do not add a
|
|
131
|
+
`Fragment` only to satisfy types. Arbitrary strings, numbers, and signals are
|
|
132
|
+
rejected unless a component explicitly exposes a text position such as
|
|
133
|
+
`ListInsetText`. These are typed props, not native `<slot>` elements,
|
|
134
|
+
wrapper slot components, or a generic `slots` object. Leave unresolved
|
|
135
|
+
dynamic expressions unknown.
|
|
136
|
+
Stable single-root Kerf UI components separately accept the explicit native
|
|
137
|
+
`slot="name"` prop for light-DOM composition inside a custom element and
|
|
138
|
+
preserve it across rerenders. Do not infer arbitrary native-attribute
|
|
139
|
+
spreading from this narrow interop contract. `ResizableRegion` and
|
|
140
|
+
`CollapsiblePanel` remain excluded because their optional restore controls
|
|
141
|
+
make their output multi-root; `CollapsiblePanelToggle` remains slot-capable.
|
|
48
142
|
4. **When authoring a component gallery**, load
|
|
49
143
|
[catalog-authoring.json](./ai/catalog-authoring.json), then follow its
|
|
50
144
|
authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract).
|
|
145
|
+
Use its component/composition/recipe taxonomy and functional-group,
|
|
146
|
+
importance, alphabetical-tie, and recipes-last ordering policy. Focused
|
|
147
|
+
demos and recipes use public components plus `CatalogExample.viewport`,
|
|
148
|
+
never local stylesheets, inline styles, or styling-only classes. A frame
|
|
149
|
+
that a top-layer specimen anchors to takes `viewport.anchorName`, and a
|
|
150
|
+
centered column takes `viewport.contentWidth` + `contentAlign`.
|
|
51
151
|
5. **Apply the rules below and in** [skill.md](./ai/skill.md).
|
|
52
152
|
6. **Before calling an integration complete**, run
|
|
53
153
|
[`kerf-ui-doctor`](./docs/ui-doctor.md). Its portable JSON report merges
|
|
54
154
|
profile/catalog, TypeScript, Kerf ESLint, and static analyzer diagnostics;
|
|
55
|
-
|
|
155
|
+
CSS-adjacent component props are checked from catalog `cssValueProps`, so
|
|
156
|
+
prefer its canonical shorthand or typed helper over raw CSS strings; a
|
|
157
|
+
`--wa-color-{tone}-fill-loud` override without a governing `on-loud` (same
|
|
158
|
+
or ancestor scope, possibly in a co-loaded stylesheet), or whose literal
|
|
159
|
+
pair measures below 4.5:1, is review finding `KUI-L018` (set both); CSS that restyles a component
|
|
160
|
+
(`KUI-L019`), touches its private `--_*` variables (`KUI-L020`), overrides a token a typed prop sets
|
|
161
|
+
(`KUI-L021`), or styles it through a hook class on its root (`KUI-L022`) is an error: configure the
|
|
162
|
+
component instead, and report a component gap when no prop exists; application-component imports may use TypeScript `paths` aliases; use `"ownership": "component"` with catalog `styleSources` to apply this boundary between an app's own components; repair source-located errors until exit 0. Use full mode for release gates;
|
|
56
163
|
generated `dist`/`coverage`, dependency, cache, evidence, and nested-worktree
|
|
57
164
|
directories are excluded consistently from every static stage.
|
|
58
165
|
[`kerf-ui-analyze`](./docs/ui-analyzer.md) remains available when only static
|
|
@@ -65,29 +172,201 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
65
172
|
ratings separately with a named reviewer rather than presenting them as
|
|
66
173
|
objective assertions.
|
|
67
174
|
|
|
175
|
+
## Application interaction choices
|
|
176
|
+
|
|
177
|
+
For ordinary server-backed freshness, prefer event-driven updates, subscriptions,
|
|
178
|
+
or explicit user refresh when they meet the product need. Use fixed-interval
|
|
179
|
+
polling when periodic sampling is genuinely required or no suitable update
|
|
180
|
+
channel exists; choose the interval deliberately and cancel the timer when its
|
|
181
|
+
owning view is disposed.
|
|
182
|
+
|
|
183
|
+
Make cursor cues match enabled behavior: use a pointer for actionable targets,
|
|
184
|
+
grab/grabbing or resize cues for actual drag and resize affordances, and a
|
|
185
|
+
default or disabled cue when an action is unavailable. Keep the semantic
|
|
186
|
+
control, keyboard behavior, focus treatment, and disabled state aligned with
|
|
187
|
+
the cursor; the cursor alone cannot explain an interaction. See
|
|
188
|
+
[accessibility contracts](./docs/accessibility.md) and
|
|
189
|
+
[interaction principles](./docs/apple-hig.md#interaction).
|
|
190
|
+
|
|
191
|
+
## Interface copy capitalization
|
|
192
|
+
|
|
193
|
+
Follow Apple's split, the package default: **names are title style;
|
|
194
|
+
descriptions are sentence style.** Title style: buttons, menu items and menu
|
|
195
|
+
headings, popup-menu triggers, segments, `Select` choices, tabs,
|
|
196
|
+
page/view/pane/dialog/toolbar titles, back labels, `ListHeader` and column
|
|
197
|
+
headings, field labels, icon-only control names, and fragment
|
|
198
|
+
`EmptyState`/`StateBanner` titles ("Save Draft", "Back to Inbox"). Sentence
|
|
199
|
+
style: body copy, descriptions, details, messages, tooltips, placeholders,
|
|
200
|
+
checkbox/switch/radio option text, and status lines ("Saved just now"). Title
|
|
201
|
+
style capitalizes the first and last word and phrasal-verb particles ("Log
|
|
202
|
+
In"); it lowercases articles, coordinating conjunctions, `to` in infinitives,
|
|
203
|
+
`as`, and prepositions of four letters or fewer elsewhere. Keep brand spellings
|
|
204
|
+
and user data as written. `kerf-ui-doctor` reports violations in known
|
|
205
|
+
title-style labels as `KUI-D040`. See
|
|
206
|
+
[Writing interface copy](./docs/writing.md#capitalization).
|
|
207
|
+
|
|
68
208
|
## Core rules (do the right thing)
|
|
69
209
|
|
|
210
|
+
- **Prefer a Kerf UI component over a Web Awesome component over a raw HTML
|
|
211
|
+
tag**, using each for what it is good at. Never render a `Discouraged` Web
|
|
212
|
+
Awesome element (`wa-dropdown`, `wa-button-group`, `wa-select`, `wa-tab-group`,
|
|
213
|
+
`wa-icon`, …) directly; reach it only through the Kerf component that wraps or
|
|
214
|
+
replaces it (`PopupMenu`, `SegmentedControl`, `Select`, `TabBar`,
|
|
215
|
+
`LucideIcon`), and file a component gap rather than dropping to the raw tag.
|
|
70
216
|
- **Reach for the primitive, not for CSS.** The package is built to look right
|
|
71
|
-
|
|
72
|
-
`background`, a wrapper card, or a decoration,
|
|
73
|
-
pane, or
|
|
74
|
-
component prop
|
|
75
|
-
|
|
76
|
-
|
|
217
|
+
without an application customization layer. Before adding `padding`, `margin`,
|
|
218
|
+
`width`, `height`, `border`, `background`, a wrapper card, or a decoration,
|
|
219
|
+
check whether the component, pane, or content-item already owns it. Prefer a
|
|
220
|
+
component prop — `FloatingToolbar inset`, `DisclosureArrow size`, `ListHeader
|
|
221
|
+
headingLevel`, `TokenSearchField clearIcon`, `ContentItem frame="framed"` for a
|
|
222
|
+
visibly bounded content item — over overriding its `--kui-*` token. CSS for genuinely new structure
|
|
223
|
+
belongs to the application-owned component that renders it and must not select
|
|
224
|
+
nested Kerf or Web Awesome components.
|
|
77
225
|
- **Never double-inset.** A `.kui-pane` has no padding; its `.kui-content` children
|
|
78
|
-
own the geometry (8px inline margin + 1px border + 8px padding).
|
|
226
|
+
own the geometry (8px inline margin + 1px border + 8px padding). Render an
|
|
227
|
+
ordinary surface-like child as `ContentItem` (`@kerfjs/ui/content-item`) with
|
|
228
|
+
typed `frame` (`none`/`framed`) and `shape` (`rounded`/`pill`) props instead
|
|
229
|
+
of hand-writing `<div class="kui-content-item">`. For a chat transcript, set
|
|
230
|
+
`bubble="start"` (other participants) or `bubble="end"` with
|
|
231
|
+
`appearance="brand-loud"` (the person's own messages): the item fits its
|
|
232
|
+
message up to 80% of the row. Do not add a
|
|
79
233
|
container padding on top of a content-item's own margin — pick one owner. Use
|
|
80
234
|
`.kui-content` for 24px major vertical rhythm.
|
|
81
|
-
- **
|
|
82
|
-
|
|
235
|
+
- **Opt into document globals explicitly.** Import `@kerfjs/ui/document.css`
|
|
236
|
+
once for border-box sizing, token-backed body/link presentation, inherited
|
|
237
|
+
native table-cell and form-control font metrics, zero body margin, and
|
|
238
|
+
zero-specificity semantic cursors for native controls (pointer, not-allowed
|
|
239
|
+
when disabled, text on text inputs). Put `.kui-app-root` on the one direct mount container only when a
|
|
240
|
+
percentage-height shell needs the provided `html` → `body` → app-root height
|
|
241
|
+
chain. Add `data-viewport="locked"` to that body-child root for a
|
|
242
|
+
full-viewport shell whose document never scrolls (`100dvh` and
|
|
243
|
+
`overflow: clip` on `html`, `body`, and the root). The baseline is not part of `styles.css` or component browser imports.
|
|
244
|
+
- **Use compact layout options where needed.** `Text flush lineHeight="tight"`
|
|
245
|
+
fits short dialog copy, and `Text align="center"` centers wrapping status
|
|
246
|
+
copy; `ValueTable density="compact"` reduces row spacing,
|
|
247
|
+
with public row column, padding, and gap tokens for specific metadata layouts.
|
|
248
|
+
`ToolbarText size="xsmall"` suits a dense rail heading. The
|
|
249
|
+
`TokenSearchField` editor shrinks in narrow groups; its minimum width can be
|
|
250
|
+
set with `--kui-token-search-editor-min-width`.
|
|
251
|
+
- **Label read-only field previews.** Use `FieldLabel` from `@kerfjs/ui/text`
|
|
252
|
+
in `ListInsetControl sides="trl"` above a `ContentItem` value. Connect its
|
|
253
|
+
id to the preview group's `aria-labelledby`; use the live control's own
|
|
254
|
+
`label` while editing.
|
|
255
|
+
- **Use Toolbar zone options.** `responsive="trailing-priority"` moves an
|
|
256
|
+
expanded trailing control to a full second row at `responsiveAt`; the leading
|
|
257
|
+
title remains above it. Public leading-min-width, trailing-gap/justify, and
|
|
258
|
+
per-zone inline-padding tokens cover app-specific toolbar geometry.
|
|
259
|
+
In a stacked Toolbar, `ToolbarControlGroup placement="end"` places a collapsed
|
|
260
|
+
search at its row's trailing edge; `sizing="fill"` gives its expanded state a
|
|
261
|
+
full row and a reduced-motion-aware downward entrance.
|
|
262
|
+
`--kui-toolbar-inset: 0px` removes an embedded Toolbar's outer padding and
|
|
263
|
+
corresponding minimum-height allowance while preserving its zone gap and
|
|
264
|
+
safe-area compensation. For a shorter header embedded in a panel or card,
|
|
265
|
+
pass `density="compact"` (40px: a 34px control band and 3px block insets)
|
|
266
|
+
and give its groups `size="compact"`; never shrink a Toolbar with CSS.
|
|
267
|
+
Composites forward `density` from their `ToolbarConfig` (Workbench panel,
|
|
268
|
+
main, and bottom toolbars, CollapsiblePanel, NavStack, SplitView) and size
|
|
269
|
+
the groups they compose (panel toggles, the back button) to match; pass
|
|
270
|
+
`density` to `CollapsiblePanelRelocated` when its toolbar is compact.
|
|
271
|
+
- **Name panel toggles in title style.** A panel toolbar's
|
|
272
|
+
`toggle: { action, name }` uses `name` as the toggle group's accessible name
|
|
273
|
+
and in the default "Show …" / "Hide …" label, so pass a title-style panel
|
|
274
|
+
name (`name: "Navigator"` gives "Show Navigator"); it is never recapitalized.
|
|
275
|
+
- **Position region restore controls declaratively.** A ResizableRegion has a
|
|
276
|
+
background token, `contentOverflow="visible"` for an anchored popup,
|
|
277
|
+
top/bottom `restorePosition`, typed `restoreInset`, and
|
|
278
|
+
`restorePlacement="inline"` for normal flow. FloatingToolbar also has
|
|
279
|
+
`placement="inline"`, per-edge inset tokens, and `safeAreaInsets`.
|
|
280
|
+
- **Configure list rows through their APIs.** `ListItem density="spacious"`
|
|
281
|
+
gives option rows more room. `multiline` wraps labels, with
|
|
282
|
+
`multilineIconAlign="center"` when the icon should center on the whole copy.
|
|
283
|
+
`divider` owns row separators and `state="drag-target"` paints the drop
|
|
284
|
+
target. For lines only between rows, give every row but the last
|
|
285
|
+
`divider="after"` (the last `"none"`); a row's corners are flat wherever a
|
|
286
|
+
divider line meets them, so the group rounds only its outer corners on
|
|
287
|
+
hover and selection. For a reorderable list, set `draggable` + `itemId` on `ListItem`,
|
|
288
|
+
`ListItemLink`, or `ListActionRow` rows and call `wireListReorder` (from
|
|
289
|
+
`@kerfjs/ui/wire-list-reorder`) once; it paints the dimmed dragging rows and
|
|
290
|
+
the before/after insertion line, supports Alt+Shift+ArrowUp/ArrowDown, and
|
|
291
|
+
reports `{ listId, sourceIds, target: { id, position }, source }` for
|
|
292
|
+
`reorderListItems`. The `dragging` / `dropPosition` props render the same
|
|
293
|
+
states from app-owned drag state. For keyboard row navigation in a
|
|
294
|
+
`scrollable` List, call `wireListFocusScroll` (from
|
|
295
|
+
`@kerfjs/ui/wire-list-focus-scroll`) once: it scrolls a keyboard-focused row
|
|
296
|
+
whose focus ring crosses the clip into view in Firefox and Safari too.
|
|
297
|
+
Public ListItem tokens set row, icon, label, and trailing geometry;
|
|
298
|
+
ListHeader `size="xs|sm|m|l|xl"` sets label scale independently of
|
|
299
|
+
`headingLevel` (`sm` keeps the current FieldLabel-sized uppercase style;
|
|
300
|
+
`m`/`l`/`xl` match themed h5/h4/h3). Its height, title padding, and border
|
|
301
|
+
tokens tune section density. A semantic `count` requires `countLabel` and
|
|
302
|
+
excludes other indicators; `badge` and `status` may render together, and
|
|
303
|
+
either may be explicitly `undefined` in conditional app state.
|
|
304
|
+
For a filled command list, scope `--kui-list-item-background`,
|
|
305
|
+
`--kui-list-item-color`, `--kui-list-item-border`,
|
|
306
|
+
`--kui-list-item-hover-background`, `--kui-list-item-hover-border`,
|
|
307
|
+
`--kui-list-item-selected-background`, `--kui-list-item-selected-color`,
|
|
308
|
+
and `--kui-list-item-selected-border` at the list or row boundary.
|
|
309
|
+
To align `ListItem` and `ListActionRow` rows in one list on a custom
|
|
310
|
+
leading inset, set `--kui-list-row-padding-inline` on the `List` (never
|
|
311
|
+
`--kui-list-item-padding-inline`, which moves only `ListItem` rows). Both
|
|
312
|
+
row kinds draw an 18px untiled leading icon by default, so their labels
|
|
313
|
+
align; resize both with `--kui-list-row-icon-size` on the `List` (never
|
|
314
|
+
`--kui-list-item-icon-size`, which resizes only `ListItem` icons).
|
|
315
|
+
- **Use `Row` for horizontal and `List` for vertical layout.** Both expose
|
|
316
|
+
physical `hAlign`/`vAlign` props and typed gaps. Row defaults to left/full,
|
|
317
|
+
an `xs` gap, and no wrapping; List retains full/top and zero-gap defaults.
|
|
318
|
+
Use canonical physical `textInsets` or `controlInsets` sides in
|
|
319
|
+
`t`/`r`/`b`/`l` order; text geometry wins on overlapping sides.
|
|
320
|
+
`ListInsetText` and `ListInsetControl` inset every side by default and accept
|
|
321
|
+
the same `sides` grammar for selective edges.
|
|
322
|
+
List additionally supplies
|
|
323
|
+
optional typed `gap`, `flex`, vertical scrolling, and canonical
|
|
83
324
|
`dividerSides` (`t`/`r`/`b`/`l` order). It adds no list semantics; children own
|
|
84
|
-
those, and only one bounded region should own scrolling.
|
|
325
|
+
those, and only one bounded region should own scrolling. Pass a finite spacing
|
|
326
|
+
shorthand (`gap="xs"`, `gap="m"`) or a complete `CssLength` from the CSS-free
|
|
327
|
+
`@kerfjs/ui/css-values` builders; raw CSS strings are rejected. Use `flex()`
|
|
328
|
+
for List flex, typed lengths for Skeleton geometry, and
|
|
329
|
+
foreground colors for choice icons and `LucideIcon.color`: `uiColor()` with an `*-on-*`/text token,
|
|
330
|
+
`foregroundColorVar()`, or `foregroundColor()` for a custom CSS color; fill tokens such as `uiColor('success-fill-quiet')` do not
|
|
331
|
+
type-check. Fills (a `ChoiceChips` swatch, a row `iconTile` color) take a
|
|
332
|
+
plain `CssColor`: `fillColor('#3b82f6')` for a custom CSS color, `uiColor()`,
|
|
333
|
+
or `colorVar()`; never `foregroundColor()` for a fill. These brands are intentionally
|
|
334
|
+
not interchangeable; rows use classes/tokens/props rather than raw `style`.
|
|
335
|
+
Set `LucideIcon.inline` for an icon in `Text` or prose; it changes the SVG
|
|
336
|
+
from block to inline-block without changing its inherited 1em size.
|
|
337
|
+
- **Use `Grid` for equal-width columns.** Set a fixed positive `columns` count
|
|
338
|
+
or typed `minColumnWidth` for automatic container-width collapse, never both.
|
|
339
|
+
The app owns the outer width and child semantics; use custom CSS grid for
|
|
340
|
+
asymmetric/intrinsic tracks and `ResizableRegion` for adjustable boundaries.
|
|
341
|
+
`Grid.gap` and `Grid.flex` use the same typed grammars as Row.
|
|
342
|
+
`Grid.textInsets` and `Grid.controlInsets` select physical sides for the
|
|
343
|
+
standard 17px text and 8px control inset; text wins on overlap.
|
|
344
|
+
For selectable document tiles, use `selectionMode="multiple"` and a required
|
|
345
|
+
`ariaLabel`, with `ContentItem selectionMode="multiple"` children. Wire
|
|
346
|
+
`wireContentItems` for spatial arrow navigation and Enter/Space activation.
|
|
347
|
+
- **Give a layout root `fill`, not a frame `Pane`.** A Row, List, or Grid that
|
|
348
|
+
is the sole layout root of a definite-height parent takes its full height
|
|
349
|
+
with `fill` and carries safe `data-*` markers through `rootAttributes`.
|
|
350
|
+
Inside a flex layout use `flex` instead.
|
|
85
351
|
- **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
|
|
86
352
|
`--kui-wa-control-inset` (8px controls/items) and
|
|
87
353
|
`--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
|
|
88
354
|
Accordion, Card, Details, Callout, and Include), while
|
|
89
|
-
|
|
90
|
-
|
|
355
|
+
plain Details keep their body flush while plain Accordion items inset both
|
|
356
|
+
trigger and body, framed Details use the 16px container inset only on the
|
|
357
|
+
trigger, and framed Accordion items use it on both regions;
|
|
358
|
+
`--kui-wa-container-inset` keeps Tab Panel at 16px. Dialog body and footer use
|
|
359
|
+
the surface (8px) and container (16px) tiers respectively, independent of the
|
|
360
|
+
dialog's shared `--spacing`. Override the tier at the narrowest useful scope
|
|
361
|
+
instead of restyling individual shadow parts.
|
|
362
|
+
Filled badges use each semantic variant's quiet fill with normal text for
|
|
363
|
+
WCAG-AA compact-copy contrast. Override
|
|
364
|
+
`--kui-wa-badge-filled-background` and
|
|
365
|
+
`--kui-wa-badge-filled-foreground` as a contrast-safe pair instead of adding
|
|
366
|
+
host selectors.
|
|
367
|
+
When a dialog provides another dismissal affordance, add `hide-actions` to
|
|
368
|
+
the `wa-dialog` host; the theme hides its directly exported `header-actions`
|
|
369
|
+
part without an unsupported chained `::part()` selector.
|
|
91
370
|
Checkbox and Radio Group option regions also receive the shared 8px inline
|
|
92
371
|
outer inset because those groups have no bordered field shell. The Color
|
|
93
372
|
Picker trigger receives the same inset for the same unbordered geometry.
|
|
@@ -97,33 +376,180 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
97
376
|
with field values at the shared 9px border-plus-padding inset. OTP Input's
|
|
98
377
|
label uses the same uppercase xs/650 treatment and its label and hint share
|
|
99
378
|
that 9px alignment.
|
|
379
|
+
- `Select` requires a visible `label` or an `ariaLabel` for a visually hidden
|
|
380
|
+
accessible name. Set `multiple` with an array `value` for any number of
|
|
381
|
+
choices: the popup stays open while choices toggle and closes on an outside
|
|
382
|
+
press or Escape, and the closed control summarizes the chosen labels. A
|
|
383
|
+
toolbar filter menu adds `selectedPresentation="icon-only"` and a fixed
|
|
384
|
+
`triggerIcon`: the trigger shows that icon plus a count badge while any
|
|
385
|
+
choice is chosen, and its accessible name ends with the chosen labels.
|
|
386
|
+
Set `caret={false}` on an icon-only toolbar Select to make a round trigger;
|
|
387
|
+
a custom `renderSelected` icon stays centered, and the default keeps the
|
|
388
|
+
visible caret.
|
|
389
|
+
`SelectChoice.disabled` keeps an unavailable option visible but unselectable;
|
|
390
|
+
`disabledReason` adds its tooltip. For multiple selects, opt in to
|
|
391
|
+
`selectAllLabel` and `clearLabel` footer buttons to select enabled choices
|
|
392
|
+
or clear the value through ordinary change events. The app owns the updated
|
|
393
|
+
controlled value and localized action labels.
|
|
394
|
+
Icon-only Selects (single or multiple) and icon-only `PopupMenu`s show an
|
|
395
|
+
`aria-hidden` Web Awesome help tag repeating that name (and a Select's
|
|
396
|
+
choice) on hover and keyboard focus, hidden while the popup is open; the
|
|
397
|
+
register import installs it, so do not add a `title` or tooltip of your own.
|
|
398
|
+
The same installer tags an icon-only `<button>` or link inside a
|
|
399
|
+
`ToolbarControlGroup` named by `aria-label` (no visible text or `title`);
|
|
400
|
+
import `@kerfjs/ui/help-tags/register` once when a toolbar has such buttons
|
|
401
|
+
but no registered Select or PopupMenu.
|
|
402
|
+
The package names the internal combobox, including custom
|
|
403
|
+
selected content; consumers do not need shadow-DOM naming workarounds.
|
|
404
|
+
Import `select/register` once for the canonical animation lifecycle: stale
|
|
405
|
+
close/show completions cannot override a later request. Consumers must not
|
|
406
|
+
repair popup timing or anchor placement; raw Web Awesome selects stay native.
|
|
407
|
+
Use `hint` for supporting text below the control and `placeholderText` only
|
|
408
|
+
for the empty value inside it; loading placeholders retain the visible hint.
|
|
100
409
|
- **Trust the defaults.** Render a control at its natural size and color (a
|
|
101
410
|
`LucideIcon` is 24px); if it looks wrong, fix the surrounding layout, not the
|
|
102
411
|
control. Never force a component's width/height to size it — that leaves a halo
|
|
103
412
|
or a stretched oval.
|
|
413
|
+
- **Make room for an expanded search instead of growing it past what fits.** A
|
|
414
|
+
collapsible search group grows into the space beside its sibling groups; if
|
|
415
|
+
that space is too small, the siblings wrap onto a new row while it opens.
|
|
416
|
+
Size the expanded search to what fits (`--kui-token-search-expanded-width`,
|
|
417
|
+
or `sizing="grow"` with a `growBasis` that fits), and if a useful search
|
|
418
|
+
cannot fit beside the other controls, set aside those controls while the
|
|
419
|
+
search is open: mark them `visibility="yield-to-expanded-sibling"` (they
|
|
420
|
+
leave a 480px-or-narrower toolbar while a sibling is expanded) or gather
|
|
421
|
+
them behind a "…" `PopupMenu` overflow group. The app decides which
|
|
422
|
+
controls yield.
|
|
104
423
|
- **Toolbars hold only `ToolbarText` and `ToolbarControlGroup`.** Never put a bare
|
|
105
424
|
button, input, link, or loose markup in a `leading`/`center`/`trailing` zone.
|
|
106
425
|
Wrap every control — `SegmentedControl`, `Select`, a collapsible
|
|
107
426
|
`TokenSearchField`, Web Awesome controls — inside a `ToolbarControlGroup`. For an
|
|
108
427
|
ordinary icon/action control inside the group use a **plain `<button>`** (the
|
|
109
428
|
group styles it fully) — that is the default; reach for `wa-button` only when you
|
|
110
|
-
need a Web Awesome feature
|
|
111
|
-
popup
|
|
112
|
-
|
|
113
|
-
`
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
429
|
+
need a Web Awesome feature. A toolbar popup menu is a `PopupMenu`
|
|
430
|
+
(`@kerfjs/ui/popup-menu`, registered once via `@kerfjs/ui/popup-menu/register`)
|
|
431
|
+
in a `single` `ToolbarControlGroup` with `nestedDropdown`; never hand-write
|
|
432
|
+
`wa-dropdown` markup for a menu. Let the group size the trigger from its icon,
|
|
433
|
+
localized text, and caret. Set `overflow="wrap"` for independent action links
|
|
434
|
+
that must remain fully visible at narrow widths; whole links move to a second
|
|
435
|
+
row, as in the catalog resource footer. `PopupMenu` items also support nested `submenu`
|
|
436
|
+
actions, headings, dividers, checked or trailing choice marks, danger tone,
|
|
437
|
+
and disabled reasons; nested headings/dividers stay out of keyboard choices;
|
|
438
|
+
use `context` with `anchor` + `openPopupMenu` (or `openPopupMenuAt`) and
|
|
439
|
+
`closePopupMenu` for pointer-anchored row menus; the menu owns its
|
|
440
|
+
zero-footprint anchor host, so add no wrapper or CSS. `openPopupMenuAt`
|
|
441
|
+
also opens a button-triggered menu at the pointer for one opening. A row's
|
|
442
|
+
trailing "…" overflow menu is `ListActionRow`'s `trailingMenu` (`label`,
|
|
443
|
+
`icon`, `items`, optional `placement` and `disabled`), which renders a
|
|
444
|
+
`PopupMenu` as the row's sibling trailing control. Do not force a dropdown or button width. Nothing
|
|
445
|
+
wraps inside a group: an icon sits beside its label on one row, and a
|
|
446
|
+
`ToolbarText` is one ellipsized line unless you opt into `wrap`/`maxLines`. A
|
|
447
|
+
Select or PopupMenu trigger drops its focus ring while its popup is open and
|
|
448
|
+
the ring follows the control's shape; never add ring CSS. Compact
|
|
449
|
+
mixed groups keep standard item padding and raised selected chrome without an
|
|
450
|
+
internal separator; the selected item paints over the outer border. For an
|
|
451
|
+
avatar control, set `content="avatar"` and `avatarImage` on the group instead of
|
|
452
|
+
inserting an `img`; a lone control paints the group and a multi-button group
|
|
453
|
+
paints only its pressed highlight. Dividers earn their place: a `Toolbar`
|
|
454
|
+
draws none by default and pinned chrome gets its line from scroll state (see
|
|
455
|
+
the scroll-divider rule below); never fake one with a border or pad below a
|
|
456
|
+
divider to make it look right.
|
|
457
|
+
- **Use one direct toolbar composition for panel/dialog/page headings.** Put an
|
|
458
|
+
optional icon in a `ToolbarControlGroup`, an extra-large `ToolbarText` directly
|
|
459
|
+
in the leading zone, and actions in a trailing group. A short supporting
|
|
460
|
+
line ("Changes save automatically.") is the `ToolbarText` `description`:
|
|
461
|
+
quiet, one truncating line under the title, aligned with its text, with
|
|
462
|
+
`descriptionId` for `aria-describedby`. Longer copy is app-owned content
|
|
463
|
+
below. Do not create a private heading wrapper or restyle the
|
|
464
|
+
toolbar. A narrow peripheral rail or drawer, where extra-large would truncate
|
|
465
|
+
at its minimum size, names itself with the default `ToolbarText` size.
|
|
466
|
+
`ToolbarText size="xlarge-fixed"` keeps the 20px `--kui-font-l` heading step;
|
|
467
|
+
`xlarge` retains the responsive page-title clamp.
|
|
468
|
+
- **Use `Text` for ordinary semantic headings, paragraphs, and inline secondary
|
|
469
|
+
text outside toolbar title zones.** Omit `variant` for the default `p`, pass
|
|
470
|
+
`h1`–`h6` based on the document outline, or use `variant="span"` inside a row,
|
|
471
|
+
label, or table cell without adding box geometry. Independently compose `tone="quiet|danger"`,
|
|
472
|
+
`size="compact|large|xlarge"`, and `font="monospace"` for supporting, error,
|
|
473
|
+
compact, prominent, display, and code roles instead of global utility classes. It passes native attributes
|
|
474
|
+
through; block variants own the standard transparent border plus item padding, while `span` owns none. Keep
|
|
475
|
+
toolbar titles on `ToolbarText` and list-aligned bare prose on `ListInsetText`.
|
|
476
|
+
Text supports `controlMargins` with canonical physical Sides for an exterior 8px control gutter; it preserves border/padding and avoids an isolated Row wrapper. Avoid stacking it with parent insets. Inline spans retain native inline margin behavior.
|
|
477
|
+
|
|
478
|
+
`ToolbarControlGroup.tileTone` selects `neutral`, `brand`, `success`, `warning`, or `danger` quiet fill, matching quiet border, and on-quiet foreground for a non-interactive icon tile. Compose a contained `single` group whose only child is a direct decorative LucideIcon (`aria-hidden="true"`). Omission preserves the normal group palette. The prop does not recolor interactive, mixed, multi-control, or borderless groups; keep real actions in controls with their existing focus/hover/pressed treatments.
|
|
479
|
+
`ListItem`, `ListItemLink`, and `ListActionRow` take `iconTile` to present their leading `icon` in a filled 32px rounded tile holding an 18px glyph, for settings or command rows that identify each entry by color. Pass a tone (`neutral`, `brand`, `success`, `warning`, or `danger`) for the same quiet fill, matching quiet border, and on-quiet foreground as `ToolbarControlGroup.tileTone`, or `{ color, foreground? }` for an application color: `color` is a `CssColor` (`uiColor()`, `colorVar()`, or `fillColor('#e5484d')`) and `foreground` a `CssForegroundColor`; without one, the glyph is black or white, whichever contrasts with the fill. The tile sits 6px clear of a standard 44px row (a compact row is at least 42px tall), moves the label to the tile's edge, and keeps its colors when the row is hovered or selected. Never wrap the icon in your own tile or resize the row's icon slot.
|
|
480
|
+
Toolbar zones accept `KerfUiContent` directly. Use `ToolbarText` for identity and `ToolbarControlGroup` for related controls that need its shared chrome; a bare control keeps its own styling and accessibility responsibilities.
|
|
481
|
+
Expanded search groups accept `expandedOverflow="visible"` to anchor app-owned suggestion/date/help surfaces below their relative root; collapsed/default groups retain existing clipping. Apps own surface placement/dismissal and use `data-token-search-keep-open` or `collapsible.keepOpenOn` for focus.
|
|
482
|
+
|
|
118
483
|
- **Space by the five-step scale, by relationship not by eye.** `0`
|
|
119
484
|
`--kui-space-none`, `4px` `--kui-space-2xs`, `8px` `--kui-space-xs` (inside a
|
|
120
485
|
group), `16px` `--kui-space-m`, `24px` `--kui-space-l` (between major differing
|
|
121
|
-
regions). 12px/32px are off-scale exceptions.
|
|
486
|
+
regions). 12px/32px are off-scale exceptions. Prefer direct `Row.gap`/`List.gap`
|
|
487
|
+
shorthands for repeated rhythm; use `Spacer` for one typed empty width/height
|
|
488
|
+
or flexible main-axis gap. Use `space`, `px`, `rem`, `em`, `pct`, `lengthVar`, and
|
|
489
|
+
`calc(plus(...))` for typed runtime composition. `remify()` is source-CSS only.
|
|
490
|
+
- **Keep nested highlight corners concentric.** Inset hover and selection surfaces
|
|
491
|
+
follow the owning control's pill or rounded shape; their radius is the outer
|
|
492
|
+
radius minus `--kui-layout-highlight-inset`. Do not give an inner highlight an
|
|
493
|
+
unrelated radius.
|
|
122
494
|
- **Panes share one child-owned geometry.** Sidebars, main areas, inspectors, and
|
|
123
|
-
dialogs all
|
|
124
|
-
scrolling `.kui-pane__content`, optional
|
|
125
|
-
|
|
126
|
-
|
|
495
|
+
dialogs all render `Pane`: an unpadded `.kui-pane` (optional header, one
|
|
496
|
+
scrolling `.kui-pane__content`, optional footer). Use `tabIndex={0}` for a
|
|
497
|
+
whole-surface Tab stop or `-1` for programmatic
|
|
498
|
+
focus on Pane, SunkenPanel, static ContentItem, or a plain TabNavigator scene;
|
|
499
|
+
`outlined` holds its standard focus ring for an app state such as a drop target.
|
|
500
|
+
Workbench uses `mainTabIndex`/`mainOutlined` for the center and
|
|
501
|
+
`tabIndex`/`outlined` per rail or drawer. Hidden scenes and collapsed panels
|
|
502
|
+
suppress those states. Never write a component's anatomy classes onto your
|
|
503
|
+
own element to recreate it (`KUI-L103`); only the catalog's `placeableClasses`
|
|
504
|
+
(layout utilities, `.kui-app-root`,
|
|
505
|
+
`.kui-content-item` on a non-div carrier) belong there. A visible pane owns
|
|
506
|
+
its collapse control (the last control of its last group); a hidden pane's
|
|
507
|
+
restore moves to the adjacent main toolbar's matching edge — no icon-only
|
|
508
|
+
rail — and a collapsed drawer's restore sits in the bottom toolbar or a
|
|
509
|
+
`FloatingToolbar` beside the drawer, near where its effect appears. Align
|
|
510
|
+
text to text and icons to icons across a pane; a border is decoration, never
|
|
511
|
+
the alignment anchor. Keep one scroll owner per region.
|
|
512
|
+
- **Dividers between pinned chrome and scrolling content are scroll state.**
|
|
513
|
+
Toolbars draw no divider by default. Call `wireScrollDividers(appRoot)`
|
|
514
|
+
(`@kerfjs/ui/wire-scroll-dividers`) once and keep its disposer: every `Pane`
|
|
515
|
+
with `chromeDividers="scroll"` then draws the line under its header only while content is scrolled beneath
|
|
516
|
+
it and the line over its footer only while more content lies below (never
|
|
517
|
+
when the content fits), every `NavStack`'s top chrome and bottom toolbar and
|
|
518
|
+
every `TabNavigator` bar do the same around the active view or scene, and
|
|
519
|
+
every `TabBar` marks each side of its strip with tabs scrolled out of view. Configure a pane with `chromeDividers`
|
|
520
|
+
(`scroll` for a plain pane by default, `always` for a sunken pane by default,
|
|
521
|
+
or explicit `scroll`, `always`, `none`), and a `NavStack` or `TabNavigator`
|
|
522
|
+
with its own `chromeDividers` (same values; a `SplitView` forwards it through
|
|
523
|
+
`compactStack`); name app-owned chrome in `targets`.
|
|
524
|
+
A `TabNavigator` also takes `separator="auto" | "hidden"`: auto draws the
|
|
525
|
+
bar's top edge beside a sunken active scene or nested Pane even when content
|
|
526
|
+
fits; hidden suppresses that edge, including scroll dividers.
|
|
527
|
+
Never add a border, or a permanent `dividerSides`, to fake one.
|
|
528
|
+
For a header that floats over its scrolling content, set
|
|
529
|
+
`headerPresentation="overlay"` on the `Pane` (or in `PaneConfig`). It paints
|
|
530
|
+
the translucent chrome material (`--kui-chrome-material`, opaque under
|
|
531
|
+
reduced transparency, increased contrast, and forced colors). The same
|
|
532
|
+
`wireScrollDividers` call measures the header and publishes its height as
|
|
533
|
+
block-start scroll clearance, which the content clears automatically. Keep
|
|
534
|
+
overlay-header text in the normal text color.
|
|
535
|
+
For a translucent stack bar laid over the active view, set
|
|
536
|
+
`chromePresentation="overlay"` on the `NavStack`. `wireNavStack` measures
|
|
537
|
+
the top chrome and hands its height (top safe area included) to the views
|
|
538
|
+
as their block-start inset, so a plain view or a sole `Pane` clears it
|
|
539
|
+
automatically. Keep its text in the normal text color. For a translucent
|
|
540
|
+
bottom toolbar, set `bottomToolbarPresentation="overlay"` (separate from
|
|
541
|
+
`chromePresentation`); `wireNavStack` hands its height (bottom safe area
|
|
542
|
+
included) to the views as their block-end inset, so the last item rests
|
|
543
|
+
just above it. Its `ToolbarText` and default-tone `ToolbarControlGroup`
|
|
544
|
+
controls lift themselves to AA. For a translucent tab bar, set
|
|
545
|
+
`barPresentation="overlay"` on the `TabNavigator`; `wireTabNavigator`
|
|
546
|
+
measures the bar and the scenes hand its height to their content as the
|
|
547
|
+
block-end inset. Its tab labels lift themselves to AA.
|
|
548
|
+
While a side overlay is open (a Workbench rail overlay, a `wireSidebar` compact
|
|
549
|
+
overlay, an overlay `CollapsiblePanel` or horizontal `ResizableRegion`), the
|
|
550
|
+
layout hides the covered work area's `FloatingToolbar`s and restore corners
|
|
551
|
+
itself (unfocusable, out of the accessibility tree) until it closes — do not
|
|
552
|
+
hide them from overlay state yourself.
|
|
127
553
|
- **State and behavior live in the app.** Components take semantic `data-action`
|
|
128
554
|
strings and controlled values; wire them once with `delegate()`/`delegateActions()`
|
|
129
555
|
or the disposer-returning `wire…` helpers, and own domain copy, transport, and
|
|
@@ -133,11 +559,32 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
133
559
|
navigation stacks, tab selection and order, pane sizes, and `collapsed`/`expanded`
|
|
134
560
|
disclosure flags in the app — they are data or persisted layout, and the app reads
|
|
135
561
|
them to render. The `wire…` helpers own the _ephemeral_ parts: `wireNavStack` the
|
|
136
|
-
|
|
562
|
+
content-slide, per-view top/bottom chrome cross-fade, and focus move/restore
|
|
563
|
+
(mark a preferred new-view target with `data-nav-focus`), `wireTabBars` the
|
|
564
|
+
overflow autoscroll, drag preview, and
|
|
137
565
|
replacement focus after controlled automatic tab activation,
|
|
138
|
-
`wireResizableRegions` the live drag preview
|
|
139
|
-
|
|
140
|
-
|
|
566
|
+
`wireResizableRegions` the live drag preview, `wireScrollDividers` the
|
|
567
|
+
scroll-state attributes from which a `Pane` draws its chrome dividers and a
|
|
568
|
+
`TabBar` its overflow dividers; they report committed changes via
|
|
569
|
+
callbacks. For a tab-local action plus a separate far-edge action, set
|
|
570
|
+
`TabBar trailingPlacement="adjacent"`, put the local action in `trailing`, and
|
|
571
|
+
the workspace action in `end`; the component keeps both visible while its tab
|
|
572
|
+
list shrinks and scrolls, without application descendant CSS. Each action
|
|
573
|
+
zone accepts one ToolbarControlGroup or a standalone `wa-button` for its own
|
|
574
|
+
Web Awesome chrome. Managed
|
|
575
|
+
TokenSearchField clear also preserves open state and replacement
|
|
576
|
+
editor focus before the next input task, so shortcut-letter typing stays in search.
|
|
577
|
+
Select All deletion does the same; deletion
|
|
578
|
+
restoration finishes before the next keystroke rather than on a delayed frame.
|
|
579
|
+
Persist both query and remaining tokens read from an edited field; change
|
|
580
|
+
`revision` to replace unmanaged DOM-owned text programmatically, or call
|
|
581
|
+
`model.replace({ query, tokens })` for a model-managed field. In grammar-assisted
|
|
582
|
+
search, a model rule's `suggest(input, state)` receives current committed tokens
|
|
583
|
+
so suggestions can omit selected values; one-argument callbacks still work.
|
|
584
|
+
A sibling helper can call `model.commit(value)` for the active `name:` prefix
|
|
585
|
+
even when that value is not suggested; invalid values and missing prefixes
|
|
586
|
+
leave state unchanged.
|
|
587
|
+
The one richer case is `wireTokenSearchFields`, which manages the
|
|
141
588
|
collapsible field's expand/collapse/focus by default (on, per-behavior opt-out) and
|
|
142
589
|
exposes the `expanded` signal on its handle — bind it in render or hand in your own
|
|
143
590
|
via `collapsible.signals`. Do not hand-roll open/collapse/focus that helper
|
|
@@ -149,43 +596,211 @@ maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
|
149
596
|
`onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an
|
|
150
597
|
`onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — so the app can drop its own keydown/input
|
|
151
598
|
boilerplate while still owning parsing and controlled token state.
|
|
599
|
+
When `onEdit` or `onRemoveToken` changes tokens and the controlled render
|
|
600
|
+
replaces the focused editor, the helper hands focus and caret to the new
|
|
601
|
+
editor in the same task (end stays at end), so do not add a refocus
|
|
602
|
+
`MutationObserver` or `requestAnimationFrame`.
|
|
152
603
|
- **Placeholder loading state, don't rebuild it.** For a value or component that is
|
|
153
604
|
still loading, set `placeholder` on the component (`Select`, `ListHeader`,
|
|
154
|
-
`ListItem`, `ValueTableRow`, `
|
|
605
|
+
`ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`,
|
|
155
606
|
`AppTab`, `ToolbarText`, `ListActionRow`): it renders its real chrome with value
|
|
156
|
-
slots as subtle **unanimated** skeleton blocks and interactivity disabled
|
|
157
|
-
|
|
158
|
-
|
|
607
|
+
slots as subtle **unanimated** skeleton blocks and interactivity disabled. Only
|
|
608
|
+
unknown values change: a placeholder is never dimmed or styled as disabled (a
|
|
609
|
+
control you disabled keeps its live disabled tone), so a parent composes a
|
|
610
|
+
faithful loading view (e.g. an inspector) without hand-rebuilding markup.
|
|
611
|
+
Component-drawn chrome stays live: a `ListItem` or `ListActionRow` keeps its
|
|
612
|
+
`busy` spinner while its `status` (and a `ListItem`'s `trailing`) content
|
|
613
|
+
become skeletons. Use the standalone `Skeleton` for a custom slot. Prefer it over `wa-skeleton`
|
|
159
614
|
(the pure-Kerf primitives avoid Web Awesome), and never animate it — use
|
|
160
|
-
`LoadingSpinner` for known busy activity instead.
|
|
615
|
+
`LoadingSpinner` for known busy activity instead. Set its `size` prop to a
|
|
616
|
+
named icon step or positive pixel number when the inherited 1em is unsuitable.
|
|
617
|
+
- **Keep ListItem content inside the row.** The rounded `ListItem` root clips
|
|
618
|
+
overflowing label, status, and dormant trailing content. Set `multiline` when
|
|
619
|
+
the primary label should wrap; use `ListActionRow` instead when trailing content
|
|
620
|
+
must be interactive.
|
|
621
|
+
- **Dialog bodies are lists by default.** Compose rows and sections in `List`,
|
|
622
|
+
use `DialogSurface bodyInset="none"` when those children own their geometry,
|
|
623
|
+
and wrap bare prose in `ListInsetText` so it shares the standard list gutter
|
|
624
|
+
without stacking a second body inset.
|
|
161
625
|
- **Use a StateBanner badge only for compact supporting status.** Pass the
|
|
162
626
|
optional string `badge` for a terse count or status beside the title. It
|
|
163
627
|
inherits the banner tone and is announced with the banner, so keep its text
|
|
164
628
|
meaningful and never rely on color alone.
|
|
629
|
+
- **Configure StateBanner copy and action placement.** `copyLayout="stacked"`
|
|
630
|
+
puts detail below the title and badge; `actionPlacement="below"` always
|
|
631
|
+
gives the action a separate trailing row. The default trailing action stays
|
|
632
|
+
beside the copy while it has room and wraps onto its own trailing row on a
|
|
633
|
+
narrow banner, so do not switch placement per breakpoint.
|
|
634
|
+
`presentation="strip"` renders a flush, square, full-width band for a
|
|
635
|
+
layout edge with tone-colored `dividerSides` (bottom by default) instead of
|
|
636
|
+
the inset rounded card; never restyle a card into a strip.
|
|
637
|
+
- **Use `SplitButton` for a primary action with options.** One loud semantic
|
|
638
|
+
fill with a native primary button and an options trigger (`aria-expanded`,
|
|
639
|
+
`aria-haspopup`); `tone`, `fill`, `busy`, and `disabled` are props. Never
|
|
640
|
+
build one from `wa-button-group` or app CSS on native buttons.
|
|
641
|
+
- **Use `IconToggleButton` for an icon toggle outside a Toolbar.** In content or a
|
|
642
|
+
pane footer, `IconToggleButton({ icon, iconName, label, pressed, action })`
|
|
643
|
+
gives a native `aria-pressed` button the single contained toolbar group's
|
|
644
|
+
geometry; never wrap a `ToolbarControlGroup` outside a toolbar or restyle a
|
|
645
|
+
button to match it.
|
|
646
|
+
- **Let an icon-state toggle skip selected chrome.** When a pressed toggle's
|
|
647
|
+
glyph already shows its state (an empty or filled star), set
|
|
648
|
+
`data-selected-chrome="none"` on that button, or `selectedChrome="none"` on
|
|
649
|
+
its `ToolbarControlGroup`; never override the group's pressed-button styles.
|
|
650
|
+
- **Lay out a `ValueTable` through its props.** `labelWidth` sets a minimum
|
|
651
|
+
label column, `presentation="stacked"` puts values under labels, and
|
|
652
|
+
`stackBelow="compact" | "narrow"` stacks only while the table is narrower
|
|
653
|
+
than 512px/576px; do not override `--kui-value-table-row-columns`.
|
|
654
|
+
- **Show selectable item summaries with `SummaryRow`.** One `role="option"`
|
|
655
|
+
per item as a list `row` or board `card`, with a state `rail`, a clamped
|
|
656
|
+
`title`, `trailingMeta`, a `metadata` line, `selected`, `dimmed`, and
|
|
657
|
+
`listEdge` rounding; the app owns the listbox and keyboard movement. Never
|
|
658
|
+
hand-roll ticket-row chrome.
|
|
659
|
+
- **Group settings rows in `FramedList`.** For rows of arbitrary content in
|
|
660
|
+
one rounded frame with dividers between them (settings, account cards,
|
|
661
|
+
shortcut lists), compose `FramedListRow`s; `ValueTable` is the same frame for
|
|
662
|
+
label/value facts. Never hand-roll a `ul` with borders and row padding.
|
|
663
|
+
- **Bound a result picker with a framed `List`.** For a bordered, scrolling
|
|
664
|
+
list of `ListItem` rows (search results, duplicate candidates), use
|
|
665
|
+
`<List scrollable frame maxHeight={rem(14)} minHeight={rem(4.25)}>`:
|
|
666
|
+
`frame` draws a 1px neutral border, the control radius, and a 4px inset
|
|
667
|
+
that keeps the first and last rows' focus rings inside the clip, and the
|
|
668
|
+
typed `CssLength` bounds need no flex-column ancestor. Never wrap a List in
|
|
669
|
+
an app div with `max-height`, `overflow`, and a border.
|
|
670
|
+
- **Square an icon-only button with `IconButton`.** Web Awesome squares a
|
|
671
|
+
`wa-button` only for a lone `wa-icon`; with a `LucideIcon` use
|
|
672
|
+
`IconButton({ icon, iconName, label })` (label required) instead of
|
|
673
|
+
overriding `wa-button::part(base)`. Inside a `ToolbarControlGroup` keep a
|
|
674
|
+
native `button`; the group owns its geometry.
|
|
675
|
+
- **Paint a strip's surface with `List surface`.** `surface="base"` or
|
|
676
|
+
`"raised"` fills a List and its insets with a solid surface (a banner strip
|
|
677
|
+
above a sunken work area); never wrap it in app CSS that sets a background.
|
|
678
|
+
- **Use `Combobox` to pick or create a value by typing.** A themed native
|
|
679
|
+
input on the ARIA combobox pattern with filtered suggestions and an optional
|
|
680
|
+
create option; `wireComboboxes(root, { onCommit })` reports `{ id, value,
|
|
681
|
+
created, input }`. Never use a hand-styled `<input list>` + `<datalist>`.
|
|
682
|
+
- **Pick or drop files with `FilePickerTrigger` / `FileDropZone`.** Both wrap
|
|
683
|
+
a real, visually hidden file input; `wireFilePickers(root, { onFiles })`
|
|
684
|
+
reports browsed and dropped files and highlights the zone while dragging.
|
|
685
|
+
Never hand-style a file input, its label, or a dashed drop target.
|
|
686
|
+
- **Swap content in place with `ContentSwap`.** Two sides share one cell;
|
|
687
|
+
`active`, `transition` (`push`, `crossfade`, `none`), and `direction` drive
|
|
688
|
+
Kerf-owned motion with an inert, hidden inactive side and reduced-motion
|
|
689
|
+
fallback. Use `NavStack` for full views with toolbars.
|
|
690
|
+
- **Lay out a kanban board with `ColumnTrack`.** Equal columns that never
|
|
691
|
+
narrow below `minColumnWidth` scroll sideways; `layout="paged"` pages one
|
|
692
|
+
column at a time with a peek and snapping. Never re-track a `Grid` or
|
|
693
|
+
hand-roll scroll-snap CSS.
|
|
694
|
+
- **Show ambient activity with `EdgeActivityIndicator`.** A layout-free,
|
|
695
|
+
pointer-inert top-edge strip whose bars ripple while `busy`, with an optional
|
|
696
|
+
polite `message` pill; Kerf owns the wave and reduced motion. Never hand-roll
|
|
697
|
+
fixed bars, keyframes, or a hanging pill in app CSS.
|
|
698
|
+
- **Host app-level progress in `CornerStatus`.** For a non-dismissible
|
|
699
|
+
"Loading…" or "Updating… N of M" with no home beside the affected work, put
|
|
700
|
+
a `StateBanner` (`urgency="status"`) inside `CornerStatus` and call
|
|
701
|
+
`wireCornerStatus` once: a top-layer manual popover at a safe-area-aware
|
|
702
|
+
corner, with no close button, light dismiss, Escape, or focus change. Never
|
|
703
|
+
position a banner with fixed-position CSS or hide a toast's close part.
|
|
704
|
+
- **Size a Select through its API.** `triggerWidth` chooses `fit-content`,
|
|
705
|
+
`max-content`, or `fill`; `--kui-select-trigger-max-width` caps it. For custom
|
|
706
|
+
selected text, use the public color, font-size, and font-weight tokens; the
|
|
707
|
+
closed value ellipsizes when space runs out. `presentation="title"` gives a
|
|
708
|
+
rail view heading a 36px bold, flush-start trigger and adjacent caret;
|
|
709
|
+
`focusRingInset` keeps its ring inside clipping ancestors.
|
|
710
|
+
- **Configure application tabs at their owners.** AppTab's `icon-only`
|
|
711
|
+
presentation keeps `name` accessible, `labelMaxWidth` ellipsizes a long name,
|
|
712
|
+
`nameOverflow="visible"` shows the full name during inline loading, and
|
|
713
|
+
`dropTarget` highlights a drag-over without changing selection. `attention`
|
|
714
|
+
uses `--kui-app-tab-attention-color`. TabBar's public
|
|
715
|
+
`--kui-tab-bar-strip-*` tokens set compact strip geometry.
|
|
716
|
+
An inspector TabBar uses the shared rounded rectangle radius on its strip
|
|
717
|
+
and inset segmented tabs; an ordinary segmented TabBar keeps pill ends and
|
|
718
|
+
smaller interior tab corners. Configure the presentation instead of
|
|
719
|
+
restyling AppTab.
|
|
720
|
+
Set `pinned` on the first AppTab to keep it visible within a scrolling
|
|
721
|
+
tablist; it remains in keyboard order. Use `--kui-app-tab-pinned-background`
|
|
722
|
+
for the surrounding surface and keep that backdrop opaque.
|
|
723
|
+
- **Use `Badge` for compact non-interactive metadata.** Configure its semantic
|
|
724
|
+
tone, appearance, shape, and size instead of creating badge CSS in an app or
|
|
725
|
+
consuming component. Use a real button or link for interactive content.
|
|
726
|
+
For new content without a count, use the text-free `size="dot"` form: it
|
|
727
|
+
takes no children, and needs a `label` (announced as an image) or
|
|
728
|
+
`ariaHidden` when its owner announces it. A `TabNavigator` tab shows the dot
|
|
729
|
+
with `badge: true` plus its required `badgeLabel`. A text badge takes a
|
|
730
|
+
decorative leading `icon`, a `title` tooltip, and `data-*` `rootAttributes`
|
|
731
|
+
for app identity; never wrap a Badge or nest a `Row` in it for those.
|
|
732
|
+
For app-supplied text that can run long (a tag or category name), set
|
|
733
|
+
`maxWidth` (a `CssLength`, such as `px(160)`): the label truncates with an
|
|
734
|
+
ellipsis and string or number content becomes the hover `title`.
|
|
735
|
+
- **Use `Chip` for removable tags.** Give the native remove button a delegated
|
|
736
|
+
`removeAction` and a specific `removeLabel`; the application updates the tag
|
|
737
|
+
list. `itemId` identifies the chip to the action handler. `size="compact"`
|
|
738
|
+
gives a 20px chip and 16px remove button; `disabled` disables removal.
|
|
739
|
+
- **Use a link `Chip` for downloadable files and short links.** `href` renders a
|
|
740
|
+
native `<a>` with chip geometry; `download` (`true` or a file name) and
|
|
741
|
+
`external` (new tab, safe rel, announced) are optional, and a link chip has
|
|
742
|
+
no remove button. Inside a ContentItem bubble set `tone="inherit"` so it
|
|
743
|
+
follows the bubble's foreground instead of styling an anchor yourself.
|
|
744
|
+
- **Use `ChoiceChips` for a wrapping exclusive choice.** When one value comes
|
|
745
|
+
from a visible set too large for a `SegmentedControl` track (a nine-color
|
|
746
|
+
palette in a 560px dialog), render separate pills backed by native radios:
|
|
747
|
+
one Tab stop, arrow-key selection, and a real form value under `name`. Name
|
|
748
|
+
the group with `label` or `labelledBy`, lead choices with a `swatch`
|
|
749
|
+
(`CssColor` such as `fillColor('#3b82f6')`, or `'transparent'` for the struck-through no-color dot) or an
|
|
750
|
+
`icon`, and handle the delegated `action` on `change`. Never wrap a
|
|
751
|
+
`SegmentedControl` or button-appearance `wa-radio` set instead. Set
|
|
752
|
+
`multiple` (with a `readonly Value[]` `value`) when any number may be on:
|
|
753
|
+
the same pills become native checkboxes in a `role="group"`, each a Tab stop
|
|
754
|
+
that Space toggles, and every checked value submits under `name`. On dark
|
|
755
|
+
inverse chrome, place the chips in a dark appearance scope (`.wa-dark`)
|
|
756
|
+
instead of restyling them.
|
|
757
|
+
|
|
758
|
+
- **Use `Composer` for a chat or prompt composer.** `@kerfjs/ui/composer`
|
|
759
|
+
renders a raised frame (standard border, large radius, `shadow-l`) whose
|
|
760
|
+
border turns brand while focus is within, a borderless textarea that grows
|
|
761
|
+
between `minRows` (default 1) and `maxRows` (default 8) lines and then
|
|
762
|
+
scrolls, and an action row with an optional quiet `hint` and the trailing
|
|
763
|
+
`actions` (a brand Send button). Name it with a title-style `label`; give it
|
|
764
|
+
an `id` so the hint describes the field. Slot it into a `DialogSurface`
|
|
765
|
+
floating footer (`footerInset="none"`) over a transcript. Never rebuild
|
|
766
|
+
composer chrome around a `wa-textarea` with app CSS. For Enter-to-send, set
|
|
767
|
+
`submitOnEnter` and call `wireComposers(root)` from
|
|
768
|
+
`@kerfjs/ui/wire-composers` once: Enter or Cmd/Ctrl+Enter clicks the first
|
|
769
|
+
trailing action, Shift+Enter inserts a newline, and an IME composition
|
|
770
|
+
commit or an empty message never sends. Never hand-roll that handler.
|
|
165
771
|
|
|
166
772
|
## Public exports
|
|
167
773
|
|
|
168
|
-
`LucideIcon`, `DisclosureArrow`, `Toolbar`, `ToolbarControlGroup`, `FloatingToolbar`, `ToolbarText`,
|
|
169
|
-
`
|
|
170
|
-
`ListInsetText`, `SegmentedControl`,
|
|
774
|
+
`Badge`, `LucideIcon`, `DisclosureArrow`, `Toolbar`, `ToolbarControlGroup`, `ToolbarActionLink`, `FloatingToolbar`, `ToolbarText`, `Text`,
|
|
775
|
+
`ListItem`, `ListActionRow` (+ `wireListReorder`, `reorderListItems`), `wireListFocusScroll`, `ListHeader`, `ListInsetControl`,
|
|
776
|
+
`ListInsetText`, `SegmentedControl`, `ChoiceChips`, `Composer`,
|
|
171
777
|
`Select`, `TokenSearchField` (+ `readTokenSearchField`, `placeTokenSearchCaret`,
|
|
172
778
|
`wireTokenSearchFields`), `AppTab`, `TabBar` (+ `wireTabBars`, `reorderTabs`),
|
|
779
|
+
`wireScrollDividers` (scroll-state dividers for every `Pane`, `NavStack`,
|
|
780
|
+
`TabNavigator`, and `TabBar`),
|
|
173
781
|
`ResizableRegion` (+ `wireResizableRegions`), `StateBanner`, `EmptyState`,
|
|
174
782
|
`LoadingSpinner`, `Skeleton`, `ValueTable`, `ValueTableRow`. Whole-screen layouts (opt-in,
|
|
175
|
-
tree-shakeable, declarative with `wire…` helpers
|
|
176
|
-
|
|
783
|
+
tree-shakeable, declarative with `wire…` helpers; the browser build of each layout
|
|
784
|
+
subpath loads its CSS and that of the components it renders, and a companion
|
|
785
|
+
CSS subpath remains for pipelines without the `browser` condition):
|
|
786
|
+
`NavStack`, `SplitView`, `Workbench`, `TabNavigator`, driven by `deviceClass()` from
|
|
177
787
|
`@kerfjs/ui/device-class`. For a standalone collapsible rail/drawer outside a full
|
|
178
788
|
shell, `@kerfjs/ui/collapsible-panel` (`CollapsiblePanel`, `CollapsiblePanelToggle`)
|
|
179
789
|
|
|
180
|
-
- `@kerfjs/ui/wire-sidebar` (`wireSidebar`: toggle, focus, compact overlay, persistence).
|
|
790
|
+
- `@kerfjs/ui/wire-sidebar` (`wireSidebar`: toggle, focus, compact overlay, persistence; a compact overlay starts closed and opens only on a user action, and `inlineCollapsed` declares a panel's inline default).
|
|
181
791
|
`@kerfjs/ui/catalog` is another opt-in shell — a
|
|
182
792
|
`Catalog` component + `wireCatalog` helper for building a component-gallery catalog
|
|
183
|
-
(collapsible category sidebar + preview stage + resources footer, with
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
793
|
+
(collapsible category sidebar + preview stage + resources footer, with
|
|
794
|
+
focus-preserving active-row reveal for long desktop sidebars) from your own
|
|
795
|
+
entries; controlled/stateless like the layouts. Its optional contrast, reduced
|
|
796
|
+
motion, theme, and preview-background controls are built in; pass state and
|
|
797
|
+
`wireCatalog` callbacks instead of recreating their toolbar markup, while your
|
|
798
|
+
app owns applying and persisting preferences. For any Catalog demo, follow
|
|
187
799
|
the [authoritative authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
|
|
188
|
-
rather than inferring structure from the shell or private CSS.
|
|
800
|
+
rather than inferring structure from the shell or private CSS. The shipped
|
|
801
|
+
Catalog stage fills the preview scroller for short specimens and grows with
|
|
802
|
+
tall ones in every consumer; do not add a demo-specific height or backdrop
|
|
803
|
+
override.
|
|
189
804
|
`@kerfjs/ui/webawesome` is a
|
|
190
805
|
type-only boundary for `wa-*` JSX; `@kerfjs/ui/select/register` and the CSS are the
|
|
191
806
|
declared side effects.
|
|
@@ -194,12 +809,43 @@ shell, `@kerfjs/ui/collapsible-panel` (`CollapsiblePanel`, `CollapsiblePanelTogg
|
|
|
194
809
|
|
|
195
810
|
- [skill.md](./ai/skill.md): the full rule set + a common-mistakes table (the shipped AI skill).
|
|
196
811
|
- [design-philosophy.md](./docs/design-philosophy.md): why kerf UI is shaped this way — the decision principles behind the rules above.
|
|
812
|
+
- [writing.md](./docs/writing.md): interface copy — the title-style vs. sentence-style capitalization rule per element, from Apple's guidance.
|
|
197
813
|
- [layout.md](./docs/layout.md): the pane/content-item geometry, public roles/tokens, and the spacing scale.
|
|
198
814
|
- [component-contract.md](./docs/component-contract.md): what a component owns vs. what the app owns.
|
|
199
815
|
- [accessibility.md](./docs/accessibility.md): keyboard and ARIA contracts per component.
|
|
200
816
|
- [recipes.md](./docs/recipes.md): production compositions (app shell, list-detail dialog, composer form, …) as copyable references.
|
|
201
|
-
- [
|
|
817
|
+
- [workbench.md](./docs/workbench.md): the `Workbench` multi-panel shell, its collapse policies, and opt-in `resizable` panels driven by `wireWorkbench` (`@kerfjs/ui/wire-workbench`: drag, keyboard, min/max, persistence, compact suspension), the `mainMinSize` / `mainMinHeight` work-area minimums (default 320px wide beside any inline rail, 120px tall above the drawer) that resizable panels stop at and inline panels shrink around, and a panel's `responsiveOverlayAt` (`narrow` / `compact`, rails and the bottom drawer) that presents it as an overlay below a Workbench container breakpoint without a device-class check; a panel given its `collapsed` signal is a transient overlay (collapsed on entering the breakpoint, takes focus and keeps Tab inside while open, closed by Escape or an outside press, focus returned; `dismissOverlays`), and overlays are exclusive by default (opening one closes the others; `exclusiveOverlays: false` opts out).
|
|
818
|
+
- [app-layouts.md](./docs/app-layouts.md): choosing `NavStack`/`SplitView`/`Workbench`/`TabNavigator` by data + interaction + device, and dialog presentation, plus the safe-area model (surfaces paint through unsafe areas; content pads only the edges it reaches; `Pane.safeAreaEdges` for app-owned arrangements, `Toolbar.safeAreaEdges` for an app bar or bottom bar at a screen edge).
|
|
202
819
|
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists). The UX sidebar visibly tags superseded and exceptional Web Awesome choices as `Discouraged`; Popup remains an available conditional positioning primitive.
|
|
820
|
+
- [ai/components/README.md](./ai/components/README.md): the generated per-component markdown reference — the assistant entry point over both JSON catalogs.
|
|
203
821
|
- [component-catalog.json](./ai/component-catalog.json) + [component-catalog-extension.schema.json](./ai/component-catalog-extension.schema.json) + [catalog-authoring.json](./ai/catalog-authoring.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable selection facts, a reusable app-component extension contract, Catalog authoring discovery, and exact signatures.
|
|
204
822
|
- [compile-time-contracts-v1.json](./ai/compile-time-contracts-v1.json) + [type-contracts.md](./docs/type-contracts.md): stable compile diagnostics, packed-declaration proof, migrations, and explicit non-goals.
|
|
205
823
|
- [README.md](./README.md): package overview and the component subpath table.
|
|
824
|
+
|
|
825
|
+
Neutral lowered surfaces and decorative neutral fills/borders are translucent theme colors; compose nested public components directly. Default/raised canvases, foregrounds, focus indicators, and loud contrast-bearing fills remain opaque. Do not assign depth-specific component tokens in demo wrappers.
|
|
826
|
+
|
|
827
|
+
Navigation transition continuity: `wireNavStack` slides the incoming view over the preserved previous view on push and the outgoing view off on pop, cross-fades both live chrome surfaces with inert snapshots, and settles/cancels an interrupted transition before starting the next. Reduced motion and duration zero settle immediately.
|
|
828
|
+
|
|
829
|
+
For a tab scene with drill-down, put a `NavStack` directly in `TabNavigatorTab.content`, configure each view's top `toolbar` and `pane`, and omit `bottomToolbar` at both levels so the scaffold bar remains the only bottom chrome. Wire both components on their own roots. The catalog's **NavStack inside a tab** example exercises push and tab switching.
|
|
830
|
+
|
|
831
|
+
`Pane.deepInset` (and `PaneConfig.deepInset`) or `TabNavigatorTab.deepInset` on a plain scene adds 8px on all four sides of the scroll content, so ordinary 8px item margins land 16px from the inline edge. Nested Row/List/Grid spacing stays at its default. Set a nested scene's Pane option instead of insetting its entire NavStack or toolbar.
|
|
832
|
+
For a child table whose decoration spans the Pane while its text stays aligned, use the Pane content slot's inherited `--kui-pane-content-inset-inline-start` and `--kui-pane-content-inset-inline-end`: negate them for the child's logical margins and add them to cell padding. They include safe areas and `deepInset`; see `docs/app-layouts.md#edge-to-edge-content-inside-a-pane`.
|
|
833
|
+
|
|
834
|
+
`ToolbarText` and `ToolbarControlGroup` accept typed `hideBelow`/`showBelow`
|
|
835
|
+
lengths (for example `px(416)`). Wire `wireToolbarVisibility(root)` from
|
|
836
|
+
`@kerfjs/ui/wire-toolbar-visibility` and dispose on unmount. Thresholds use the
|
|
837
|
+
nearest Toolbar content-box width: hideBelow hides strictly below, showBelow
|
|
838
|
+
shows strictly below, with complementary behavior at equality. Percentages use
|
|
839
|
+
that content width; em and custom properties use the item's own context. Invalid,
|
|
840
|
+
negative, unresolved, or contradictory values leave the item visible under this
|
|
841
|
+
width policy. Keep primary actions visible and offer a complementary overflow
|
|
842
|
+
group. See `docs/component-contract.md` "Toolbar width visibility" for lifecycle
|
|
843
|
+
details.
|
|
844
|
+
|
|
845
|
+
Select menus use native viewport shifting with 10px gutters: default menus grow to content (up to 20rem), while `fitMenu` matches trigger width and long labels wrap. Keep popup sizing and position repairs out of consumer CSS.
|
|
846
|
+
|
|
847
|
+
Key sibling `DialogSurface`s that render conditionally with `rootAttributes={{ "data-key": "…" }}` so a re-render morphs each dialog into itself; never wrap one in a keyed app `div`. Modal `DialogSurface` bounds use typed `viewportGutter` and `maxHeight` (`CssLength` or `"viewport"`); explicit caps stay within the dynamic viewport minus both gutters. Omitted props preserve Web Awesome defaults. Application render state chooses responsive values, and preview layout remains application-owned. `height` sets a definite bounded modal size and `bodyLayout="fill"` lets one child fill the body; `bodyLayout="fill-last"` keeps leading rows at their height above one filling last child, and `footerPresentation="floating"` (with a typed `footerOffset`) floats a chat composer over the body while the body reserves its measured height; give the transcript `scrollClearance="block-end"` (a `scrollable` `List` or a `Pane`) to let it scroll beneath the composer, with the last message still resting above it, through the published `--kui-scroll-clearance-block-end` context (overlaying chrome publishes `--kui-scroll-clearance-block-start` / `-end`; one scroller per covered edge opts in; a composed Pane opts in through `PaneConfig.scrollClearance` on a Workbench `mainPane` or panel `pane`, a `CollapsiblePanel` `pane`, or a `NavStack` view's `pane`). `headerPresentation="floating"` lays the title bar over the body on the translucent `--kui-chrome-material-raised` (opaque under reduced transparency, increased contrast, and forced colors); the register measures it and the body reserves it, and a `fill` body's only child with `scrollClearance="both"` scrolls beneath both the title bar and a floating composer through the published `--kui-scroll-clearance-block-start`. `PopoverDialogSurface` is the non-modal, light-dismiss counterpart on the native Popover API, with the same size props and an `embedded` in-flow presentation; `describedBy` sets its `aria-describedby` (usually a title `ToolbarText`'s `descriptionId`).
|
|
848
|
+
|
|
849
|
+
Import `@kerfjs/ui/surface-scaffold/register` once when using `DialogSurface`: it registers `wa-dialog` and repairs Web Awesome 3.12 native dialog names before the first modal opening. Headed dialogs reference the rendered title, including live slotted labels; headerless dialogs use the public `label`. Explicit host `aria-label` and pre-existing native names are preserved. A host that is itself an explicit dialog (`role="dialog"` or `"alertdialog"` with its own name) keeps that name alone: the native panel is left unnamed, so one dialog carries the name. Geometry-only markup stays CSS-free and does not register Web Awesome implicitly.
|
|
850
|
+
|
|
851
|
+
Toolbar visibility measurement probes and invisible state children are helper-owned and survive Kerf rerenders through `data-morph-preserve`. Actual CSS visibility stays stable while rendering removes transient parent markers, preventing geometry-driven render feedback and repeated probe recreation. Toolbar replacement, explicit internal-node removal and disposal retain their existing behavior.
|