@kerfjs/ui 5.0.0-beta.98 → 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 +487 -77
- package/ai/skill.md +40 -13
- 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 +22 -5
- package/dist/catalog.js +50 -31
- 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-AZWE2FB5.js → chunk-CMETHPKR.js} +12 -15
- 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-527IAEWG.js → chunk-PYBBYSZ3.js} +10 -17
- 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-Cp3Y8kJ9.d.ts → nav-stack-VXTumzKa.d.ts} +48 -3
- 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.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.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 +14 -4
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +66 -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/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 +40 -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 +14 -4
- 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 +66 -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 +54 -8
- package/docs/collapsible-panel.md +9 -6
- package/docs/component-contract.md +41 -12
- package/docs/component-selection.md +143 -19
- 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 +112 -2
- 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/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-527IAEWG.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-AZWE2FB5.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/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/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>
|
package/docs/writing.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Writing interface copy
|
|
2
|
+
|
|
3
|
+
Kerf UI follows Apple's capitalization conventions for interface text.
|
|
4
|
+
Apple's _Writing_ guidance asks for one style per UI element type, applied
|
|
5
|
+
consistently, and its element guidance assigns those styles. This page is the
|
|
6
|
+
package default, so every Kerf application, demo, and recipe uses the same
|
|
7
|
+
rule. An application may replace it only through a written, product-wide
|
|
8
|
+
style. It should never vary from one screen to the next.
|
|
9
|
+
|
|
10
|
+
## Capitalization
|
|
11
|
+
|
|
12
|
+
**Names are title style. Descriptions are sentence style.** Text that names a
|
|
13
|
+
command, control, view, or field uses title style ("Save Draft", "Workspace
|
|
14
|
+
Settings", "Release Date"). Text that describes, explains, reports, or asks
|
|
15
|
+
uses sentence style ("Changes sync when you reconnect").
|
|
16
|
+
|
|
17
|
+
| Element | Style | Examples |
|
|
18
|
+
| --------------------------------------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------------ |
|
|
19
|
+
| Buttons, split-button and toolbar actions, link-style commands | Title | Save Draft, Add to Favorites, Don’t Save, Log In |
|
|
20
|
+
| Menu items, menu group headings, popup-menu triggers | Title | Copy Reference, Sort By, Recently Updated, New Folder… |
|
|
21
|
+
| Segmented-control segments, `Select` and pop-up choices, tabs | Title | List View, Last 30 Days, In Review |
|
|
22
|
+
| Page, view, pane, dialog, and toolbar titles (`ToolbarText` titles), back labels | Title | Workspace Settings, Back to Inbox |
|
|
23
|
+
| Group and list headers (`ListHeader`), table column headings | Title | Saved Projects, Needs Attention, Last Modified |
|
|
24
|
+
| Catalog example and stack labels (`CatalogExample`, `CatalogExampleStack`) | Title | Heading Identity Stays Whole, Icon Trigger in a Group |
|
|
25
|
+
| Content item titles: the name an item or card shows | Title | Build Output, Work Area, Unsaved Changes |
|
|
26
|
+
| Field labels (`FieldLabel`, a field's `label`) | Title | Project Name, Release Date |
|
|
27
|
+
| Region and landmark names (accessible names of panes, toolbars, groups, lists, tab bars) | Title | Ticket Workbench, View Actions, Open Documents |
|
|
28
|
+
| Accessible names of icon-only controls | Title | More Actions, Clear Search |
|
|
29
|
+
| `EmptyState`, `StateBanner`, alert, and notification titles that are fragments | Title, no ending punctuation | No Release Tasks, Migration Needs Review |
|
|
30
|
+
| The same titles written as complete sentences | Sentence, with punctuation | Release tasks could not be refreshed. |
|
|
31
|
+
| Checkbox, switch, and radio option text | Sentence | Show hidden files, Notify me about replies |
|
|
32
|
+
| Body copy, `description`, `detail`, hints, empty-state and banner detail, dialog and alert messages | Sentence, with punctuation | Changes sync when you reconnect. |
|
|
33
|
+
| Tooltips and help text | Sentence | Copy the link to this ticket |
|
|
34
|
+
| Placeholders | Sentence | Search tickets |
|
|
35
|
+
| Status lines, counts, and timestamps (`ToolbarText` status, `Badge`, `CornerStatus`) | Sentence | Saved just now, 3 of 12 updated |
|
|
36
|
+
| Progress labels (`LoadingSpinner` and `Skeleton` `label`): the operation under way | Sentence, trailing ellipsis | Loading preview…, Refreshing release tasks… |
|
|
37
|
+
|
|
38
|
+
A name that a component composes into a longer label is a name too, so pass
|
|
39
|
+
it in title style. A panel toolbar's `toggle: { action, name }` labels the
|
|
40
|
+
toggle group with `name` and completes "Show …" / "Hide …" with it:
|
|
41
|
+
`name: "Navigator"` gives "Show Navigator". Kerf UI never recapitalizes it.
|
|
42
|
+
|
|
43
|
+
Data is never recapitalized. Names that a person or a system supplies keep
|
|
44
|
+
their own spelling: file names, ticket titles, user names, and tags. So do
|
|
45
|
+
code identifiers shown as text, such as a prop value a specimen is labeled
|
|
46
|
+
with (`danger`, `transparent`). A content
|
|
47
|
+
item that shows such data (a ticket subject, a message) keeps it as written;
|
|
48
|
+
only a title the interface itself names is title style. `ContentItem`'s own
|
|
49
|
+
`title` prop is a native tooltip, so it is sentence style. Keep a content
|
|
50
|
+
item's `ariaLabel` equal to its visible title.
|
|
51
|
+
|
|
52
|
+
### Title-style rules
|
|
53
|
+
|
|
54
|
+
From the [Apple Style Guide](https://support.apple.com/guide/applestyleguide/c-apsgb744e4a3/web)
|
|
55
|
+
(_capitalization_):
|
|
56
|
+
|
|
57
|
+
- **Capitalize** the first and last word, whatever their part of speech.
|
|
58
|
+
- **Capitalize** nouns, pronouns, verbs, adjectives, and adverbs, however
|
|
59
|
+
short: It, This, Your, Is, Are, Be.
|
|
60
|
+
- **Capitalize** subordinating conjunctions such as If, and prepositions of
|
|
61
|
+
five letters or more: About, Between, Through.
|
|
62
|
+
- **Capitalize** a preposition of any length that belongs to a phrasal verb
|
|
63
|
+
or acts as another part of speech: Start Up the Computer, Turn On, Log In to
|
|
64
|
+
the Server.
|
|
65
|
+
- **Capitalize** the second word of a hyphenated compound: High-Level Events,
|
|
66
|
+
Pop-Up Menu. Built-in and Plug-in are the exceptions.
|
|
67
|
+
- **Keep lowercase**:
|
|
68
|
+
- articles (a, an, the), unless one is the first word or follows a colon;
|
|
69
|
+
- coordinating conjunctions (and, but, or, nor, for, yet, so);
|
|
70
|
+
- _to_ in an infinitive (How to Start Your Computer);
|
|
71
|
+
- _as_ (Export a Document as a PDF);
|
|
72
|
+
- prepositions of four letters or fewer (at, by, for, from, in, into, of,
|
|
73
|
+
off, on, onto, out, over, to, up, with).
|
|
74
|
+
- **Keep the brand's own spelling** for words that always start lowercase,
|
|
75
|
+
such as iPad, iOS, and macOS.
|
|
76
|
+
|
|
77
|
+
### Sentence-style rules
|
|
78
|
+
|
|
79
|
+
Capitalize the first word and proper nouns or adjectives only. End a complete
|
|
80
|
+
sentence with punctuation. Leave a fragment without ending punctuation.
|
|
81
|
+
Tooltips may omit the final period.
|
|
82
|
+
|
|
83
|
+
### Related conventions
|
|
84
|
+
|
|
85
|
+
- An ellipsis (…) ends a command or menu item that needs more input before it
|
|
86
|
+
acts: New Ticket…, Save As…. The dialog it opens repeats the command as its
|
|
87
|
+
title, without the ellipsis.
|
|
88
|
+
- Label an action with its result. Prefer a verb: Publish Update, not OK.
|
|
89
|
+
- Keep a control's accessible name equal to its visible label, or starting
|
|
90
|
+
with it.
|
|
91
|
+
|
|
92
|
+
## Diagnostics
|
|
93
|
+
|
|
94
|
+
`kerf-ui-doctor` reports `KUI-D040` (warning) when a string or template
|
|
95
|
+
literal passed to a known title-style prop leaves a word lowercase that title
|
|
96
|
+
style capitalizes. In a template literal it judges only the static words:
|
|
97
|
+
`` `Edit ${name} shortcut` `` should be `` `Edit ${name} Shortcut` ``, and the
|
|
98
|
+
interpolated value keeps its own spelling. The covered props are:
|
|
99
|
+
|
|
100
|
+
- `ToolbarText` `text` when the text is a title: it has `headingLevel`, a
|
|
101
|
+
large size, or sits in a toolbar or panel `title`, `header`, or (unless small) `leading` slot;
|
|
102
|
+
- `ListHeader`, `ListActionRow`, `SplitButton`, and `Combobox` `label`;
|
|
103
|
+
- `CatalogExample` and `CatalogExampleStack` `label`;
|
|
104
|
+
- `EmptyState` and `StateBanner` `title`;
|
|
105
|
+
- `PopupMenu` `text` and item and heading labels, including submenus;
|
|
106
|
+
- `SegmentedControl`, `Select`, and `TabNavigator` choice and tab labels;
|
|
107
|
+
- `NavStack` view titles and `backText`, and `SplitView` `backLabel`;
|
|
108
|
+
- `FieldLabel` text and the text of a `button` or `wa-button`;
|
|
109
|
+
- the `name` of a panel toolbar's `toggle: { action, name }`;
|
|
110
|
+
- region and landmark names: the `label` of `Pane`, `Workbench`, `Toolbar`,
|
|
111
|
+
`ToolbarControlGroup`, `TabBar`, `NavStack`, `CollapsiblePanel`,
|
|
112
|
+
`FloatingToolbar`, and `ResizableRegion`, the `ariaLabel` of `SunkenPanel`
|
|
113
|
+
and `List`, a `Pane`'s `contentLabel`, the panel, toolbar, and pane labels
|
|
114
|
+
inside `Workbench`, `CollapsiblePanel`, and `NavStack` configuration, and
|
|
115
|
+
the `aria-label` of a landmark element (`section`, `nav`, `aside`, `main`,
|
|
116
|
+
`header`, `footer`, `form`, `search`) or landmark role;
|
|
117
|
+
- the `label` of a raw `wa-input`, `wa-select`, `wa-textarea`, or
|
|
118
|
+
`wa-radio-group`;
|
|
119
|
+
- the accessible names of icon-only controls: `IconButton` and
|
|
120
|
+
`IconToggleButton` `label`, `PopupMenu` `label`, `SplitButton`
|
|
121
|
+
`optionsLabel`, `TokenSearchField` `clearLabel`, and the `aria-label` of a
|
|
122
|
+
`button` or `wa-button` whose only content is an icon.
|
|
123
|
+
|
|
124
|
+
The check never judges sentence-style surfaces (including `wa-checkbox`,
|
|
125
|
+
`wa-switch`, and `wa-radio` option text and the `LoadingSpinner` and
|
|
126
|
+
`Skeleton` status labels), interpolated or other dynamic values, or text
|
|
127
|
+
ending with `.`, `!`, or `?`. It skips a word joined to an interpolation, tokens containing digits, code, or paths, and
|
|
128
|
+
lowercase-led brands such as iOS. It does not report capitalized short words,
|
|
129
|
+
because Apple capitalizes a phrasal verb's particle. Suppress `KUI-D040` for a
|
|
130
|
+
lowercase brand or product name. See [the doctor](./ui-doctor.md).
|
|
131
|
+
|
|
132
|
+
## Sources
|
|
133
|
+
|
|
134
|
+
- Apple Human Interface Guidelines,
|
|
135
|
+
[Writing](https://developer.apple.com/design/human-interface-guidelines/writing):
|
|
136
|
+
choose a capitalization style for each element type and use it consistently.
|
|
137
|
+
- [Menus](https://developer.apple.com/design/human-interface-guidelines/menus)
|
|
138
|
+
and [The menu bar](https://developer.apple.com/design/human-interface-guidelines/the-menu-bar):
|
|
139
|
+
menu items and multi-word menu titles use title-style capitalization.
|
|
140
|
+
- [Alerts](https://developer.apple.com/design/human-interface-guidelines/alerts)
|
|
141
|
+
and [Notifications](https://developer.apple.com/design/human-interface-guidelines/notifications):
|
|
142
|
+
a fragment title uses title style. A complete-sentence title and the
|
|
143
|
+
message use sentence style with punctuation.
|
|
144
|
+
- [Offering help](https://developer.apple.com/design/human-interface-guidelines/offering-help):
|
|
145
|
+
tooltips use sentence case.
|
|
146
|
+
- The archived OS X Human Interface Guidelines, _Use the Right Capitalization
|
|
147
|
+
Style in Labels and Text_. Title style covers menu titles and items, push
|
|
148
|
+
buttons, toolbar item labels, and labels that are not sentences, such as
|
|
149
|
+
group box and list headings. Sentence style covers checkbox and radio option
|
|
150
|
+
text and dialog messages.
|
|
151
|
+
- [Apple Style Guide](https://support.apple.com/guide/applestyleguide/c-apsgb744e4a3/web),
|
|
152
|
+
_capitalization_: the title-style word rules above.
|