@kerfjs/ui 5.0.0-beta.97 → 5.0.0-beta.99
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 +42 -1
- package/ai/application-ui-diagnostic-ids-v1.json +1 -0
- package/ai/component-catalog.json +487 -66
- package/ai/component-catalog.schema.json +1 -1
- package/ai/component-composition-rules.json +22 -2
- package/ai/component-composition.json +360 -33
- package/ai/component-composition.schema.json +1 -1
- package/ai/components/README.md +18 -17
- package/ai/components/anchored-surface.md +13 -0
- package/ai/components/application-tabs.md +1 -1
- package/ai/components/chip.md +9 -5
- package/ai/components/choice-chips.md +15 -8
- package/ai/components/collapsible-panel.md +3 -2
- package/ai/components/composer.md +83 -0
- package/ai/components/content-item.md +2 -2
- package/ai/components/corner-status.md +1 -1
- package/ai/components/document-baseline.md +3 -3
- package/ai/components/foundation.md +2 -2
- package/ai/components/layout.md +1 -1
- package/ai/components/list-action-row.md +5 -1
- package/ai/components/list-item.md +5 -1
- package/ai/components/list.md +19 -3
- package/ai/components/nav-stack.md +11 -2
- package/ai/components/pane.md +13 -4
- package/ai/components/popup-menu.md +4 -4
- package/ai/components/recipe-app-shell.md +3 -3
- package/ai/components/recipe-collapsible-sidebar.md +3 -3
- package/ai/components/recipe-compact-toolbar.md +1 -1
- package/ai/components/recipe-composer-form.md +3 -3
- package/ai/components/recipe-list-detail-dialog.md +2 -2
- package/ai/components/recipe-list-workspace-states.md +3 -3
- package/ai/components/recipe-loading-inspector.md +1 -1
- package/ai/components/recipe-navigation-sidebar.md +3 -3
- package/ai/components/recipe-navigation-stack.md +3 -3
- package/ai/components/recipe-workspace-header.md +3 -3
- package/ai/components/resize.md +2 -2
- package/ai/components/split-view.md +4 -2
- package/ai/components/sunken-panel.md +2 -2
- package/ai/components/surface-scaffold.md +15 -3
- package/ai/components/tab-bar.md +1 -0
- package/ai/components/tab-navigator.md +4 -0
- package/ai/components/toolbar-control-group.md +2 -0
- package/ai/components/toolbar-text.md +1 -0
- package/ai/components/toolbar.md +1 -0
- package/ai/components/workbench.md +1 -0
- package/ai/public-api-signatures-v1.md +504 -80
- package/ai/skill.md +41 -14
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/component-ownership.mjs +1 -1
- package/analyzer/index.mjs +41 -14
- package/dist/anchored-surface.d.ts +30 -2
- package/dist/anchored-surface.js +1 -1
- package/dist/app-tab.js +1 -1
- package/dist/browser/composer.js +4 -0
- package/dist/catalog-resources.d.ts +3 -2
- package/dist/catalog-resources.js +4 -4
- package/dist/catalog-resources.js.map +1 -1
- package/dist/catalog.d.ts +39 -8
- package/dist/catalog.js +55 -32
- package/dist/catalog.js.map +1 -1
- package/dist/chip.d.ts +41 -9
- package/dist/chip.js +1 -1
- package/dist/choice-chips.d.ts +40 -16
- package/dist/choice-chips.js +1 -1
- package/dist/chunk-34U4ANDJ.js +119 -0
- package/dist/chunk-34U4ANDJ.js.map +1 -0
- package/dist/{chunk-36TL6BCR.js → chunk-3GLYIIFR.js} +34 -6
- package/dist/chunk-3GLYIIFR.js.map +1 -0
- package/dist/{chunk-HWY4BSLS.js → chunk-3VXDSIBJ.js} +2 -2
- package/dist/{chunk-HWY4BSLS.js.map → chunk-3VXDSIBJ.js.map} +1 -1
- package/dist/chunk-3WYREXW4.js +120 -0
- package/dist/chunk-3WYREXW4.js.map +1 -0
- package/dist/chunk-AV7CPAPT.js +82 -0
- package/dist/chunk-AV7CPAPT.js.map +1 -0
- package/dist/{chunk-XK4E225T.js → chunk-B53PS2LE.js} +2 -2
- package/dist/{chunk-XK4E225T.js.map → chunk-B53PS2LE.js.map} +1 -1
- package/dist/{chunk-R42D2BAO.js → chunk-CA7LNX3J.js} +2 -2
- package/dist/{chunk-R42D2BAO.js.map → chunk-CA7LNX3J.js.map} +1 -1
- package/dist/{chunk-AYHC62OZ.js → chunk-CMETHPKR.js} +26 -29
- package/dist/chunk-CMETHPKR.js.map +1 -0
- package/dist/{chunk-Y43B6DS3.js → chunk-CVD5IZGB.js} +2 -2
- package/dist/{chunk-Y43B6DS3.js.map → chunk-CVD5IZGB.js.map} +1 -1
- package/dist/{chunk-6STQXRT4.js → chunk-CXZXHZTR.js} +121 -12
- package/dist/chunk-CXZXHZTR.js.map +1 -0
- package/dist/{chunk-GZE2XVKC.js → chunk-DZJ4GBSP.js} +3 -3
- package/dist/{chunk-GZE2XVKC.js.map → chunk-DZJ4GBSP.js.map} +1 -1
- package/dist/chunk-ELCMSQNJ.js +49 -0
- package/dist/chunk-ELCMSQNJ.js.map +1 -0
- package/dist/{chunk-P74VXMB6.js → chunk-EOO6PYGF.js} +7 -14
- package/dist/chunk-EOO6PYGF.js.map +1 -0
- package/dist/{chunk-PRG4CL3Q.js → chunk-FR76ZJQC.js} +21 -19
- package/dist/chunk-FR76ZJQC.js.map +1 -0
- package/dist/{chunk-QQ3TTWFH.js → chunk-G3J7JDP6.js} +1 -1
- package/dist/{chunk-QQ3TTWFH.js.map → chunk-G3J7JDP6.js.map} +1 -1
- package/dist/{chunk-IGTWXPTN.js → chunk-HGV7J4T6.js} +3 -3
- package/dist/{chunk-IGTWXPTN.js.map → chunk-HGV7J4T6.js.map} +1 -1
- package/dist/{chunk-YWQGSUF2.js → chunk-HLDRH23D.js} +3 -3
- package/dist/{chunk-YWQGSUF2.js.map → chunk-HLDRH23D.js.map} +1 -1
- package/dist/{chunk-PBT3CPPY.js → chunk-HQZYKJ56.js} +24 -4
- package/dist/chunk-HQZYKJ56.js.map +1 -0
- package/dist/{chunk-V6W56V3N.js → chunk-HZPHCSCS.js} +16 -3
- package/dist/chunk-HZPHCSCS.js.map +1 -0
- package/dist/{chunk-GJYQ27C2.js → chunk-INI4WDWC.js} +8 -1
- package/dist/chunk-INI4WDWC.js.map +1 -0
- package/dist/{chunk-U657IHFB.js → chunk-IQSRHXZR.js} +10 -4
- package/dist/chunk-IQSRHXZR.js.map +1 -0
- package/dist/{chunk-KQDU7Z7P.js → chunk-K4AT3V3J.js} +2 -1
- package/dist/chunk-K4AT3V3J.js.map +1 -0
- package/dist/{chunk-QIAPOWHH.js → chunk-KCS6NJ3O.js} +2 -2
- package/dist/{chunk-QIAPOWHH.js.map → chunk-KCS6NJ3O.js.map} +1 -1
- package/dist/{chunk-UKKRPP56.js → chunk-LOSRXZAH.js} +2 -2
- package/dist/{chunk-UKKRPP56.js.map → chunk-LOSRXZAH.js.map} +1 -1
- package/dist/{chunk-ROZLJULF.js → chunk-MF6ZUUJZ.js} +8 -3
- package/dist/chunk-MF6ZUUJZ.js.map +1 -0
- package/dist/{chunk-6IVNMC6R.js → chunk-MHMWQ7RB.js} +2 -2
- package/dist/{chunk-6IVNMC6R.js.map → chunk-MHMWQ7RB.js.map} +1 -1
- package/dist/{chunk-JYD7G4RG.js → chunk-PIVY32AE.js} +15 -5
- package/dist/chunk-PIVY32AE.js.map +1 -0
- package/dist/{chunk-BU23Z5HZ.js → chunk-PYBBYSZ3.js} +13 -18
- 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-YXOMI7ES.js → chunk-QIG4IGUP.js} +2 -2
- package/dist/{chunk-YXOMI7ES.js.map → chunk-QIG4IGUP.js.map} +1 -1
- package/dist/{chunk-6BRRUPJY.js → chunk-QROYYGWU.js} +3 -3
- package/dist/chunk-QROYYGWU.js.map +1 -0
- package/dist/{chunk-FOQK4F3L.js → chunk-RHD7RKGI.js} +28 -7
- package/dist/chunk-RHD7RKGI.js.map +1 -0
- package/dist/{chunk-BBU2SPRE.js → chunk-T4WJ5VGP.js} +4 -4
- package/dist/{chunk-BBU2SPRE.js.map → chunk-T4WJ5VGP.js.map} +1 -1
- package/dist/{chunk-6NOLL5KG.js → chunk-TGLUDQP2.js} +3 -3
- package/dist/{chunk-6NOLL5KG.js.map → chunk-TGLUDQP2.js.map} +1 -1
- package/dist/{chunk-HO6FU3G7.js → chunk-TLMMFQWM.js} +4 -4
- package/dist/{chunk-HO6FU3G7.js.map → chunk-TLMMFQWM.js.map} +1 -1
- package/dist/chunk-UMKV7YVQ.js +20 -0
- package/dist/chunk-UMKV7YVQ.js.map +1 -0
- package/dist/{chunk-M2NRCFRO.js → chunk-VFYO3UGZ.js} +2 -2
- package/dist/{chunk-M2NRCFRO.js.map → chunk-VFYO3UGZ.js.map} +1 -1
- package/dist/{chunk-YOKEL75M.js → chunk-WVS6CUCT.js} +2 -2
- package/dist/{chunk-YOKEL75M.js.map → chunk-WVS6CUCT.js.map} +1 -1
- package/dist/{chunk-MN3POJFN.js → chunk-YMUIQRWK.js} +2 -2
- package/dist/{chunk-MN3POJFN.js.map → chunk-YMUIQRWK.js.map} +1 -1
- package/dist/{chunk-Y3LC7JQO.js → chunk-YOA5W5ZH.js} +2 -2
- package/dist/{chunk-Y3LC7JQO.js.map → chunk-YOA5W5ZH.js.map} +1 -1
- package/dist/{chunk-44A6LP54.js → chunk-YQ2AC4E2.js} +2 -2
- package/dist/{chunk-44A6LP54.js.map → chunk-YQ2AC4E2.js.map} +1 -1
- package/dist/chunk-ZNROKDSZ.js +54 -0
- package/dist/chunk-ZNROKDSZ.js.map +1 -0
- package/dist/collapsible-panel.d.ts +3 -2
- package/dist/collapsible-panel.js +4 -3
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/composer.d.ts +62 -0
- package/dist/composer.js +5 -0
- package/dist/composer.js.map +1 -0
- package/dist/corner-status.d.ts +1 -1
- package/dist/corner-status.js +1 -1
- package/dist/css-values.d.ts +9 -1
- package/dist/css-values.js +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/grid.js +1 -1
- package/dist/icon-button.js +1 -1
- package/dist/icon-toggle-button.js +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +40 -37
- package/dist/list-action-row.d.ts +10 -2
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
- package/dist/list-item.d.ts +10 -3
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +36 -4
- package/dist/list.js +1 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/{nav-stack-BvSKY448.d.ts → nav-stack-VXTumzKa.d.ts} +53 -4
- package/dist/nav-stack.d.ts +3 -2
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +40 -3
- package/dist/pane.js +1 -1
- package/dist/{panel-toolbar-CL9tYOkh.d.ts → panel-toolbar-vg6Ir5Dy.d.ts} +6 -1
- package/dist/popup-menu-register.d.ts +2 -1
- package/dist/popup-menu-register.js +97 -22
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.js +1 -1
- package/dist/row.js +1 -1
- package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
- package/dist/select-register.js +11 -0
- package/dist/select-register.js.map +1 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-button.js +1 -1
- package/dist/split-view.d.ts +7 -5
- package/dist/split-view.js +6 -3
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +6 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/anchored-surface.css +27 -1
- package/dist/styles/catalog/components/catalog-example-stack.css +5 -0
- package/dist/styles/catalog/components/catalog-example.css +33 -0
- package/dist/styles/catalog/components/catalog-stage.css +7 -0
- package/dist/styles/chip.css +70 -0
- package/dist/styles/components/actions/popup-menu/popup-menu.css +21 -4
- package/dist/styles/components/actions/toolbar/toolbar.css +19 -0
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +75 -0
- package/dist/styles/components/collections/list/list.css +77 -7
- package/dist/styles/components/collections/list-action-row/list-action-row.css +177 -22
- package/dist/styles/components/collections/list-item/list-item.css +158 -11
- package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +27 -1
- package/dist/styles/components/feedback/chip/chip.css +70 -0
- package/dist/styles/components/feedback/state-banner/state-banner.css +24 -13
- package/dist/styles/components/forms/composer/composer.css +100 -0
- package/dist/styles/components/forms/select/select.css +1 -0
- package/dist/styles/components/forms/token-search-field/token-search-field.css +13 -2
- package/dist/styles/components/layout/pane/pane.css +81 -2
- package/dist/styles/components/navigation/nav-stack/nav-stack.css +84 -0
- package/dist/styles/components/navigation/tab-bar/tab-bar.css +15 -4
- package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +79 -4
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +195 -0
- package/dist/styles/composer.css +100 -0
- package/dist/styles/foundation.css +66 -0
- package/dist/styles/list-action-row.css +177 -22
- package/dist/styles/list-item.css +158 -11
- package/dist/styles/list.css +77 -7
- package/dist/styles/nav-stack.css +84 -0
- package/dist/styles/pane.css +81 -2
- package/dist/styles/popup-menu.css +21 -4
- package/dist/styles/select.css +1 -0
- package/dist/styles/state-banner.css +24 -13
- package/dist/styles/styles.css +1 -0
- package/dist/styles/surface-scaffold.css +195 -0
- package/dist/styles/tab-bar.css +15 -4
- package/dist/styles/tab-navigator.css +79 -4
- package/dist/styles/token-search-field.css +13 -2
- package/dist/styles/toolbar-control-group.css +75 -1
- package/dist/styles/toolbar-text.css +75 -0
- package/dist/styles/toolbar.css +19 -0
- package/dist/styles/webawesome.css +18 -0
- package/dist/surface-scaffold-register.d.ts +6 -1
- package/dist/surface-scaffold-register.js +89 -3
- package/dist/surface-scaffold-register.js.map +1 -1
- package/dist/surface-scaffold.d.ts +66 -7
- package/dist/surface-scaffold.js +1 -1
- package/dist/tab-navigator.d.ts +23 -2
- package/dist/tab-navigator.js +2 -0
- package/dist/tab-navigator.js.map +1 -1
- package/dist/token-search-field.d.ts +1 -1
- package/dist/token-search-field.js +1 -1
- package/dist/{token-search-model-DTcTXWMS.d.ts → token-search-model-aYR0YAei.d.ts} +32 -2
- package/dist/token-search-model.d.ts +1 -1
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +1 -0
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +3 -2
- package/dist/wire-catalog.js +2 -2
- 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-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-nav-stack.js +135 -0
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-scroll-dividers.d.ts +9 -0
- package/dist/wire-scroll-dividers.js +1 -1
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-navigator.d.ts +3 -1
- package/dist/wire-tab-navigator.js +133 -1
- package/dist/wire-tab-navigator.js.map +1 -1
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +8 -3
- package/dist/workbench.js +2 -1
- package/docs/accessibility.md +132 -3
- package/docs/anchored-surface.md +46 -4
- package/docs/app-layouts.md +23 -2
- package/docs/apple-hig.md +1 -0
- package/docs/catalog.md +61 -9
- package/docs/collapsible-panel.md +9 -6
- package/docs/component-contract.md +46 -13
- package/docs/component-selection.md +147 -20
- package/docs/composer.md +143 -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 -1
- package/docs/design/templates/choice-chips.svg +1 -1
- 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-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 -1
- package/docs/design/templates/list-action-row/trailing-menu.svg +1 -1
- 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/size-l-dark.svg +1 -1
- package/docs/design/templates/list-header/size-l.svg +1 -1
- package/docs/design/templates/list-header/size-m-dark.svg +1 -1
- package/docs/design/templates/list-header/size-m.svg +1 -1
- package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
- package/docs/design/templates/list-header/size-xl.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/icon-tile-dark.svg +1 -0
- package/docs/design/templates/list-item/icon-tile.svg +1 -0
- 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-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-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 -1
- package/docs/design/templates/state-banner/strip.svg +1 -1
- package/docs/design/templates/state-banner/success-dark.svg +1 -1
- package/docs/design/templates/state-banner/success.svg +1 -1
- package/docs/design/templates/state-banner/warning-dark.svg +1 -1
- package/docs/design/templates/state-banner/warning.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/tab-bar-dark.svg +1 -1
- package/docs/design/templates/tab-bar.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-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/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-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-philosophy.md +9 -1
- package/docs/examples/command-palette-adapter.tsx +3 -3
- package/docs/layout.md +147 -14
- package/docs/nav-stack.md +132 -8
- package/docs/recipes.md +9 -9
- package/docs/split-view.md +3 -3
- package/docs/sunken-panel.md +2 -2
- package/docs/surface-scaffold.md +138 -7
- package/docs/tab-navigator.md +38 -1
- package/docs/type-contracts.md +16 -16
- package/docs/ui-analyzer.md +3 -1
- package/docs/ui-doctor.md +71 -0
- package/docs/ux-demo.md +6 -6
- package/docs/webawesome-theme.md +7 -0
- package/docs/workbench.md +10 -6
- package/docs/writing.md +152 -0
- package/doctor/copy-capitalization-checks.mjs +591 -0
- package/doctor/index.mjs +17 -8
- package/llms.txt +105 -11
- package/package.json +15 -1
- package/ux-demo/recipes/app-shell.tsx +11 -11
- package/ux-demo/recipes/collapsible-sidebar.tsx +12 -11
- package/ux-demo/recipes/compact-toolbar.tsx +10 -10
- package/ux-demo/recipes/composer-form.tsx +8 -8
- package/ux-demo/recipes/list-detail-dialog.tsx +13 -13
- package/ux-demo/recipes/list-workspace-states.tsx +13 -13
- package/ux-demo/recipes/loading-inspector.tsx +10 -10
- package/ux-demo/recipes/navigation-sidebar.tsx +7 -7
- package/ux-demo/recipes/navigation-stack.tsx +5 -5
- package/ux-demo/recipes/workspace-header.tsx +5 -5
- package/dist/chunk-36TL6BCR.js.map +0 -1
- package/dist/chunk-4LOK4634.js +0 -21
- package/dist/chunk-4LOK4634.js.map +0 -1
- package/dist/chunk-6BRRUPJY.js.map +0 -1
- package/dist/chunk-6STQXRT4.js.map +0 -1
- package/dist/chunk-76PWEN5Y.js +0 -64
- package/dist/chunk-76PWEN5Y.js.map +0 -1
- package/dist/chunk-AYHC62OZ.js.map +0 -1
- package/dist/chunk-BU23Z5HZ.js.map +0 -1
- package/dist/chunk-DQDTZE4W.js +0 -70
- package/dist/chunk-DQDTZE4W.js.map +0 -1
- package/dist/chunk-FOQK4F3L.js.map +0 -1
- package/dist/chunk-GJYQ27C2.js.map +0 -1
- package/dist/chunk-JYD7G4RG.js.map +0 -1
- package/dist/chunk-KQDU7Z7P.js.map +0 -1
- package/dist/chunk-P74VXMB6.js.map +0 -1
- package/dist/chunk-PBT3CPPY.js.map +0 -1
- package/dist/chunk-PRG4CL3Q.js.map +0 -1
- package/dist/chunk-ROZLJULF.js.map +0 -1
- package/dist/chunk-U657IHFB.js.map +0 -1
- package/dist/chunk-V6W56V3N.js.map +0 -1
package/docs/surface-scaffold.md
CHANGED
|
@@ -54,7 +54,7 @@ import { remify } from '@kerfjs/ui/css-values';
|
|
|
54
54
|
import { DialogSurface } from '@kerfjs/ui/surface-scaffold';
|
|
55
55
|
|
|
56
56
|
<DialogSurface preferredWidth={remify(832)} viewportGutter={remify(8)} maxHeight="viewport" bodyInset="none">
|
|
57
|
-
<wa-dialog label="Close
|
|
57
|
+
<wa-dialog label="Close Workspace">{/* Application-owned content and footer */}</wa-dialog>
|
|
58
58
|
</DialogSurface>;
|
|
59
59
|
```
|
|
60
60
|
|
|
@@ -86,12 +86,129 @@ itself stops scrolling. Combine it with `bodyInset="none"`.
|
|
|
86
86
|
|
|
87
87
|
```tsx
|
|
88
88
|
<DialogSurface size="large" height={remify(640)} viewportGutter={remify(8)} bodyInset="none" bodyLayout="fill">
|
|
89
|
-
<wa-dialog label="Repository
|
|
89
|
+
<wa-dialog label="Repository Status">
|
|
90
90
|
<SplitView id="repo-split" label="Changes" listWidth={{ size: 432, maxFraction: 0.5 }} list={list} detail={detail} />
|
|
91
91
|
</wa-dialog>
|
|
92
92
|
</DialogSurface>;
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Chat dialogs: a floating footer over a filling transcript
|
|
96
|
+
|
|
97
|
+
A chat-style dialog keeps a heading or notices above one scrolling transcript
|
|
98
|
+
and floats its composer over the body's block end. Two props compose it:
|
|
99
|
+
|
|
100
|
+
- `bodyLayout="fill-last"` stacks the body's children: the leading children
|
|
101
|
+
keep their natural height, and the last one takes the remaining height and
|
|
102
|
+
owns its scrolling (a `scrollable` `List` transcript). The body itself stops
|
|
103
|
+
scrolling. `PopoverDialogSurface` accepts the same layout.
|
|
104
|
+
- `footerPresentation="floating"` lays the footer over the body's block end,
|
|
105
|
+
`footerOffset` (a branded `CssLength`, default the 16px container inset)
|
|
106
|
+
from the panel's inline and block-end edges, on a transparent background.
|
|
107
|
+
The modal panel is its positioning context. The default `docked` footer
|
|
108
|
+
sits below the body as before.
|
|
109
|
+
|
|
110
|
+
The register measures the footer (it follows a composer that grows, wraps, or
|
|
111
|
+
hides) and the body reserves that height plus the offset after its own inset,
|
|
112
|
+
with a matching `scroll-padding`. Flowing body content scrolls beneath the
|
|
113
|
+
floating footer and its end stays reachable above it; with `fill` or
|
|
114
|
+
`fill-last` the filling child's scrollport ends at the footer's top. Content
|
|
115
|
+
is never hidden beneath the footer.
|
|
116
|
+
|
|
117
|
+
To let a filling transcript scroll visibly beneath the floating footer, opt
|
|
118
|
+
its scroller in with `scrollClearance="block-end"` (a `scrollable` `List`, or a
|
|
119
|
+
`Pane`, as the `fill` or last `fill-last` child). The body then stops
|
|
120
|
+
reserving the footer below that child, so the child reaches the panel's block
|
|
121
|
+
end, and publishes the footer's clearance (measured height plus offset) as the
|
|
122
|
+
inherited `--kui-scroll-clearance-block-end` context. The child adds it to its
|
|
123
|
+
own block-end padding and `scroll-padding`: messages pass beneath the
|
|
124
|
+
transparent footer mid-scroll, the last message rests above the composer at
|
|
125
|
+
the end, and focus or `scrollIntoView` never leaves an item hidden beneath it.
|
|
126
|
+
The context is general: chrome that overlays a region's block-start or
|
|
127
|
+
block-end edge publishes `--kui-scroll-clearance-block-start` / `-end`, and a
|
|
128
|
+
scroll owner opts in per edge (see `docs/layout.md` "Scroll clearance"). A
|
|
129
|
+
dialog body clears any clearance inherited from the page.
|
|
130
|
+
|
|
131
|
+
Choose the offset like any other responsive value: the scaffold adds no
|
|
132
|
+
breakpoint. An 8px offset lines a composer up with the transcript's
|
|
133
|
+
content-item edges when the body has `bodyInset="none"` and list geometry;
|
|
134
|
+
`viewportGutter` and `footerOffset` can follow `deviceClass()` when a phone
|
|
135
|
+
needs tighter edges. Put a [`Composer`](./composer.md) in the floating footer
|
|
136
|
+
with `footerInset="none"`: its raised frame and shadow lift it over the
|
|
137
|
+
transcript, and its field grows the measured footer. With `submitOnEnter` and
|
|
138
|
+
`wireComposers(root)`, Enter sends through the same action as the Send button.
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
<DialogSurface height={remify(560)} viewportGutter={remify(8)} bodyInset="none" bodyLayout="fill-last" footerPresentation="floating" footerOffset={remify(8)} footerInset="none">
|
|
142
|
+
<wa-dialog label="Assistant">
|
|
143
|
+
<StateBanner title="Answers use the latest nightly build." tone="neutral" />
|
|
144
|
+
<List gap="xs" controlInsets="tb" scrollable scrollClearance="block-end">
|
|
145
|
+
{messages.map((message) => (
|
|
146
|
+
<ContentItem bubble={message.mine ? 'end' : 'start'} appearance={message.mine ? 'brand-loud' : 'neutral'}>
|
|
147
|
+
<Text variant="span">{message.text}</Text>
|
|
148
|
+
</ContentItem>
|
|
149
|
+
))}
|
|
150
|
+
</List>
|
|
151
|
+
<Composer submitOnEnter slot="footer" id="assistant-message" name="message" label="Message" placeholder="Ask about this build" actions={<wa-button variant="brand" data-action="send-message">Send</wa-button>} />
|
|
152
|
+
</wa-dialog>
|
|
153
|
+
</DialogSurface>;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### A floating title bar
|
|
157
|
+
|
|
158
|
+
`headerPresentation="floating"` lays the dialog's header (its title and close
|
|
159
|
+
control) over the body's block-start edge on the translucent chrome material,
|
|
160
|
+
`--kui-chrome-material-raised` (the raised panel surface at 80% opacity)
|
|
161
|
+
behind `--kui-chrome-material-filter` (a blur and saturation backdrop filter).
|
|
162
|
+
Content passing beneath the title bar reads as softened color, not as
|
|
163
|
+
competing text. The default `docked` header sits above the body as before.
|
|
164
|
+
|
|
165
|
+
The register measures the header the same way it measures the footer (it
|
|
166
|
+
follows a title that wraps, text that grows, or a `without-header` toggle).
|
|
167
|
+
The body reserves the measured height before its own inset, with a matching
|
|
168
|
+
`scroll-padding`, so flowing content starts below the title bar and scrolls
|
|
169
|
+
beneath it. A dialog without the register has no measurement, so its header
|
|
170
|
+
stays docked rather than covering content.
|
|
171
|
+
|
|
172
|
+
To let a filling transcript scroll visibly beneath the title bar, make it the
|
|
173
|
+
body's only child (`bodyLayout="fill"`, or `fill-last` with no leading rows)
|
|
174
|
+
and opt its scroller in with block-start `scrollClearance`. The body then
|
|
175
|
+
stops reserving the header, so the child reaches the panel's block-start
|
|
176
|
+
edge, and publishes the header's height as `--kui-scroll-clearance-block-start`.
|
|
177
|
+
Leading `fill-last` rows (a notice above the transcript) keep the body's
|
|
178
|
+
reservation: they never sit beneath the title bar. Combined with a floating
|
|
179
|
+
composer and `scrollClearance="both"`, the transcript scrolls beneath both:
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
<DialogSurface height={remify(560)} viewportGutter={remify(8)} bodyInset="none" bodyLayout="fill" headerPresentation="floating" footerPresentation="floating" footerOffset={remify(8)} footerInset="none">
|
|
183
|
+
<wa-dialog label="Release Thread">
|
|
184
|
+
<ToolbarText slot="label" text="Release Thread" size="xlarge" description="Engineering · 5.2 candidate" />
|
|
185
|
+
<List gap="xs" controlInsets="tb" scrollable scrollClearance="both">
|
|
186
|
+
{bubbles}
|
|
187
|
+
</List>
|
|
188
|
+
<Composer submitOnEnter slot="footer" id="thread-message" name="message" label="Message" placeholder="Reply to the thread" actions={<wa-button variant="brand" data-action="send-message">Send</wa-button>} />
|
|
189
|
+
</wa-dialog>
|
|
190
|
+
</DialogSurface>;
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Like a `Pane`'s overlay header, the title bar draws its divider as scroll
|
|
194
|
+
state: a 1px line along its bottom edge only while the body, or a filling
|
|
195
|
+
child that reaches beneath it, is scrolled away from its top, and none at
|
|
196
|
+
rest. The register follows those scrollers (a nested scroller that starts
|
|
197
|
+
below the title bar never counts), and the line is an inset shadow, so it
|
|
198
|
+
never moves the header or the content.
|
|
199
|
+
|
|
200
|
+
The material turns opaque under `prefers-reduced-transparency: reduce` or
|
|
201
|
+
`prefers-contrast: more`, and where the browser lacks `backdrop-filter`; in
|
|
202
|
+
forced colors the header paints `Canvas` with a `CanvasText` bottom edge.
|
|
203
|
+
|
|
204
|
+
For a title with a short supporting line, slot a `ToolbarText` as the label
|
|
205
|
+
(`<ToolbarText slot="label" text="Release Thread" size="xlarge" description="Engineering · 5.2 candidate" />`).
|
|
206
|
+
On the floating title bar an untoned `ToolbarText` keeps AA by itself: its
|
|
207
|
+
title takes the normal text color and its description lifts halfway toward
|
|
208
|
+
it. Any other quiet copy you place there can fall below AA over the content
|
|
209
|
+
passing beneath it, so keep it in the body (see
|
|
210
|
+
[Accessibility › Chrome material](accessibility.md#chrome-material)).
|
|
211
|
+
|
|
95
212
|
Treat a dialog body as a `List` by default. When its rows or sections own their
|
|
96
213
|
standard list geometry, set `bodyInset="none"` so the dialog does not add a
|
|
97
214
|
second inset. Bare prose is still a list child: wrap it in `ListInsetText` so its
|
|
@@ -109,8 +226,22 @@ hand-built popover with application chrome CSS. It is a native
|
|
|
109
226
|
`popover="auto"` section with `role="dialog"` that owns Kerf's dialog chrome
|
|
110
227
|
(raised surface, border, large radius and shadow, and a backdrop) and the
|
|
111
228
|
same geometry props as a modal `DialogSurface`: `size`, `preferredWidth`,
|
|
112
|
-
`viewportGutter` (16px by default), `height` / `maxHeight`, and `bodyLayout
|
|
113
|
-
|
|
229
|
+
`viewportGutter` (16px by default), `height` / `maxHeight`, and `bodyLayout`
|
|
230
|
+
(`flow`, `fill`, or `fill-last`).
|
|
231
|
+
Name it with `label` or `labelledBy`. To give it an accessible description,
|
|
232
|
+
pass `describedBy`, the id of the element that holds the summary. It renders as
|
|
233
|
+
`aria-describedby` on the `role="dialog"` root and usually names a title
|
|
234
|
+
`ToolbarText`'s `descriptionId`:
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
<PopoverDialogSurface id="connection-details" labelledBy="connection-title" describedBy="connection-summary" bodyLayout="fill-last">
|
|
238
|
+
<Toolbar label="Connection Details Heading" leading={<ToolbarText text="Connection Details" size="xlarge" id="connection-title" description="Connected to the build server." descriptionId="connection-summary" />} />
|
|
239
|
+
{details}
|
|
240
|
+
</PopoverDialogSurface>;
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`DialogSurface` has no `describedBy`. It wraps a `wa-dialog` that the app
|
|
244
|
+
authors, so the app names and describes that dialog on its own markup.
|
|
114
245
|
|
|
115
246
|
Open it with a control's `popoverTarget` (or `showPopover()`); the browser
|
|
116
247
|
places it centered in the top layer, light-dismisses it, and restores nothing
|
|
@@ -121,8 +252,8 @@ layer and never wider than its container, for a catalog specimen or an inline
|
|
|
121
252
|
preview.
|
|
122
253
|
|
|
123
254
|
```tsx
|
|
124
|
-
<button type="button" popoverTarget="repository-status">Repository
|
|
125
|
-
<PopoverDialogSurface id="repository-status" label="Repository
|
|
255
|
+
<button type="button" popoverTarget="repository-status">Repository Status</button>
|
|
256
|
+
<PopoverDialogSurface id="repository-status" label="Repository Status" preferredWidth={remify(1024)} height={remify(640)} viewportGutter={remify(8)} bodyLayout="fill">
|
|
126
257
|
<SplitView id="repo-split" label="Changes" list={list} detail={detail} />
|
|
127
258
|
</PopoverDialogSurface>;
|
|
128
259
|
```
|
|
@@ -136,4 +267,4 @@ preserve `data-morph-skip-children` when its upgraded light-DOM items must retai
|
|
|
136
267
|
identity across Kerf rerenders. Import `@kerfjs/ui/popup-menu/register` once for
|
|
137
268
|
the focus handoff fix when wrapping a raw `wa-dropdown`.
|
|
138
269
|
|
|
139
|
-
Import `@kerfjs/ui/surface-scaffold/register` once when using `DialogSurface`: it registers `wa-dialog
|
|
270
|
+
Import `@kerfjs/ui/surface-scaffold/register` once when using `DialogSurface`: it registers `wa-dialog`, measures each surface's footer for a floating footer's body clearance, draws a floating header's divider while content is scrolled beneath it, 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.
|
package/docs/tab-navigator.md
CHANGED
|
@@ -136,7 +136,7 @@ The app owns each stack's view array and the navigator's active tab. Call
|
|
|
136
136
|
`wireTabNavigator` for tab selection and `wireNavStack` for back navigation
|
|
137
137
|
and transitions, each on its own component root. Push a detail by appending
|
|
138
138
|
a view with its own `toolbar` and `pane`; switching tabs keeps that view
|
|
139
|
-
mounted. The catalog's **NavStack
|
|
139
|
+
mounted. The catalog's **NavStack Inside a Tab** example demonstrates the
|
|
140
140
|
push, tab switch, and return flow.
|
|
141
141
|
|
|
142
142
|
Set a tab's `appearance: "sunken"` when its scene owns scrolling and should
|
|
@@ -169,6 +169,43 @@ so it never moves the bar or a tab.
|
|
|
169
169
|
the wiring reports content below. It does not suppress the sunken-surface
|
|
170
170
|
separator; use `separator="hidden"` for that.
|
|
171
171
|
|
|
172
|
+
## Translucent bar
|
|
173
|
+
|
|
174
|
+
`barPresentation="overlay"` lays the tab bar over the active scene's bottom
|
|
175
|
+
edge on the translucent chrome material (`--kui-chrome-material` behind
|
|
176
|
+
`--kui-chrome-material-filter`), so the scene's content scrolls visibly beneath
|
|
177
|
+
it, as under an iOS tab bar. The default, `docked`, gives the bar its own band.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
<TabNavigator
|
|
181
|
+
id="mail"
|
|
182
|
+
label="Mail Sections"
|
|
183
|
+
barPresentation="overlay"
|
|
184
|
+
active={active.value}
|
|
185
|
+
tabs={tabs}
|
|
186
|
+
/>;
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
`wireTabNavigator` measures the live bar's border box (bottom safe area and its
|
|
190
|
+
1px top edge included), publishes it on the root, and marks the root
|
|
191
|
+
`data-bar-overlay="measured"`. The scenes then hand that height to their
|
|
192
|
+
content as the block-end `--kui-edge-inset-*` context: a plain scene pads and
|
|
193
|
+
scroll-pads by it, and a sole `Pane` or `NavStack` clears it itself, so the
|
|
194
|
+
last item, and anything focused or scrolled into view, rests just above the
|
|
195
|
+
bar. A `NavStack` with its own bottom toolbar pads that toolbar for the bar as
|
|
196
|
+
it would for a bottom safe area: the toolbar's controls sit just above the tab
|
|
197
|
+
bar while its material runs on beneath it. Until the wiring runs, the bar stays
|
|
198
|
+
docked.
|
|
199
|
+
|
|
200
|
+
Over the material, unselected labels lift halfway toward the normal text color
|
|
201
|
+
and the selected label mixes 40% of it into the brand color, so both keep AA
|
|
202
|
+
over any content beneath. The material turns opaque under reduced
|
|
203
|
+
transparency, increased contrast, or without `backdrop-filter`, and paints
|
|
204
|
+
`Canvas` with a `CanvasText` top edge in forced colors. The scroll divider still
|
|
205
|
+
shows only while more content lies below. Like the NavStack overlay bars, the
|
|
206
|
+
tab bar ends where a classic (space-taking) scrollbar's track begins, so the
|
|
207
|
+
active scene's thumb and buttons stay visible and usable.
|
|
208
|
+
|
|
172
209
|
## Tab badges
|
|
173
210
|
|
|
174
211
|
Give a tab a `badge` (a count or short string such as `3`, `"99+"`, or
|
package/docs/type-contracts.md
CHANGED
|
@@ -11,22 +11,22 @@ public-signature artifact.
|
|
|
11
11
|
|
|
12
12
|
## Strengthened contracts
|
|
13
13
|
|
|
14
|
-
| ID | Compile-time guarantee
|
|
15
|
-
| ---------- |
|
|
16
|
-
| `KUI-T001` | `ListHeader` is a passive heading, a fully named/icon-bearing trailing action, or a controlled disclosure with `action` + `expanded`. Props ignored by the selected mode are rejected.
|
|
17
|
-
| `KUI-T002` | `Select` has a visible `label` or an `ariaLabel`.
|
|
18
|
-
| `KUI-T003` | A literal `Select.value` belongs to its literal `choices`.
|
|
19
|
-
| `KUI-T004` | A literal `SegmentedControl.value` belongs to its literal `choices`.
|
|
20
|
-
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `TokenSearchField({ collapsible: true })`.
|
|
21
|
-
| `KUI-T006` | `TokenSearchEditorAttributes` accepts application `data-*` metadata but rejects component-owned identity, morph, count, and placeholder attributes.
|
|
22
|
-
| `KUI-T007` | `ToolbarText.maxLines` requires `wrap: true`; it is never silently ignored in typed code.
|
|
23
|
-
| `KUI-T008` | A literal `TabNavigator.active` id belongs to its literal `tabs`.
|
|
24
|
-
| `KUI-T009` | Adjacent-token keyboard removal requires `onRemoveToken`; disabling removal rejects the now-meaningless callback.
|
|
25
|
-
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all AppTab, TabBar, ToolbarControlGroup, and Select presentation axes; the convenience root barrel re-exports them.
|
|
26
|
-
| `KUI-T011` | Semantic component zones use the recursive `KerfUiContent` type: `SafeHtml`, runtime-empty booleans/nullish values, and readonly nested arrays are valid; arbitrary strings, numbers, and signals are rejected. Explicit text positions such as `ListInsetText` retain their text exception.
|
|
27
|
-
| `KUI-T012` | `List.gap` accepts finite `UiSpaceName` shorthands or a complete branded `CssLength`; raw strings and non-standalone `CssLengthExpression` arithmetic are rejected. `calc(plus(...))` promotes a typed expression to a complete value.
|
|
28
|
-
| `KUI-T013` | CSS-valued props preserve property grammar: `List.flex` uses `CssFlex`, `Skeleton` dimensions use `CssSize`/`CssLength`, and choice icons and `LucideIcon.color` use `CssForegroundColor` (foreground tokens via `uiColor()`, `foregroundColorVar()`, or custom values via `foregroundColor()`; fill tokens such as `uiColor('success-fill-quiet')` are rejected); row declaration strings are absent. |
|
|
29
|
-
| `KUI-T014` | Stable single-root visual components accept the explicit native `slot` attribute. Multi-root `ResizableRegion` and `CollapsiblePanel` remain excluded because no single returned element can own the assignment, and other arbitrary native attributes remain rejected.
|
|
14
|
+
| ID | Compile-time guarantee |
|
|
15
|
+
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `KUI-T001` | `ListHeader` is a passive heading, a fully named/icon-bearing trailing action, or a controlled disclosure with `action` + `expanded`. Props ignored by the selected mode are rejected. |
|
|
17
|
+
| `KUI-T002` | `Select` has a visible `label` or an `ariaLabel`. |
|
|
18
|
+
| `KUI-T003` | A literal `Select.value` belongs to its literal `choices`. |
|
|
19
|
+
| `KUI-T004` | A literal `SegmentedControl.value` belongs to its literal `choices`. |
|
|
20
|
+
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `TokenSearchField({ collapsible: true })`. |
|
|
21
|
+
| `KUI-T006` | `TokenSearchEditorAttributes` accepts application `data-*` metadata but rejects component-owned identity, morph, count, and placeholder attributes. |
|
|
22
|
+
| `KUI-T007` | `ToolbarText.maxLines` requires `wrap: true`; it is never silently ignored in typed code. |
|
|
23
|
+
| `KUI-T008` | A literal `TabNavigator.active` id belongs to its literal `tabs`. |
|
|
24
|
+
| `KUI-T009` | Adjacent-token keyboard removal requires `onRemoveToken`; disabling removal rejects the now-meaningless callback. |
|
|
25
|
+
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all AppTab, TabBar, ToolbarControlGroup, and Select presentation axes; the convenience root barrel re-exports them. |
|
|
26
|
+
| `KUI-T011` | Semantic component zones use the recursive `KerfUiContent` type: `SafeHtml`, runtime-empty booleans/nullish values, and readonly nested arrays are valid; arbitrary strings, numbers, and signals are rejected. Explicit text positions such as `ListInsetText` retain their text exception. |
|
|
27
|
+
| `KUI-T012` | `List.gap` accepts finite `UiSpaceName` shorthands or a complete branded `CssLength`; raw strings and non-standalone `CssLengthExpression` arithmetic are rejected. `calc(plus(...))` promotes a typed expression to a complete value. |
|
|
28
|
+
| `KUI-T013` | CSS-valued props preserve property grammar: `List.flex` uses `CssFlex`, `Skeleton` dimensions use `CssSize`/`CssLength`, and choice icons and `LucideIcon.color` use `CssForegroundColor` (foreground tokens via `uiColor()`, `foregroundColorVar()`, or custom values via `foregroundColor()`; fill tokens such as `uiColor('success-fill-quiet')` are rejected); a row `iconTile` is a finite tone or a `CssColor` fill (custom values via `fillColor()`) with an optional `CssForegroundColor` glyph, and a `ChoiceChips` swatch is a `CssColor` fill (`fillColor()`, `uiColor()`, `colorVar()`) or `'transparent'`; a `fillColor()` value is a plain `CssColor` and is rejected where a `CssForegroundColor` is required; row declaration strings are absent. |
|
|
29
|
+
| `KUI-T014` | Stable single-root visual components accept the explicit native `slot` attribute. Multi-root `ResizableRegion` and `CollapsiblePanel` remain excluded because no single returned element can own the assignment, and other arbitrary native attributes remain rejected. |
|
|
30
30
|
|
|
31
31
|
`KerfUiContent` lets conditionals and mapped component collections be direct
|
|
32
32
|
siblings without an otherwise-unnecessary `Fragment`:
|
package/docs/ui-analyzer.md
CHANGED
|
@@ -110,7 +110,9 @@ Catalog entries may also publish `cssValueProps`. Each path names its grammar,
|
|
|
110
110
|
finite shorthands, canonical and exceptional scale steps, accepted typed
|
|
111
111
|
helpers, expression-only helpers, raw escape policy, and examples. The analyzer
|
|
112
112
|
uses that same metadata for direct component calls and JSX, including nested
|
|
113
|
-
paths such as `choices[].color
|
|
113
|
+
paths such as `choices[].color` (each array item's member) and
|
|
114
|
+
`iconTile.color` (an object-valued prop's member, skipped when the prop is a
|
|
115
|
+
tone string); consumer catalogs receive identical checks.
|
|
114
116
|
Dynamic values remain a type-system responsibility rather than being guessed.
|
|
115
117
|
|
|
116
118
|
## Component ownership (`KUI-L019`–`KUI-L023`)
|
package/docs/ui-doctor.md
CHANGED
|
@@ -139,6 +139,77 @@ The browser evaluator is different: it runs the application and is disabled by d
|
|
|
139
139
|
|
|
140
140
|
An unavailable or failed stage does not prevent independent stages from reporting. Its final exit is still a configuration failure, so a partial run cannot appear clean.
|
|
141
141
|
|
|
142
|
+
## Interface copy capitalization
|
|
143
|
+
|
|
144
|
+
The analyzer stage also checks visible label copy against the package
|
|
145
|
+
capitalization rule in [Writing interface copy](./writing.md#capitalization).
|
|
146
|
+
Names of commands, controls, views, and fields use title style, following
|
|
147
|
+
Apple's guidance. `KUI-D040` (warning) reports a string or template literal
|
|
148
|
+
passed to a known title-style prop that leaves a word lowercase where title style
|
|
149
|
+
capitalizes it. For example, `<wa-button>Save draft</wa-button>` should be
|
|
150
|
+
"Save Draft", and `<ListHeader label="Needs attention" />` should be "Needs
|
|
151
|
+
Attention". The action names the repaired label.
|
|
152
|
+
|
|
153
|
+
The check reads `.tsx` and `.jsx` source text only and skips test modules.
|
|
154
|
+
Fixture components that tests render (for example
|
|
155
|
+
`tests/browser/fixtures/*.tsx`) are not test modules and are checked: they
|
|
156
|
+
stand in for application screens, so their copy follows the same rule. It
|
|
157
|
+
covers these string literals:
|
|
158
|
+
|
|
159
|
+
- `ToolbarText` titles: text with `headingLevel`, a large size, or in a
|
|
160
|
+
toolbar or panel `title`, `header`, or (unless small) `leading` slot;
|
|
161
|
+
- `ListHeader`, `ListActionRow`, `SplitButton`, and `Combobox` labels;
|
|
162
|
+
- `CatalogExample` and `CatalogExampleStack` labels, which render as a
|
|
163
|
+
`ListHeader` heading (their `note` stays sentence style and is not read);
|
|
164
|
+
- `EmptyState` and `StateBanner` titles;
|
|
165
|
+
- `PopupMenu` trigger text and item and heading labels, including submenus
|
|
166
|
+
declared in the same file;
|
|
167
|
+
- `SegmentedControl`, `Select`, and `TabNavigator` choice and tab labels;
|
|
168
|
+
- `NavStack` view titles and `backText`, and `SplitView` `backLabel`;
|
|
169
|
+
- `FieldLabel` text and the static text of a `button` or `wa-button`;
|
|
170
|
+
- the `name` of a panel toolbar's `toggle: { action, name }` object literal
|
|
171
|
+
(Workbench panels, `CollapsiblePanel`), which names the toggle group and
|
|
172
|
+
completes its "Show …" / "Hide …" label;
|
|
173
|
+
- region and landmark names: the `label` of `Pane`, `Workbench`, `Toolbar`,
|
|
174
|
+
`ToolbarControlGroup`, `TabBar`, `NavStack`, `CollapsiblePanel`,
|
|
175
|
+
`FloatingToolbar`, and `ResizableRegion`; the `ariaLabel` of `SunkenPanel`
|
|
176
|
+
and `List`; a `Pane`'s `contentLabel`; the panel, toolbar, and pane labels
|
|
177
|
+
in `Workbench` (`leftRail`, `rightRail`, `bottomDrawer`, `mainToolbar`,
|
|
178
|
+
`mainBottomToolbar`, `mainPane`), `CollapsiblePanel` (`toolbar`,
|
|
179
|
+
`bottomToolbar`, `pane`), and `NavStack` (`views`, `bottomToolbar`)
|
|
180
|
+
configuration declared in the same file; and the `aria-label` of a
|
|
181
|
+
`section`, `nav`, `aside`, `main`, `header`, `footer`, `form`, or `search`
|
|
182
|
+
element or an element with a landmark `role`;
|
|
183
|
+
- the `label` of a raw `wa-input`, `wa-select`, `wa-textarea`, or
|
|
184
|
+
`wa-radio-group`, which is a field or group label;
|
|
185
|
+
- the accessible names of icon-only controls, which the rule also gives title
|
|
186
|
+
style: `IconButton` and `IconToggleButton` `label`, `PopupMenu` `label`,
|
|
187
|
+
`SplitButton` `optionsLabel`, `TokenSearchField` `clearLabel`, and the
|
|
188
|
+
`aria-label` of a `button` or `wa-button` whose only content is an icon. A
|
|
189
|
+
button with visible text is judged by that text, never by its `aria-label`.
|
|
190
|
+
|
|
191
|
+
The check is deliberately one-directional, to keep false positives rare:
|
|
192
|
+
|
|
193
|
+
- It reports only lowercase words. It never reports a capitalized short word,
|
|
194
|
+
because Apple capitalizes a phrasal verb's particle ("Log In to the
|
|
195
|
+
Server").
|
|
196
|
+
- It leaves text ending in `.`, `!`, or `?` to sentence style.
|
|
197
|
+
- It judges only a template literal's static words, so
|
|
198
|
+
`` `Edit ${name} shortcut` `` is reported and the interpolated value never
|
|
199
|
+
is. A word joined to an interpolation (`` `${count}s` ``) is skipped.
|
|
200
|
+
- It ignores other dynamic values and every sentence-style surface: descriptions,
|
|
201
|
+
details, placeholders, tooltips, status text, and option text, including
|
|
202
|
+
`wa-checkbox`, `wa-switch`, and `wa-radio` labels. It does not read
|
|
203
|
+
`LoadingSpinner` or `Skeleton` labels, which announce a status.
|
|
204
|
+
- It skips tokens containing digits, code, paths, or URLs, and lowercase-led
|
|
205
|
+
brands such as iOS and macOS.
|
|
206
|
+
- It keeps a minor word inside a longer hyphenated compound lowercase, as
|
|
207
|
+
between separate words ("Edge-to-Edge", "Up-to-Date").
|
|
208
|
+
- It does not read `ContentItem` `title`, which is a native tooltip.
|
|
209
|
+
|
|
210
|
+
Suppress `KUI-D040` for a file whose copy is a lowercase brand or product
|
|
211
|
+
name.
|
|
212
|
+
|
|
142
213
|
## Full and changed modes
|
|
143
214
|
|
|
144
215
|
`--full` is the default and analyzes the selected package. `--changed` reads tracked and untracked paths from Git unless one or more `--path` values are supplied. An empty changed set is a configuration error instead of a false-clean success. With `--package`, workspace-relative Git paths are converted to package-relative paths before TypeScript, ESLint, and analyzer selection; paths outside the selected package are ignored.
|
package/docs/ux-demo.md
CHANGED
|
@@ -21,13 +21,13 @@ Each `?component=recipe-*` route uses public package primitives, real wiring,
|
|
|
21
21
|
deterministic state, and semantic layout owners from the [recipe guide](./recipes.md).
|
|
22
22
|
|
|
23
23
|
- It imports public component subpaths, exercising their browser-selected reachable CSS rather than a catalog-only style path.
|
|
24
|
-
- The `ListActionRow` route's Run
|
|
24
|
+
- The `ListActionRow` route's Run Tests row composes a trailing `PopupMenu` (`trailingMenu`) with Edit and Delete commands, revealed on interaction, that also opens at the pointer when the row's primary button is right-clicked.
|
|
25
25
|
- The `ListActionRow` route demonstrates sibling primary/trailing native controls, independent disabled states, controlled selection, first-line leading-icon alignment for wrapped labels, and an application-owned native popover relationship without nesting controls. The `ListItem` route demonstrates the same multiline leading-icon anchor alongside its single-control navigation contract.
|
|
26
|
-
- The `PopupMenu` route's context example opens one app-owned menu either at the row's right-click point or below its adjacent, keyboard-operable Demand
|
|
26
|
+
- The `PopupMenu` route's context example opens one app-owned menu either at the row's right-click point or below its adjacent, keyboard-operable Demand Actions button. The Nested Decisions example shows the automatic phone-width submenu placement above or below its parent list, with native ArrowLeft return, Escape dismissal, and child selection.
|
|
27
27
|
- The `AppTab` and `TabBar` routes are focused component specimens: AppTab shows its selected, compact, segmented, icon-only, truncation, placeholder, pending, metadata, and close-icon axes inside the required tablist context; TabBar shows its rail, segmented, inspector, allocation, placement, and accessory-zone axes, including an adjacent action plus a separately pinned end action whose tabs overflow at narrow widths, without application readouts. The pinned leading-tab specimen uses native strip scrolling so momentum and the final tab's end position remain natural; `snapTabs` stays an opt-in for applications that want whole-tab settling. The separate `Application tabs` composition route demonstrates controlled selection, matching panel content, overflow, adding (a new tab opens `pending` with a spinner and stays selectable while its panel shows a `Skeleton` heading until a simulated load completes), closing, keyboard/pointer reordering, and application-owned ordering. The `ResizableRegion` route likewise replaces only the decorative handle glyph while retaining separator semantics and shared wiring.
|
|
28
28
|
- Every first-party visual component and every free Web Awesome 3.12 component has its own stable `?component=<id>` URL and focused demo. Composite header, menu, and feedback scenarios remain addressable alongside their subcomponents; the root opens the first Kerf component. The former aggregate Web Awesome theme specimen is intentionally omitted because its component families are covered by those focused routes.
|
|
29
29
|
- `ai/component-catalog.json` is the canonical catalog metadata. A deterministic checked-in projection supplies the demo's unique id, category, kind (`component`, `composition`, or `recipe`), source (`kerf` or `webawesome`), name, description, recommendation, direct `uses` dependencies, existing documentation path, and demo-source path; first-party, recipe, and Web Awesome renderer maps are exhaustively typed against its generated id unions. Functional groups follow their authored importance order; components precede compositions inside each group, equal-importance entries use alphabetical order, and the Recipes group comes last. Composition names stay concise and project a visible `Composition` sidebar tag. Non-supported Web Awesome recommendations project to a visible `Discouraged` tag, with Popup as the deliberate conditional exception. Demo paths resolve to the matching `ui/ux-demo/demos/<id>.tsx` or `ui/ux-demo/recipes/*.tsx` file, or to `ui/ux-demo/webawesome-demos.tsx` for Web Awesome entries. `ui/ux-demo/main.tsx` owns only the catalog shell, shared state, routing, and interaction wiring. First-party component entries additionally derive `ui/src/<public-subpath>.tsx` from their canonical `delivery.browserImport` or opt-in `delivery.moduleImport`.
|
|
30
|
-
- Every detail footer groups compact `Demo
|
|
30
|
+
- Every detail footer groups compact `Demo Source` and `Guidance` actions; first-party component details also expose `Component Source`. Web Awesome details say `Integration Guidance` to distinguish the local integration contract from the upstream component implementation. Each button retains its repository-relative path in the DOM for verification and uses a deploy-safe absolute GitHub blob URL with a contextual new-tab name; the demo does not depend on a local source server or add a package runtime export. At phone widths, the resource group and related-component selector stack as full-width rows, with any resource overflow contained locally so labels cannot overlap the selector or widen the document.
|
|
31
31
|
- The master/detail shell groups first-party routes by category with production `ListHeader` and `ListItem` components. Catalog entries can supply short reusable trailing tags; the Web Awesome projection uses them to label exactly the 15 discouraged choices. The 70 ecosystem components live in a separate `Web Awesome` disclosure with seven subgroups, so they remain discoverable without being presented as first-class `@kerfjs/ui` exports. Direct Web Awesome routes open the disclosure and reveal the selected row at wide sizes; narrow layouts keep the expanded list in document flow rather than introducing a competing nested scroller.
|
|
32
32
|
- The shell itself uses `@kerfjs/ui/layout.css`: sidebars, details, previews, dialogs, and resize specimens share unpadded panes plus self-contained content items. Its sidebar identity uses the Kerf logo beside a vertically centered title, with supporting copy in its own aligned row; the current-view heading is also a toolbar. The shared Catalog sidebar includes a filter for entry and heading names that works across first-party and ecosystem sections, including collapsed sections. Collapsing the catalog removes the pane completely and moves its restore action to the main toolbar's leading edge instead of leaving an icon-only rail. The selected view description remains inset below the page toolbar. The preview stage sits directly in the sunken main Pane, with its canvas padded by the medium spacing token. The stage fills the preview scroller for short specimens and grows with taller ones; every background choice follows that same shared behavior in this demo and in consumers. The checkerboard belongs to that stage, rather than a viewport-height wrapper or nested card, and one explicitly repeated SVG tile keeps the pattern continuous through below-fold content. A lightly separated footer keeps live status above compact source, guidance, and relationship groups. The focused `ResizableRegion` specimen stretches its surface through the available stage height and reports committed width in that shared status footer; narrow layouts retain local horizontal access when the pane is resized wider than the stage, and the split remains readable at 200% root scaling. Geometry coverage checks wide, intermediate, narrow, and 200% zoom layouts.
|
|
33
33
|
- The composer-form recipe demonstrates one coherent visible form surface with toolbar title/supporting-copy hierarchy, fields and actions on the shared 8px control gutter, and 24px major rhythm. Its conditional error or success `StateBanner` is the only nested semantic surface. Reset synchronizes the upgraded Web Awesome fields' live value properties with their empty controlled attributes and announces `Draft reset`; browser coverage preserves behavior and verifies wide, narrow, dark, validation, success, reset, 200% zoom, and forced-colors states.
|
|
@@ -35,7 +35,7 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
35
35
|
- Catalog-only brand marks, preview dimensions, checkerboard tiles, and the compound display-settings control retain local geometry because they are specimen chrome or intrinsic control anatomy rather than reusable application spacing roles.
|
|
36
36
|
- The menu composition route demonstrates toolbar/content/footer anatomy, 24px major gaps, 8/1/8 child geometry, the full-width `ListHeader` count-or-badge/action split, logical-end 44px action targets with 18px visuals, and 44px row/header/toolbar targets. Its one chevron is a production 18px `DisclosureArrow` inside a controlled Tools header that actually reveals and hides content; ordinary Projects navigation has no false disclosure affordance. Browser assertions cover stable naming, expanded/content transitions, visual rotation, node identity, reduced motion, RTL alignment and containment, and wide, narrow, dark, and 200% layouts. The focused ListHeader route separately shows the shared neutral count pill for Attachments, Notes (including zero), and Duplicates plus a non-count legacy badge, full-width logical-end actions, and no disclosure without content.
|
|
37
37
|
- The `DisclosureArrow` route renders the production 18px root-scaled default without a catalog-only size override. Its two native buttons independently control the default right-to-down chevron and a recognizable right-facing replacement arrow with left-to-up custom directions; both use shortest-path rotation and their names stay stable while `aria-expanded` communicates state. Browser coverage verifies the custom clockwise path, pointer and native keyboard activation, focus, narrow and 200%-zoom stacking with contained labels, consumer sizing, and the independent `.5` Web Awesome glyph scale retained by Kerf `Select`.
|
|
38
|
-
- A detail with relationships renders one content-fitted `Components` footer selector: `Uses` links to direct dependencies and `Used
|
|
38
|
+
- A detail with relationships renders one content-fitted `Components` footer selector: `Uses` links to direct dependencies and `Used By` links to reverse dependents. Its popup owns the standard surface inset so headings and even long component names stay clear of the menu border. Choosing either navigates to that component's demo. The relationship group is absent when both sets are empty; no duplicate summary is rendered.
|
|
39
39
|
- Focused demos ship no local stylesheets, inline styles, or styling-only class names. They compose Kerf components first, Web Awesome surfaces where Kerf has no equivalent, and ordinary semantic HTML for the remainder. The catalog-owned `CatalogExample.viewport` contract supplies the few specimen constraints needed to demonstrate layout behavior. Recipes follow the same rule: they ship no stylesheets, inline styles, or styling-only classes, and the catalog frames each one in the `CatalogExample` viewport its exported `presentation` declares (full-width application arrangements span the canvas measure; narrower recipes sit in the left-aligned example column). Demo-only CSS is limited to the document-shell `style.css`, which carries no recipe rules. Decorative chrome and Web Awesome controls share the same semantic system palette instead of carrying a separate demo identity.
|
|
40
40
|
- Scenarios use deterministic data and cover real variants, long content, disabled state, selection, progress, feedback, overlays, media, helpers, and stateful interactions. Individual Web Awesome action, form, layout, navigation, feedback, media, and helper routes provide focused theme specimens without a redundant aggregate route; ListItem and ListHeader demonstrate typed domain metadata, protected native button/disclosure semantics, and a native popover trigger relationship without product props; the Headers composition demonstrates direct toolbar headings with an extra-large title, optional supporting copy, and grouped icon/actions; the Select route verifies that option icons survive unrelated Kerf rerenders and selected slot content follows value changes; the Animation route exposes preset, easing, duration, playback-rate, and transport controls with live lifecycle status; observer routes provide user-driven intersection, mutation, and resize events with live results; ToolbarControlGroup exposes all eight Hot Sheet 2 variants, loads the Web Awesome registrations needed by its popup specimen, and preserves the upgraded dropdown's managed light-DOM children across Kerf rerenders; the Toolbar route composes a collapsible TokenSearchField inside a group, animates between the empty iconic and complete field states, stays open while populated, and focuses the revealed editor; SegmentedControl covers toolbar, rounded-rectangle, pill, equal-width, and disabled presentations; TokenSearchField covers editable ordered chips, pointer and keyboard removal, caret-preserving controlled deletion, editing, clearing, free text, disabled state, and fixed first-line alignment while content wraps; StateBanner exposes every built-in tone with tone-tinted badges, a scoped override, and a placeholder with and without a badge, the badged placeholder in every tone so captures cover the solid badge skeleton; the Application tabs composition uses a Web Awesome card with semantic header/footer slots and Kerf `Text` while demonstrating overflow, edge autoscroll, and controlled pointer/keyboard reordering.
|
|
41
41
|
- The ToolbarControlGroup route also demonstrates the public compact/tight,
|
|
@@ -53,11 +53,11 @@ deterministic state, and semantic layout owners from the [recipe guide](./recipe
|
|
|
53
53
|
- The footer action log is an `aria-live` region, making interactions visible to both people and browser tests.
|
|
54
54
|
- The focused Toast route calls Web Awesome's documented programmatic stack API and notes that Hot Sheet 2 still uses its own app-level toast implementation; the catalog demonstrates ecosystem support without implying current product adoption.
|
|
55
55
|
- Browser coverage walks every Kerf, composition, and Web Awesome route, checks every listed Web Awesome custom element is registered in its focused specimen, exercises the ecosystem disclosure and both relationship directions, validates offline source/guidance hrefs and accessible wide/narrow/200%-zoom wrapping, and covers tab selection/reordering/overflow, semantic palettes and scoped overrides, light/dark rendering, toolbar popup and responsive find behavior, single/multiline search alignment, menu alignment, banner urgency, keyboard resizing, live custom-element values, and representative wide/narrow captures.
|
|
56
|
-
- The production build
|
|
56
|
+
- The production build splits the code loaded at startup into three eagerly preloaded chunks behind a tiny entry, so none nears the largest-chunk limit in `demo-bundle-budget.json`: `vendor` (the Web Awesome select and popup-menu registrations with their Lit and Floating UI runtime), `kerf` (the built `@kerfjs/ui` modules and the kerf core, plus every startup stylesheet), and `catalog` (the catalog shell and per-component demo modules). A chunk carries the CSS its modules import, so all startup CSS modules share the `kerf` chunk: the stylesheet stays one file with the cascade order a single-chunk build emits, and the chunk graph stays acyclic (`catalog` imports `kerf`, never the reverse). Only modules statically reachable from the entry qualify, so lazy-only dependencies stay in their lazy chunks. It then dynamically imports the complete Web Awesome specimen and registration surface when an ecosystem route or the ToolbarControlGroup popup specimen is selected. Directly addressed routes pass through the same loader.
|
|
57
57
|
|
|
58
58
|
The focused ListHeader route shows `xs`, `sm`, `m`, `l`, and `xl` labels at one
|
|
59
59
|
semantic heading level. Its default `sm` style still matches `FieldLabel`.
|
|
60
60
|
It also shows simultaneous badge and status indicators, with a conditional
|
|
61
61
|
badge expression that may return `undefined`.
|
|
62
62
|
|
|
63
|
-
Before handoff, inspect the actual captures for readability, context, alignment, clipping, spacing, responsiveness, focus, and obvious defects. Fix and recapture rather than treating the screenshot as proof by itself.
|
|
63
|
+
Before handoff, inspect the actual captures for readability, context, alignment, clipping, spacing, responsiveness, focus, and obvious defects. Fix and recapture rather than treating the screenshot as proof by itself. Firefox and WebKit screenshots leave out `backdrop-filter`, so translucent chrome looks unblurred in them. Check the blur on a `recordVideo` frame instead (see [Accessibility › Chrome material](accessibility.md#chrome-material)).
|
package/docs/webawesome-theme.md
CHANGED
|
@@ -190,6 +190,13 @@ a panel, and a Web Awesome card containing details, using public components and
|
|
|
190
190
|
no demo stylesheet. Browser tests cover repeated layers, actual compositing,
|
|
191
191
|
text contrast, light/dark switching, narrow/wide layouts, and forced colors.
|
|
192
192
|
|
|
193
|
+
The built-in close control of a `wa-dialog` or `wa-drawer` matches a borderless
|
|
194
|
+
single `ToolbarControlGroup` button, the close a toolbar-composed dialog uses
|
|
195
|
+
(see the list-detail dialog recipe): a 40px circle with no border and the
|
|
196
|
+
neutral hover fill, in place of Web Awesome's 35px rounded square. The theme
|
|
197
|
+
sizes it through the directly exported `close-button__base` part, so the
|
|
198
|
+
default header and a toolbar-composed header present one close affordance.
|
|
199
|
+
|
|
193
200
|
Add `class="hide-actions"` to a `wa-dialog` when the dialog supplies its own
|
|
194
201
|
dismissal affordance and should omit Web Awesome's header action region. The
|
|
195
202
|
theme sets `display: none` on the directly exported `header-actions` part; it
|
package/docs/workbench.md
CHANGED
|
@@ -198,7 +198,7 @@ and calls `wireNavStack` for animated push/pop and focus movement. See
|
|
|
198
198
|
rightRail={{
|
|
199
199
|
label: "Tickets",
|
|
200
200
|
collapsed: ticketsCollapsed.value,
|
|
201
|
-
toolbar: { toggle: { action: "toggle-tickets", name: "
|
|
201
|
+
toolbar: { toggle: { action: "toggle-tickets", name: "Tickets" } },
|
|
202
202
|
navStack: { id: "ticket-stack", label: "Tickets", views: ticketViews.value },
|
|
203
203
|
}}
|
|
204
204
|
/>
|
|
@@ -221,7 +221,10 @@ and close. A panel's `toolbar` has these parts:
|
|
|
221
221
|
toggle, which the Workbench renders: the per-side panel glyph,
|
|
222
222
|
`aria-controls` naming the panel, `aria-expanded`, a "Show …"/"Hide …"
|
|
223
223
|
label (or your localized `showLabel` / `hideLabel`), and the `data-action`
|
|
224
|
-
the app handles. It is always the last group.
|
|
224
|
+
the app handles. It is always the last group. `name` is the panel's
|
|
225
|
+
title-style name ("Navigator", "Build Output"): it becomes the toggle
|
|
226
|
+
group's accessible name and completes the "Show Navigator" / "Hide
|
|
227
|
+
Navigator" label, so it follows [the capitalization rule](./writing.md#capitalization).
|
|
225
228
|
|
|
226
229
|
While a panel is closed, marked groups follow their open-panel zone order
|
|
227
230
|
(`leading`, `center`, `trailing`), followed by its toggle:
|
|
@@ -249,8 +252,8 @@ toggle, so it never depends on a control it covers. An app's own
|
|
|
249
252
|
label: "Navigator",
|
|
250
253
|
title: <ToolbarText text="Navigator" />,
|
|
251
254
|
leading: <NewFileGroup />,
|
|
252
|
-
trailing: <ToolbarControlGroup relocateOnCollapse label="Search
|
|
253
|
-
toggle: { action: "toggle-navigator", name: "
|
|
255
|
+
trailing: <ToolbarControlGroup relocateOnCollapse label="Search Files"><SearchButton /></ToolbarControlGroup>,
|
|
256
|
+
toggle: { action: "toggle-navigator", name: "Navigator" },
|
|
254
257
|
},
|
|
255
258
|
content: <Files />,
|
|
256
259
|
collapsed: navCollapsed.value,
|
|
@@ -297,7 +300,8 @@ The `Pane`s and `List`s the Workbench composes around your content are
|
|
|
297
300
|
configurable the same way:
|
|
298
301
|
|
|
299
302
|
- `mainPane` (`PaneConfig`: `contentElement`, `contentLabel`, `separators`,
|
|
300
|
-
`safeAreaEdges`, `chromeDividers`, `appearance`
|
|
303
|
+
`safeAreaEdges`, `chromeDividers`, `appearance`, `deepInset`,
|
|
304
|
+
`scrollClearance`, `headerPresentation`, `tabIndex`, `outlined`) configures the work area's
|
|
301
305
|
`Pane`, which exists whenever the work area has a toolbar, `mainHeader`, or
|
|
302
306
|
`mainFooter`. Without that chrome, `appearance: "sunken"` paints the main
|
|
303
307
|
region's own scroll surface;
|
|
@@ -500,7 +504,7 @@ presents as one, mirroring `wireSidebar`'s compact overlay:
|
|
|
500
504
|
data-action="toggle-navigator"
|
|
501
505
|
aria-controls="editor-left-rail"
|
|
502
506
|
aria-expanded={String(!navCollapsed.value)}
|
|
503
|
-
aria-label={navCollapsed.value ? "Show
|
|
507
|
+
aria-label={navCollapsed.value ? "Show Navigator" : "Hide Navigator"}
|
|
504
508
|
>
|
|
505
509
|
<LucideIcon {...collapsiblePanelToggleIcon("left", navCollapsed.value)} />
|
|
506
510
|
</button>
|