@kerfjs/ui 5.0.0-beta.4 → 5.0.0-beta.40
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 +342 -108
- package/ai/application-ui-diagnostic-ids-v1.json +100 -0
- package/ai/application-ui-profile-sync.cjs +529 -0
- package/ai/application-ui-profile.d.mts +1 -0
- package/ai/application-ui-profile.d.ts +102 -0
- package/ai/application-ui-profile.defaults.json +41 -0
- package/ai/application-ui-profile.mjs +626 -0
- package/ai/application-ui-profile.schema.json +130 -0
- package/ai/catalog-authoring.json +25 -0
- package/ai/catalog-authoring.schema.json +61 -0
- package/ai/compile-time-contracts-v1.json +132 -0
- package/ai/compile-time-contracts-v1.schema.json +51 -0
- package/ai/component-catalog-extension-v2.d.ts +7 -0
- package/ai/component-catalog-extension-v2.schema.json +7 -0
- package/ai/component-catalog-extension.schema.json +79 -0
- package/ai/component-catalog-v2-overrides.json +496 -0
- package/ai/component-catalog-v2.d.ts +90 -0
- package/ai/component-catalog-v2.json +5678 -0
- package/ai/component-catalog-v2.schema.json +298 -0
- package/ai/component-catalog.json +2694 -417
- package/ai/component-catalog.schema.json +39 -0
- package/ai/public-api-signatures-v1.md +1591 -126
- package/ai/skill.md +140 -54
- package/ai/webawesome-jsx-signatures-v1.md +2 -1
- package/analyzer/cli.mjs +49 -0
- package/analyzer/index.d.mts +46 -0
- package/analyzer/index.mjs +1086 -0
- package/analyzer/report.schema.json +66 -0
- package/dist/app-tab.d.ts +15 -4
- package/dist/app-tab.js +3 -1
- package/dist/browser/app-tab.js +1 -0
- package/dist/browser/floating-toolbar.js +3 -0
- package/dist/browser/list-action-row.js +5 -0
- package/dist/browser/list-header.js +7 -0
- package/dist/browser/list-inset-control.js +3 -0
- package/dist/browser/list-inset-text.js +3 -0
- package/dist/browser/list-item.js +5 -0
- package/dist/browser/list.js +3 -0
- package/dist/browser/pane.js +3 -0
- package/dist/browser/row.js +3 -0
- package/dist/browser/segmented-control.js +1 -0
- package/dist/browser/select.js +1 -0
- package/dist/browser/skeleton.js +3 -0
- package/dist/browser/spacer.js +3 -0
- package/dist/browser/state-banner.js +1 -0
- package/dist/browser/sunken-panel.js +3 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/browser/text.js +3 -0
- package/dist/browser/toolbar-text.js +1 -0
- package/dist/browser/value-table.js +1 -0
- package/dist/catalog-resources.d.ts +35 -0
- package/dist/catalog-resources.js +22 -0
- package/dist/catalog-resources.js.map +1 -0
- package/dist/catalog.d.ts +151 -0
- package/dist/catalog.js +396 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chunk-2TYUFZUC.js +22 -0
- package/dist/chunk-2TYUFZUC.js.map +1 -0
- package/dist/chunk-6NDBE2OK.js +32 -0
- package/dist/chunk-6NDBE2OK.js.map +1 -0
- package/dist/chunk-6WTETUZ6.js +21 -0
- package/dist/chunk-6WTETUZ6.js.map +1 -0
- package/dist/chunk-AQFWBG23.js +83 -0
- package/dist/chunk-AQFWBG23.js.map +1 -0
- package/dist/chunk-B6JYRX3P.js +51 -0
- package/dist/chunk-B6JYRX3P.js.map +1 -0
- package/dist/chunk-C34NZOLJ.js +53 -0
- package/dist/chunk-C34NZOLJ.js.map +1 -0
- package/dist/chunk-CAB6NQ2T.js +102 -0
- package/dist/chunk-CAB6NQ2T.js.map +1 -0
- package/dist/chunk-CK6P5AUK.js +136 -0
- package/dist/chunk-CK6P5AUK.js.map +1 -0
- package/dist/chunk-DAO2VFTT.js +129 -0
- package/dist/chunk-DAO2VFTT.js.map +1 -0
- package/dist/chunk-DEYOGDE7.js +141 -0
- package/dist/chunk-DEYOGDE7.js.map +1 -0
- package/dist/chunk-DYBPI5O2.js +25 -0
- package/dist/chunk-DYBPI5O2.js.map +1 -0
- package/dist/{chunk-TRNBHPNW.js → chunk-E34TE2ZI.js} +12 -8
- package/dist/chunk-E34TE2ZI.js.map +1 -0
- package/dist/chunk-EYALJQQD.js +25 -0
- package/dist/chunk-EYALJQQD.js.map +1 -0
- package/dist/chunk-I45QO2IZ.js +88 -0
- package/dist/chunk-I45QO2IZ.js.map +1 -0
- package/dist/chunk-I4V3UDSA.js +79 -0
- package/dist/chunk-I4V3UDSA.js.map +1 -0
- package/dist/chunk-OGTJNHRG.js +42 -0
- package/dist/chunk-OGTJNHRG.js.map +1 -0
- package/dist/chunk-OL4TC3U2.js +156 -0
- package/dist/chunk-OL4TC3U2.js.map +1 -0
- package/dist/chunk-OMSRSL3B.js +120 -0
- package/dist/chunk-OMSRSL3B.js.map +1 -0
- package/dist/chunk-R3EBGEAW.js +46 -0
- package/dist/chunk-R3EBGEAW.js.map +1 -0
- package/dist/chunk-SOK5EUF7.js +25 -0
- package/dist/chunk-SOK5EUF7.js.map +1 -0
- package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-T7DOWS6T.js +61 -0
- package/dist/chunk-T7DOWS6T.js.map +1 -0
- package/dist/chunk-TIGSG6BX.js +218 -0
- package/dist/chunk-TIGSG6BX.js.map +1 -0
- package/dist/chunk-UDHHKZWO.js +41 -0
- package/dist/chunk-UDHHKZWO.js.map +1 -0
- package/dist/{chunk-MQIZAD4A.js → chunk-UKKSMZYT.js} +76 -22
- package/dist/chunk-UKKSMZYT.js.map +1 -0
- package/dist/chunk-V6GQKOX2.js +39 -0
- package/dist/chunk-V6GQKOX2.js.map +1 -0
- package/dist/chunk-V6HCTCVD.js +46 -0
- package/dist/chunk-V6HCTCVD.js.map +1 -0
- package/dist/chunk-VDUJZF5G.js +515 -0
- package/dist/chunk-VDUJZF5G.js.map +1 -0
- package/dist/chunk-VXFGMDA7.js +31 -0
- package/dist/chunk-VXFGMDA7.js.map +1 -0
- package/dist/chunk-WN52USHV.js +115 -0
- package/dist/chunk-WN52USHV.js.map +1 -0
- package/dist/chunk-WSXUPSID.js +43 -0
- package/dist/chunk-WSXUPSID.js.map +1 -0
- package/dist/chunk-X5GRDQ7V.js +50 -0
- package/dist/chunk-X5GRDQ7V.js.map +1 -0
- package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
- package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
- package/dist/chunk-ZASJJMGV.js +17 -0
- package/dist/chunk-ZASJJMGV.js.map +1 -0
- package/dist/chunk-ZPWZIVI6.js +47 -0
- package/dist/chunk-ZPWZIVI6.js.map +1 -0
- package/dist/collapsible-panel.d.ts +77 -0
- package/dist/collapsible-panel.js +84 -0
- package/dist/collapsible-panel.js.map +1 -0
- package/dist/css-values.d.ts +75 -0
- package/dist/css-values.js +3 -0
- package/dist/css-values.js.map +1 -0
- package/dist/device-class.d.ts +62 -0
- package/dist/device-class.js +103 -0
- package/dist/device-class.js.map +1 -0
- package/dist/disclosure-arrow.js +1 -1
- package/dist/divider-sides-BzB6rphT.d.ts +6 -0
- package/dist/empty-state.d.ts +3 -2
- package/dist/empty-state.js +1 -1
- package/dist/flex-alignment-CF8NLj7i.d.ts +4 -0
- package/dist/floating-toolbar.d.ts +29 -0
- package/dist/floating-toolbar.js +3 -0
- package/dist/floating-toolbar.js.map +1 -0
- package/dist/index.d.ts +28 -14
- package/dist/index.js +34 -23
- package/dist/{menu-action-row.d.ts → list-action-row.d.ts} +19 -8
- package/dist/list-action-row.js +7 -0
- package/dist/list-action-row.js.map +1 -0
- package/dist/list-header.d.ts +80 -0
- package/dist/list-header.js +9 -0
- package/dist/list-header.js.map +1 -0
- package/dist/list-inset-control.d.ts +20 -0
- package/dist/list-inset-control.js +3 -0
- package/dist/list-inset-control.js.map +1 -0
- package/dist/list-inset-text.d.ts +29 -0
- package/dist/list-inset-text.js +3 -0
- package/dist/list-inset-text.js.map +1 -0
- package/dist/list-item.d.ts +45 -0
- package/dist/list-item.js +7 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list.d.ts +30 -0
- package/dist/list.js +5 -0
- package/dist/list.js.map +1 -0
- package/dist/loading-spinner.js +1 -1
- package/dist/nav-stack.d.ts +41 -0
- package/dist/nav-stack.js +6 -0
- package/dist/nav-stack.js.map +1 -0
- package/dist/pane.d.ts +50 -0
- package/dist/pane.js +4 -0
- package/dist/pane.js.map +1 -0
- package/dist/resizable-region.d.ts +21 -3
- package/dist/resizable-region.js +1 -1
- package/dist/row.d.ts +28 -0
- package/dist/row.js +5 -0
- package/dist/row.js.map +1 -0
- package/dist/segmented-control.d.ts +11 -8
- package/dist/segmented-control.js +3 -1
- package/dist/select-register.d.ts +5 -1
- package/dist/select-register.js +129 -1
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +34 -8
- package/dist/select.js +3 -1
- package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
- package/dist/skeleton.d.ts +25 -0
- package/dist/skeleton.js +4 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/spacer.d.ts +16 -0
- package/dist/spacer.js +4 -0
- package/dist/spacer.js.map +1 -0
- package/dist/split-view.d.ts +43 -0
- package/dist/split-view.js +82 -0
- package/dist/split-view.js.map +1 -0
- package/dist/state-banner.d.ts +11 -5
- package/dist/state-banner.js +3 -1
- package/dist/styles/app-tab.css +26 -0
- package/dist/styles/catalog.css +582 -0
- package/dist/styles/collapsible-panel.css +212 -0
- package/dist/styles/floating-toolbar.css +38 -0
- package/dist/styles/foundation.css +80 -0
- package/dist/styles/layout.css +2 -20
- package/dist/styles/list-action-row.css +224 -0
- package/dist/styles/list-header.css +224 -0
- package/dist/styles/list-inset-control.css +23 -0
- package/dist/styles/list-inset-text.css +30 -0
- package/dist/styles/list-item.css +171 -0
- package/dist/styles/list.css +118 -0
- package/dist/styles/nav-stack.css +141 -0
- package/dist/styles/pane.css +62 -0
- package/dist/styles/resizable-region.css +158 -0
- package/dist/styles/row.css +92 -0
- package/dist/styles/segmented-control.css +10 -7
- package/dist/styles/select.css +115 -2
- package/dist/styles/skeleton.css +31 -0
- package/dist/styles/spacer.css +11 -0
- package/dist/styles/split-view.css +35 -0
- package/dist/styles/state-banner.css +49 -10
- package/dist/styles/styles.css +10 -5
- package/dist/styles/sunken-panel.css +22 -0
- package/dist/styles/surface-scaffold.css +51 -0
- package/dist/styles/tab-bar.css +24 -0
- package/dist/styles/tab-scaffold.css +85 -0
- package/dist/styles/text.css +5 -0
- package/dist/styles/token-search-field.css +14 -2
- package/dist/styles/toolbar-control-group.css +235 -8
- package/dist/styles/toolbar-text.css +65 -2
- package/dist/styles/toolbar.css +47 -2
- package/dist/styles/webawesome.css +171 -0
- package/dist/styles/workbench.css +187 -0
- package/dist/sunken-panel.d.ts +20 -0
- package/dist/sunken-panel.js +3 -0
- package/dist/sunken-panel.js.map +1 -0
- package/dist/surface-scaffold.d.ts +26 -0
- package/dist/surface-scaffold.js +3 -0
- package/dist/surface-scaffold.js.map +1 -0
- package/dist/tab-bar.d.ts +24 -6
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +31 -0
- package/dist/tab-scaffold.js +51 -0
- package/dist/tab-scaffold.js.map +1 -0
- package/dist/text.d.ts +20 -0
- package/dist/text.js +3 -0
- package/dist/text.js.map +1 -0
- package/dist/token-search-field.d.ts +30 -13
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +33 -7
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +31 -4
- package/dist/toolbar-text.js +3 -1
- package/dist/toolbar.d.ts +10 -7
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +7 -3
- package/dist/value-table.js +3 -1
- package/dist/webawesome.d.ts +1 -0
- package/dist/wire-catalog.d.ts +57 -0
- package/dist/wire-catalog.js +302 -0
- package/dist/wire-catalog.js.map +1 -0
- package/dist/wire-nav-stack.d.ts +18 -0
- package/dist/wire-nav-stack.js +228 -0
- package/dist/wire-nav-stack.js.map +1 -0
- package/dist/wire-resizable-regions.d.ts +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +48 -0
- package/dist/wire-sidebar.js +147 -0
- package/dist/wire-sidebar.js.map +1 -0
- package/dist/wire-tab-bars.d.ts +19 -2
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-scaffold.d.ts +11 -0
- package/dist/wire-tab-scaffold.js +21 -0
- package/dist/wire-tab-scaffold.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +104 -4
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +44 -0
- package/dist/workbench.js +106 -0
- package/dist/workbench.js.map +1 -0
- package/docs/accessibility.md +155 -20
- package/docs/app-layouts.md +61 -0
- package/docs/catalog.md +364 -0
- package/docs/collapsible-panel.md +142 -0
- package/docs/component-contract.md +258 -28
- package/docs/component-integration.md +63 -0
- package/docs/component-selection.md +219 -57
- package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
- package/docs/design/templates/empty-state/filtered.svg +1 -0
- package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
- package/docs/design/templates/empty-state/with-action.svg +1 -0
- package/docs/design/templates/empty-state-dark.svg +1 -0
- package/docs/design/templates/empty-state.svg +1 -0
- package/docs/design/templates/list/compact-dark.svg +1 -0
- package/docs/design/templates/list/compact.svg +1 -0
- package/docs/design/templates/list/stack-dark.svg +1 -0
- package/docs/design/templates/list/stack.svg +1 -0
- package/docs/design/templates/list-action-row/default-dark.svg +1 -0
- package/docs/design/templates/list-action-row/default.svg +1 -0
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
- package/docs/design/templates/list-action-row/selected.svg +1 -0
- package/docs/design/templates/list-action-row-dark.svg +1 -0
- package/docs/design/templates/list-action-row.svg +1 -0
- package/docs/design/templates/list-dark.svg +1 -0
- package/docs/design/templates/list-header/action-dark.svg +1 -0
- package/docs/design/templates/list-header/action.svg +1 -0
- package/docs/design/templates/list-header/count-dark.svg +1 -0
- package/docs/design/templates/list-header/count.svg +1 -0
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
- package/docs/design/templates/list-header/inline-action.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
- package/docs/design/templates/list-header-dark.svg +1 -0
- package/docs/design/templates/list-header.svg +1 -0
- package/docs/design/templates/list-item/default-dark.svg +1 -0
- package/docs/design/templates/list-item/default.svg +1 -0
- package/docs/design/templates/list-item/multiline-dark.svg +1 -0
- package/docs/design/templates/list-item/multiline.svg +1 -0
- package/docs/design/templates/list-item/selected-dark.svg +1 -0
- package/docs/design/templates/list-item/selected.svg +1 -0
- package/docs/design/templates/list-item/trailing-dark.svg +1 -0
- package/docs/design/templates/list-item/trailing.svg +1 -0
- package/docs/design/templates/list-item-dark.svg +1 -0
- package/docs/design/templates/list-item.svg +1 -0
- package/docs/design/templates/list.svg +1 -0
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
- package/docs/design/templates/segmented-control/equal.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small.svg +1 -0
- package/docs/design/templates/segmented-control-dark.svg +1 -0
- package/docs/design/templates/segmented-control.svg +1 -0
- package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
- package/docs/design/templates/skeleton/avatar.svg +1 -0
- package/docs/design/templates/skeleton/block-dark.svg +1 -0
- package/docs/design/templates/skeleton/block.svg +1 -0
- package/docs/design/templates/skeleton/lines-dark.svg +1 -0
- package/docs/design/templates/skeleton/lines.svg +1 -0
- package/docs/design/templates/skeleton-dark.svg +1 -0
- package/docs/design/templates/skeleton.svg +1 -0
- package/docs/design/templates/state-banner/danger-dark.svg +1 -0
- package/docs/design/templates/state-banner/danger.svg +1 -0
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
- package/docs/design/templates/state-banner/info-badge.svg +1 -0
- package/docs/design/templates/state-banner/info-dark.svg +1 -0
- package/docs/design/templates/state-banner/info.svg +1 -0
- package/docs/design/templates/state-banner/success-dark.svg +1 -0
- package/docs/design/templates/state-banner/success.svg +1 -0
- package/docs/design/templates/state-banner/warning-dark.svg +1 -0
- package/docs/design/templates/state-banner/warning.svg +1 -0
- package/docs/design/templates/state-banner-dark.svg +1 -0
- package/docs/design/templates/state-banner.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
- package/docs/design/templates/tab-bar-dark.svg +1 -0
- package/docs/design/templates/tab-bar.svg +1 -0
- package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
- package/docs/design/templates/token-search-field/empty.svg +1 -0
- package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
- package/docs/design/templates/token-search-field/tokens.svg +1 -0
- package/docs/design/templates/token-search-field-dark.svg +1 -0
- package/docs/design/templates/token-search-field.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group.svg +1 -0
- package/docs/design/templates/toolbar-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default.svg +1 -0
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/large.svg +1 -0
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/small.svg +1 -0
- package/docs/design/templates/toolbar-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-text.svg +1 -0
- package/docs/design/templates/toolbar.svg +1 -0
- package/docs/design/templates/value-table/details-dark.svg +1 -0
- package/docs/design/templates/value-table/details.svg +1 -0
- package/docs/design/templates/value-table-dark.svg +1 -0
- package/docs/design/templates/value-table.svg +1 -0
- package/docs/design/templates.md +128 -0
- package/docs/design-philosophy.md +33 -11
- package/docs/device-class.md +54 -0
- package/docs/examples/application-ui-profile.json +60 -0
- package/docs/examples/command-palette-adapter.tsx +68 -17
- package/docs/examples/component-catalog-extension-v2.json +80 -0
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/layout.md +169 -38
- package/docs/nav-stack.md +77 -0
- package/docs/recipes.md +64 -16
- package/docs/split-view.md +55 -0
- package/docs/sunken-panel.md +53 -0
- package/docs/surface-scaffold.md +25 -0
- package/docs/tab-scaffold.md +52 -0
- package/docs/type-contracts.md +127 -0
- package/docs/ui-analyzer.md +118 -0
- package/docs/ui-doctor.md +91 -0
- package/docs/ui-evaluator.md +122 -0
- package/docs/ux-demo.md +29 -10
- package/docs/webawesome-theme.md +82 -8
- package/docs/workbench.md +123 -0
- package/doctor/cli.mjs +115 -0
- package/doctor/config.schema.json +68 -0
- package/doctor/eslint-diagnostics.d.mts +24 -0
- package/doctor/eslint-diagnostics.mjs +24 -0
- package/doctor/index.d.mts +116 -0
- package/doctor/index.mjs +1272 -0
- package/doctor/report.schema.json +118 -0
- package/evaluator/cli.mjs +89 -0
- package/evaluator/index.d.mts +90 -0
- package/evaluator/index.mjs +1138 -0
- package/evaluator/report.schema.json +152 -0
- package/llms.txt +260 -32
- package/package.json +205 -38
- package/traversal-exclusions.mjs +27 -0
- package/ux-demo/recipes/app-shell.tsx +223 -13
- package/ux-demo/recipes/collapsible-sidebar.tsx +230 -0
- package/ux-demo/recipes/compact-toolbar.tsx +116 -12
- package/ux-demo/recipes/composer-form.tsx +120 -19
- package/ux-demo/recipes/list-detail-dialog.tsx +205 -0
- package/ux-demo/recipes/list-workspace-states.tsx +176 -9
- package/ux-demo/recipes/loaders.ts +13 -4
- package/ux-demo/recipes/loading-inspector.tsx +191 -0
- package/ux-demo/recipes/mount-recipe.ts +31 -5
- package/ux-demo/recipes/navigation-sidebar.tsx +123 -11
- package/ux-demo/recipes/navigation-stack.tsx +121 -0
- package/ux-demo/recipes/recipes.css +125 -16
- package/ux-demo/recipes/types.ts +9 -1
- package/ux-demo/recipes/workspace-header.tsx +72 -3
- package/dist/browser/dialog-header.js +0 -5
- package/dist/browser/menu-action-row.js +0 -3
- package/dist/browser/menu-header.js +0 -5
- package/dist/browser/menu-item.js +0 -3
- package/dist/browser/page-header.js +0 -3
- package/dist/chunk-2PES33HS.js +0 -13
- package/dist/chunk-2PES33HS.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-7BR3DO2A.js.map +0 -1
- package/dist/chunk-7LDCTU7D.js +0 -134
- package/dist/chunk-7LDCTU7D.js.map +0 -1
- package/dist/chunk-AQNKJRFH.js +0 -79
- package/dist/chunk-AQNKJRFH.js.map +0 -1
- package/dist/chunk-CTQKI2XL.js +0 -28
- package/dist/chunk-CTQKI2XL.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-EGHL5S4P.js +0 -33
- package/dist/chunk-EGHL5S4P.js.map +0 -1
- package/dist/chunk-GY5WH7TO.js +0 -10
- package/dist/chunk-GY5WH7TO.js.map +0 -1
- package/dist/chunk-H5AGGVU5.js +0 -75
- package/dist/chunk-H5AGGVU5.js.map +0 -1
- package/dist/chunk-K3G72I6D.js +0 -24
- package/dist/chunk-K3G72I6D.js.map +0 -1
- package/dist/chunk-M5JRI6MN.js +0 -27
- package/dist/chunk-M5JRI6MN.js.map +0 -1
- package/dist/chunk-MBR3TYNL.js +0 -14
- package/dist/chunk-MBR3TYNL.js.map +0 -1
- package/dist/chunk-MFKMHK5W.js +0 -10
- package/dist/chunk-MFKMHK5W.js.map +0 -1
- package/dist/chunk-MQIZAD4A.js.map +0 -1
- package/dist/chunk-NPPD2A6O.js +0 -40
- package/dist/chunk-NPPD2A6O.js.map +0 -1
- package/dist/chunk-R6JHHBKQ.js +0 -19
- package/dist/chunk-R6JHHBKQ.js.map +0 -1
- package/dist/chunk-S3TPM2LP.js +0 -23
- package/dist/chunk-S3TPM2LP.js.map +0 -1
- package/dist/chunk-TRNBHPNW.js.map +0 -1
- package/dist/chunk-VHW5YNIB.js +0 -17
- package/dist/chunk-VHW5YNIB.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-XZXRLY5Q.js +0 -33
- package/dist/chunk-XZXRLY5Q.js.map +0 -1
- package/dist/dialog-header.d.ts +0 -15
- package/dist/dialog-header.js +0 -5
- package/dist/dialog-header.js.map +0 -1
- package/dist/menu-action-row.js +0 -4
- package/dist/menu-action-row.js.map +0 -1
- package/dist/menu-header.d.ts +0 -41
- package/dist/menu-header.js +0 -6
- package/dist/menu-header.js.map +0 -1
- package/dist/menu-item.d.ts +0 -31
- package/dist/menu-item.js +0 -4
- package/dist/menu-item.js.map +0 -1
- package/dist/page-header.d.ts +0 -9
- package/dist/page-header.js +0 -3
- package/dist/page-header.js.map +0 -1
- package/dist/styles/dialog-header.css +0 -87
- package/dist/styles/menu-action-row.css +0 -160
- package/dist/styles/menu-header.css +0 -143
- package/dist/styles/menu-item.css +0 -123
- package/dist/styles/page-header.css +0 -33
- package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/evaluator/report.schema.json",
|
|
4
|
+
"title": "Kerf UI browser evaluation report",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": [
|
|
7
|
+
"schemaVersion",
|
|
8
|
+
"tool",
|
|
9
|
+
"target",
|
|
10
|
+
"recordedAt",
|
|
11
|
+
"profileFiles",
|
|
12
|
+
"contexts",
|
|
13
|
+
"diagnostics",
|
|
14
|
+
"summary",
|
|
15
|
+
"artifacts",
|
|
16
|
+
"subjectiveReview"
|
|
17
|
+
],
|
|
18
|
+
"additionalProperties": false,
|
|
19
|
+
"properties": {
|
|
20
|
+
"schemaVersion": { "const": 1 },
|
|
21
|
+
"tool": {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"required": ["name", "reportVersion"],
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"properties": {
|
|
26
|
+
"name": { "const": "@kerfjs/ui/evaluator" },
|
|
27
|
+
"reportVersion": { "const": 1 }
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"target": {
|
|
31
|
+
"type": "object",
|
|
32
|
+
"required": ["url"],
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"properties": { "url": { "type": "string", "minLength": 1 } }
|
|
35
|
+
},
|
|
36
|
+
"recordedAt": { "type": "string", "format": "date-time" },
|
|
37
|
+
"profileFiles": { "$ref": "#/$defs/stringList" },
|
|
38
|
+
"contexts": {
|
|
39
|
+
"type": "array",
|
|
40
|
+
"minItems": 1,
|
|
41
|
+
"items": { "$ref": "#/$defs/context" }
|
|
42
|
+
},
|
|
43
|
+
"diagnostics": {
|
|
44
|
+
"type": "array",
|
|
45
|
+
"items": { "$ref": "#/$defs/diagnostic" }
|
|
46
|
+
},
|
|
47
|
+
"summary": { "$ref": "#/$defs/summary" },
|
|
48
|
+
"artifacts": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"required": ["retention", "files"],
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"properties": {
|
|
53
|
+
"retention": { "enum": ["always", "on-failure", "never"] },
|
|
54
|
+
"files": {
|
|
55
|
+
"type": "array",
|
|
56
|
+
"items": {
|
|
57
|
+
"type": "object",
|
|
58
|
+
"required": ["path", "sha256"],
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"properties": {
|
|
61
|
+
"path": { "type": "string", "minLength": 1 },
|
|
62
|
+
"sha256": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"pattern": "^[a-f0-9]{64}$"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"subjectiveReview": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"required": ["status", "rubric", "ratings", "note"],
|
|
74
|
+
"additionalProperties": false,
|
|
75
|
+
"properties": {
|
|
76
|
+
"status": { "const": "not-recorded" },
|
|
77
|
+
"rubric": {
|
|
78
|
+
"type": "array",
|
|
79
|
+
"minItems": 6,
|
|
80
|
+
"items": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"required": ["id", "prompt"],
|
|
83
|
+
"additionalProperties": false,
|
|
84
|
+
"properties": {
|
|
85
|
+
"id": { "type": "string", "minLength": 1 },
|
|
86
|
+
"prompt": { "type": "string", "minLength": 1 }
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"ratings": { "type": "array", "maxItems": 0 },
|
|
91
|
+
"note": { "type": "string", "minLength": 1 }
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"$defs": {
|
|
96
|
+
"stringList": {
|
|
97
|
+
"type": "array",
|
|
98
|
+
"items": { "type": "string", "minLength": 1 },
|
|
99
|
+
"uniqueItems": true
|
|
100
|
+
},
|
|
101
|
+
"summary": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"required": ["errors", "warnings", "passed"],
|
|
104
|
+
"additionalProperties": false,
|
|
105
|
+
"properties": {
|
|
106
|
+
"errors": { "type": "integer", "minimum": 0 },
|
|
107
|
+
"warnings": { "type": "integer", "minimum": 0 },
|
|
108
|
+
"passed": { "type": "boolean" }
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"context": {
|
|
112
|
+
"type": "object",
|
|
113
|
+
"required": [
|
|
114
|
+
"id",
|
|
115
|
+
"browser",
|
|
116
|
+
"width",
|
|
117
|
+
"height",
|
|
118
|
+
"zoom",
|
|
119
|
+
"colorScheme",
|
|
120
|
+
"reducedMotion",
|
|
121
|
+
"evidence",
|
|
122
|
+
"summary"
|
|
123
|
+
],
|
|
124
|
+
"additionalProperties": false,
|
|
125
|
+
"properties": {
|
|
126
|
+
"id": { "type": "string", "minLength": 1 },
|
|
127
|
+
"browser": { "enum": ["chromium", "firefox", "webkit"] },
|
|
128
|
+
"width": { "type": "integer", "minimum": 1 },
|
|
129
|
+
"height": { "type": "integer", "minimum": 1 },
|
|
130
|
+
"zoom": { "type": "number", "minimum": 1 },
|
|
131
|
+
"colorScheme": { "enum": ["light", "dark"] },
|
|
132
|
+
"reducedMotion": { "enum": ["reduce", "no-preference"] },
|
|
133
|
+
"evidence": { "type": "object" },
|
|
134
|
+
"summary": { "$ref": "#/$defs/summary" }
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
"diagnostic": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"required": ["code", "severity", "context", "message"],
|
|
140
|
+
"additionalProperties": false,
|
|
141
|
+
"properties": {
|
|
142
|
+
"code": { "type": "string", "pattern": "^KUI-B[0-9]{3}$" },
|
|
143
|
+
"severity": { "enum": ["error", "warning"] },
|
|
144
|
+
"context": { "type": "string", "minLength": 1 },
|
|
145
|
+
"message": { "type": "string", "minLength": 1 },
|
|
146
|
+
"repair": { "type": "string", "minLength": 1 },
|
|
147
|
+
"selector": { "type": "string", "minLength": 1 },
|
|
148
|
+
"evidence": {}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
package/llms.txt
CHANGED
|
@@ -1,45 +1,273 @@
|
|
|
1
1
|
# @kerfjs/ui
|
|
2
2
|
|
|
3
|
-
Accessible, production-backed UI primitives for kerf
|
|
3
|
+
> Accessible, production-backed UI primitives for [kerf](https://github.com/brianwestphal/kerf)
|
|
4
|
+
> applications. Components are plain functions returning `SafeHtml`; the app owns
|
|
5
|
+
> state and wires stable `data-action` hooks once. This file orients an LLM to
|
|
6
|
+
> generate correct, good-looking kerf UI — it is not a catalog to browse.
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
- [Public API signature snapshot](./ai/public-api-signatures-v1.md)
|
|
9
|
-
- [Web Awesome JSX signature snapshot](./ai/webawesome-jsx-signatures-v1.md)
|
|
10
|
-
- [Need-first component selection matrix](./docs/component-selection.md)
|
|
11
|
-
- [Production composition recipes](./docs/recipes.md)
|
|
12
|
-
- [Component contract](./docs/component-contract.md)
|
|
13
|
-
- [Web Awesome theme contract](./docs/webawesome-theme.md)
|
|
14
|
-
- [Accessibility and keyboard contracts](./docs/accessibility.md)
|
|
15
|
-
- [Design philosophy](./docs/design-philosophy.md)
|
|
16
|
-
- [Apple HIG translation](./docs/apple-hig.md)
|
|
17
|
-
- [UX catalog](./docs/ux-demo.md)
|
|
8
|
+
```bash
|
|
9
|
+
npm install kerfjs @kerfjs/ui # kerfjs is a peer; Web Awesome is an optional peer
|
|
10
|
+
```
|
|
18
11
|
|
|
19
|
-
|
|
12
|
+
Import each component from its own subpath (`@kerfjs/ui/list-item`, `@kerfjs/ui/toolbar`,
|
|
13
|
+
…); the browser build pulls that component's reachable CSS automatically, so do not
|
|
14
|
+
maintain a central style list. Configure JSX with `"jsxImportSource": "kerfjs"`.
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
## How to build a screen (retrieval order)
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
1. **Pick the component from the interface need**, not by appearance — read
|
|
19
|
+
[component-selection.md](./docs/component-selection.md) (the problem→component
|
|
20
|
+
matrix, with imports, wiring, ownership, and alternatives).
|
|
21
|
+
2. **Get exact signatures before emitting code** — read
|
|
22
|
+
[public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) (real prop names,
|
|
23
|
+
callback shapes, disposer return types).
|
|
24
|
+
3. **For exhaustive, structured facts** (ids, exports, variants, `publicClasses`,
|
|
25
|
+
relationships, side effects, and geometry ownership) load the
|
|
26
|
+
[Machine-readable component catalog](./ai/component-catalog.json) — the
|
|
27
|
+
canonical checked-in source; its schema is alongside it. Also load the
|
|
28
|
+
consuming application's catalog extension when present; generate one from the
|
|
29
|
+
[Consumer catalog extension schema](./ai/component-catalog-extension.schema.json)
|
|
30
|
+
when app-owned components must participate in selection or alignment.
|
|
31
|
+
Load the [Composition catalog v2](./ai/component-catalog-v2.json) to
|
|
32
|
+
mechanically evaluate parents, contexts, zones/cardinality, children, state,
|
|
33
|
+
wiring, responsive/layout/accessibility rules, and public boundaries. V1
|
|
34
|
+
remains compatible; v2 joins catalogs by `package:id`. Consumer v2 catalogs
|
|
35
|
+
use [the v2 extension schema](./ai/component-catalog-extension-v2.schema.json).
|
|
36
|
+
Load [compile-time contracts](./ai/compile-time-contracts-v1.json) for stable
|
|
37
|
+
`KUI-T###` ids, exact declaration symbols, and the boundary between rejected
|
|
38
|
+
source states and relationships that still require runtime/catalog checks.
|
|
39
|
+
Before generating application UI, discover `.kerf-ui-profile.json` with the
|
|
40
|
+
shipped [application profile API](./ai/application-ui-profile.mjs). Merge
|
|
41
|
+
package defaults, workspace policy, then parent-to-child directory policy;
|
|
42
|
+
honor its package-qualified preferences, approved theme/density, semantic
|
|
43
|
+
tokens, layout conventions, and narrow source-located exceptions. Validation
|
|
44
|
+
is catalog-aware per layer, including parent values later overridden by a
|
|
45
|
+
child; synchronous hosts use [application-ui-profile-sync.cjs](./ai/application-ui-profile-sync.cjs).
|
|
46
|
+
See the
|
|
47
|
+
[workspace profile example](./docs/examples/application-ui-profile.json).
|
|
48
|
+
A zone's optional `jsx.prop` is its only authoritative JSX binding; never
|
|
49
|
+
infer one from the zone id. Use `children` for one homogeneous primary
|
|
50
|
+
region and explicit named content prop slots for semantic positions or
|
|
51
|
+
replacement content. These slots use the recursive `KerfUiContent` type:
|
|
52
|
+
`SafeHtml`, runtime-empty boolean/nullish values, and readonly nested arrays.
|
|
53
|
+
Put conditionals and mapped component arrays directly in them; do not add a
|
|
54
|
+
`Fragment` only to satisfy types. Arbitrary strings, numbers, and signals are
|
|
55
|
+
rejected unless a component explicitly exposes a text position such as
|
|
56
|
+
`ListInsetText`. These are typed props, not native `<slot>` elements,
|
|
57
|
+
wrapper slot components, or a generic `slots` object. Leave unresolved
|
|
58
|
+
dynamic expressions unknown.
|
|
59
|
+
4. **When authoring a component gallery**, load
|
|
60
|
+
[catalog-authoring.json](./ai/catalog-authoring.json), then follow its
|
|
61
|
+
authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract).
|
|
62
|
+
5. **Apply the rules below and in** [skill.md](./ai/skill.md).
|
|
63
|
+
6. **Before calling an integration complete**, run
|
|
64
|
+
[`kerf-ui-doctor`](./docs/ui-doctor.md). Its portable JSON report merges
|
|
65
|
+
profile/catalog, TypeScript, Kerf ESLint, and static analyzer diagnostics;
|
|
66
|
+
CSS-adjacent component props are checked from catalog `cssValueProps`, so
|
|
67
|
+
prefer its canonical shorthand or typed helper over raw CSS strings;
|
|
68
|
+
repair source-located errors until exit 0. Use full mode for release gates;
|
|
69
|
+
generated `dist`/`coverage`, dependency, cache, evidence, and nested-worktree
|
|
70
|
+
directories are excluded consistently from every static stage.
|
|
71
|
+
[`kerf-ui-analyze`](./docs/ui-analyzer.md) remains available when only static
|
|
72
|
+
layout diagnostics are wanted; its review findings are a bounded human/AI
|
|
73
|
+
review queue rather than an objective aesthetic score.
|
|
74
|
+
7. **Evaluate the running application** by explicitly enabling the doctor's
|
|
75
|
+
browser stage or directly invoking
|
|
76
|
+
[`kerf-ui-evaluate`](./docs/ui-evaluator.md). Preserve its `KUI-B###`
|
|
77
|
+
browser evidence and screenshots; record hierarchy/rhythm/density/aesthetic
|
|
78
|
+
ratings separately with a named reviewer rather than presenting them as
|
|
79
|
+
objective assertions.
|
|
24
80
|
|
|
25
|
-
|
|
81
|
+
## Core rules (do the right thing)
|
|
26
82
|
|
|
27
|
-
|
|
83
|
+
- **Reach for the primitive, not for CSS.** The package is built to look right
|
|
84
|
+
_unstyled_. Before adding `padding`, `margin`, `width`, `height`, `border`,
|
|
85
|
+
`background`, a wrapper card, or a decoration, check whether the component, the
|
|
86
|
+
pane, or the content-item already owns it — it almost always does. Prefer a
|
|
87
|
+
component prop or a `--kui-*` token; write CSS only for genuinely new structure,
|
|
88
|
+
and then only join a component's documented `publicClasses` (never reach in by
|
|
89
|
+
tag/id/attribute or an unlisted class).
|
|
90
|
+
- **Never double-inset.** A `.kui-pane` has no padding; its `.kui-content` children
|
|
91
|
+
own the geometry (8px inline margin + 1px border + 8px padding). Do not add a
|
|
92
|
+
container padding on top of a content-item's own margin — pick one owner. Use
|
|
93
|
+
`.kui-content` for 24px major vertical rhythm.
|
|
94
|
+
- **Use `Row` for horizontal and `List` for vertical layout.** Both expose
|
|
95
|
+
physical `hAlign`/`vAlign` props and typed gaps. Row defaults to left/full,
|
|
96
|
+
an `xs` gap, and no wrapping; List retains full/top and zero-gap defaults.
|
|
97
|
+
Use canonical physical `textInsets` or `controlInsets` sides in
|
|
98
|
+
`t`/`r`/`b`/`l` order; text geometry wins on overlapping sides.
|
|
99
|
+
`ListInsetText` and `ListInsetControl` inset every side by default and accept
|
|
100
|
+
the same `sides` grammar for selective edges.
|
|
101
|
+
List additionally supplies
|
|
102
|
+
optional typed `gap`, `flex`, vertical scrolling, and canonical
|
|
103
|
+
`dividerSides` (`t`/`r`/`b`/`l` order). It adds no list semantics; children own
|
|
104
|
+
those, and only one bounded region should own scrolling. Pass a finite spacing
|
|
105
|
+
shorthand (`gap="xs"`, `gap="m"`) or a complete `CssLength` from the CSS-free
|
|
106
|
+
`@kerfjs/ui/css-values` builders; raw CSS strings are rejected. Use `flex()`
|
|
107
|
+
for List flex, typed lengths for Skeleton geometry, and
|
|
108
|
+
`uiColor()`/`colorVar()` for choice-icon colors. These brands are intentionally
|
|
109
|
+
not interchangeable; rows use classes/tokens/props rather than raw `style`.
|
|
110
|
+
- **Keep Web Awesome on the shared inset tiers.** `webawesome.css` uses
|
|
111
|
+
`--kui-wa-control-inset` (8px controls/items) and
|
|
112
|
+
`--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside
|
|
113
|
+
Accordion, Card, Details, Callout, and Include), while
|
|
114
|
+
`--kui-wa-container-inset` keeps Tab Panel at 16px. Dialog body and footer use
|
|
115
|
+
the surface (8px) and container (16px) tiers respectively, independent of the
|
|
116
|
+
dialog's shared `--spacing`. Override the tier at the narrowest useful scope
|
|
117
|
+
instead of restyling individual shadow parts.
|
|
118
|
+
When a dialog provides another dismissal affordance, add `hide-actions` to
|
|
119
|
+
the `wa-dialog` host; the theme hides its directly exported `header-actions`
|
|
120
|
+
part without an unsupported chained `::part()` selector.
|
|
121
|
+
Checkbox and Radio Group option regions also receive the shared 8px inline
|
|
122
|
+
outer inset because those groups have no bordered field shell. The Color
|
|
123
|
+
Picker trigger receives the same inset for the same unbordered geometry.
|
|
124
|
+
Slider's complete interactive region uses the shared 8px logical inline outer
|
|
125
|
+
inset without shifting its already-aligned label.
|
|
126
|
+
Known Date's Month/Day/Year captions and bordered text-like field hints align
|
|
127
|
+
with field values at the shared 9px border-plus-padding inset. OTP Input's
|
|
128
|
+
label uses the same uppercase xs/650 treatment and its label and hint share
|
|
129
|
+
that 9px alignment.
|
|
130
|
+
- `Select` requires a visible `label` or an `ariaLabel` for a visually hidden
|
|
131
|
+
accessible name. The package names the internal combobox, including custom
|
|
132
|
+
selected content; consumers do not need shadow-DOM naming workarounds.
|
|
133
|
+
Import `select/register` once for the canonical animation lifecycle: stale
|
|
134
|
+
close/show completions cannot override a later request. Consumers must not
|
|
135
|
+
repair popup timing or anchor placement; raw Web Awesome selects stay native.
|
|
136
|
+
Use `hint` for supporting text below the control and `placeholderText` only
|
|
137
|
+
for the empty value inside it; loading placeholders retain the visible hint.
|
|
138
|
+
- **Trust the defaults.** Render a control at its natural size and color (a
|
|
139
|
+
`LucideIcon` is 24px); if it looks wrong, fix the surrounding layout, not the
|
|
140
|
+
control. Never force a component's width/height to size it — that leaves a halo
|
|
141
|
+
or a stretched oval.
|
|
142
|
+
- **Toolbars hold only `ToolbarText` and `ToolbarControlGroup`.** Never put a bare
|
|
143
|
+
button, input, link, or loose markup in a `leading`/`center`/`trailing` zone.
|
|
144
|
+
Wrap every control — `SegmentedControl`, `Select`, a collapsible
|
|
145
|
+
`TokenSearchField`, Web Awesome controls — inside a `ToolbarControlGroup`. For an
|
|
146
|
+
ordinary icon/action control inside the group use a **plain `<button>`** (the
|
|
147
|
+
group styles it fully) — that is the default; reach for `wa-button` only when you
|
|
148
|
+
need a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
|
|
149
|
+
popup menu. A toolbar popup menu is a `single` `ToolbarControlGroup` around a
|
|
150
|
+
`wa-dropdown` (its `slot="trigger"` `wa-button` is the toolbar button, kept under
|
|
151
|
+
`data-morph-skip-children`). Compact mixed groups keep standard item padding
|
|
152
|
+
and raised selected chrome without an internal separator; the selected item
|
|
153
|
+
paints over the outer border. For an avatar control, set `content="avatar"` and
|
|
154
|
+
`avatarImage` on the group instead of inserting an `img`; a lone control paints
|
|
155
|
+
the group and a multi-button group paints only its pressed highlight.
|
|
156
|
+
- **Use one direct toolbar composition for panel/dialog/page headings.** Put an
|
|
157
|
+
optional icon in a `ToolbarControlGroup`, an extra-large `ToolbarText` directly
|
|
158
|
+
in the leading zone, and actions in a trailing group. Supporting copy is
|
|
159
|
+
app-owned content below. Do not create a private heading wrapper or restyle the
|
|
160
|
+
toolbar.
|
|
161
|
+
- **Use `Text` for ordinary semantic headings and paragraphs outside toolbar
|
|
162
|
+
title zones.** Pass a required `h1`–`h6` or `p` variant based on document
|
|
163
|
+
meaning. It passes native attributes through and owns the standard transparent
|
|
164
|
+
border plus item padding; keep toolbar titles on `ToolbarText` and list-aligned
|
|
165
|
+
bare prose on `ListInsetText`.
|
|
166
|
+
- **Space by the five-step scale, by relationship not by eye.** `0`
|
|
167
|
+
`--kui-space-none`, `4px` `--kui-space-2xs`, `8px` `--kui-space-xs` (inside a
|
|
168
|
+
group), `16px` `--kui-space-m`, `24px` `--kui-space-l` (between major differing
|
|
169
|
+
regions). 12px/32px are off-scale exceptions. Prefer direct `Row.gap`/`List.gap`
|
|
170
|
+
shorthands for repeated rhythm; use `Spacer` for one typed empty width/height
|
|
171
|
+
or flexible main-axis gap. Use `space`, `px`, `rem`, `em`, `pct`, `lengthVar`, and
|
|
172
|
+
`calc(plus(...))` for typed runtime composition. `remify()` is source-CSS only.
|
|
173
|
+
- **Keep nested highlight corners concentric.** Inset hover and selection surfaces
|
|
174
|
+
follow the owning control's pill or rounded shape; their radius is the outer
|
|
175
|
+
radius minus `--kui-layout-highlight-inset`. Do not give an inner highlight an
|
|
176
|
+
unrelated radius.
|
|
177
|
+
- **Panes share one child-owned geometry.** Sidebars, main areas, inspectors, and
|
|
178
|
+
dialogs all use an unpadded `.kui-pane` (optional `.kui-pane__toolbar`, one
|
|
179
|
+
scrolling `.kui-pane__content`, optional `.kui-pane__footer`). A visible pane owns
|
|
180
|
+
its collapse control; a hidden pane's restore moves to the adjacent main
|
|
181
|
+
toolbar's matching edge — no icon-only rail. Keep one scroll owner per region.
|
|
182
|
+
- **State and behavior live in the app.** Components take semantic `data-action`
|
|
183
|
+
strings and controlled values; wire them once with `delegate()`/`delegateActions()`
|
|
184
|
+
or the disposer-returning `wire…` helpers, and own domain copy, transport, and
|
|
185
|
+
policy in a thin adapter. Every element must earn its place — cut chrome, labels,
|
|
186
|
+
and readouts that do not help a person decide or act.
|
|
187
|
+
- **App state is domain/persisted; helpers own only ephemeral mechanics.** Keep
|
|
188
|
+
navigation stacks, tab selection and order, pane sizes, and `collapsed`/`expanded`
|
|
189
|
+
disclosure flags in the app — they are data or persisted layout, and the app reads
|
|
190
|
+
them to render. The `wire…` helpers own the _ephemeral_ parts: `wireNavStack` the
|
|
191
|
+
content-slide, per-view top/bottom chrome cross-fade, and focus move/restore
|
|
192
|
+
(mark a preferred new-view target with `data-nav-focus`), `wireTabBars` the
|
|
193
|
+
overflow autoscroll, drag preview, and
|
|
194
|
+
replacement focus after controlled automatic tab activation,
|
|
195
|
+
`wireResizableRegions` the live drag preview; they report committed changes via
|
|
196
|
+
callbacks. Managed TokenSearchField clear also preserves open state and replacement
|
|
197
|
+
editor focus before the next input task, so shortcut-letter typing stays in search.
|
|
198
|
+
Select All deletion does the same; deletion
|
|
199
|
+
restoration finishes before the next keystroke rather than on a delayed frame.
|
|
200
|
+
Persist both query and remaining tokens read from an edited field. The one richer case is `wireTokenSearchFields`, which manages the
|
|
201
|
+
collapsible field's expand/collapse/focus by default (on, per-behavior opt-out) and
|
|
202
|
+
exposes the `expanded` signal on its handle — bind it in render or hand in your own
|
|
203
|
+
via `collapsible.signals`. Do not hand-roll open/collapse/focus that helper
|
|
204
|
+
provides; but do keep a plain disclosure toggle (a one-line boolean the app already
|
|
205
|
+
renders from) in the app. For real-app composition it also offers a focusout
|
|
206
|
+
keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn`,
|
|
207
|
+
so a sibling suggestions/date popover does not collapse an empty field), opt-in
|
|
208
|
+
atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via
|
|
209
|
+
`onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an
|
|
210
|
+
`onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — so the app can drop its own keydown/input
|
|
211
|
+
boilerplate while still owning parsing and controlled token state.
|
|
212
|
+
- **Placeholder loading state, don't rebuild it.** For a value or component that is
|
|
213
|
+
still loading, set `placeholder` on the component (`Select`, `ListHeader`,
|
|
214
|
+
`ListItem`, `ValueTableRow`, `SegmentedControl`, `StateBanner`,
|
|
215
|
+
`AppTab`, `ToolbarText`, `ListActionRow`): it renders its real chrome with value
|
|
216
|
+
slots as subtle **unanimated** skeleton blocks and interactivity disabled, so a
|
|
217
|
+
parent composes a faithful loading view (e.g. an inspector) without hand-rebuilding
|
|
218
|
+
markup. Use the standalone `Skeleton` for a custom slot. Prefer it over `wa-skeleton`
|
|
219
|
+
(the pure-Kerf primitives avoid Web Awesome), and never animate it — use
|
|
220
|
+
`LoadingSpinner` for known busy activity instead.
|
|
221
|
+
- **Keep ListItem content inside the row.** The rounded `ListItem` root clips
|
|
222
|
+
overflowing label, status, and dormant trailing content. Set `multiline` when
|
|
223
|
+
the primary label should wrap; use `ListActionRow` instead when trailing content
|
|
224
|
+
must be interactive.
|
|
225
|
+
- **Dialog bodies are lists by default.** Compose rows and sections in `List`,
|
|
226
|
+
use `DialogSurface bodyInset="none"` when those children own their geometry,
|
|
227
|
+
and wrap bare prose in `ListInsetText` so it shares the standard list gutter
|
|
228
|
+
without stacking a second body inset.
|
|
229
|
+
- **Use a StateBanner badge only for compact supporting status.** Pass the
|
|
230
|
+
optional string `badge` for a terse count or status beside the title. It
|
|
231
|
+
inherits the banner tone and is announced with the banner, so keep its text
|
|
232
|
+
meaningful and never rely on color alone.
|
|
28
233
|
|
|
29
|
-
|
|
234
|
+
## Public exports
|
|
30
235
|
|
|
31
|
-
|
|
236
|
+
`LucideIcon`, `DisclosureArrow`, `Toolbar`, `ToolbarControlGroup`, `FloatingToolbar`, `ToolbarText`, `Text`,
|
|
237
|
+
`ListItem`, `ListActionRow`, `ListHeader`, `ListInsetControl`,
|
|
238
|
+
`ListInsetText`, `SegmentedControl`,
|
|
239
|
+
`Select`, `TokenSearchField` (+ `readTokenSearchField`, `placeTokenSearchCaret`,
|
|
240
|
+
`wireTokenSearchFields`), `AppTab`, `TabBar` (+ `wireTabBars`, `reorderTabs`),
|
|
241
|
+
`ResizableRegion` (+ `wireResizableRegions`), `StateBanner`, `EmptyState`,
|
|
242
|
+
`LoadingSpinner`, `Skeleton`, `ValueTable`, `ValueTableRow`. Whole-screen layouts (opt-in,
|
|
243
|
+
tree-shakeable, declarative with `wire…` helpers, each with a companion CSS import):
|
|
244
|
+
`NavStack`, `SplitView`, `Workbench`, `TabScaffold`, driven by `deviceClass()` from
|
|
245
|
+
`@kerfjs/ui/device-class`. For a standalone collapsible rail/drawer outside a full
|
|
246
|
+
shell, `@kerfjs/ui/collapsible-panel` (`CollapsiblePanel`, `CollapsiblePanelToggle`)
|
|
32
247
|
|
|
33
|
-
`
|
|
248
|
+
- `@kerfjs/ui/wire-sidebar` (`wireSidebar`: toggle, focus, compact overlay, persistence).
|
|
249
|
+
`@kerfjs/ui/catalog` is another opt-in shell — a
|
|
250
|
+
`Catalog` component + `wireCatalog` helper for building a component-gallery catalog
|
|
251
|
+
(collapsible category sidebar + preview stage + resources footer, with an opt-in
|
|
252
|
+
transparent-bound and margin geometry overlay plus focus-preserving active-row
|
|
253
|
+
reveal for long desktop sidebars) from your own
|
|
254
|
+
entries; controlled/stateless like the layouts. For any Catalog demo, follow
|
|
255
|
+
the [authoritative authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
|
|
256
|
+
rather than inferring structure from the shell or private CSS.
|
|
257
|
+
`@kerfjs/ui/webawesome` is a
|
|
258
|
+
type-only boundary for `wa-*` JSX; `@kerfjs/ui/select/register` and the CSS are the
|
|
259
|
+
declared side effects.
|
|
34
260
|
|
|
35
|
-
|
|
261
|
+
## Reference
|
|
36
262
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
263
|
+
- [skill.md](./ai/skill.md): the full rule set + a common-mistakes table (the shipped AI skill).
|
|
264
|
+
- [design-philosophy.md](./docs/design-philosophy.md): why kerf UI is shaped this way — the decision principles behind the rules above.
|
|
265
|
+
- [layout.md](./docs/layout.md): the pane/content-item geometry, public roles/tokens, and the spacing scale.
|
|
266
|
+
- [component-contract.md](./docs/component-contract.md): what a component owns vs. what the app owns.
|
|
267
|
+
- [accessibility.md](./docs/accessibility.md): keyboard and ARIA contracts per component.
|
|
268
|
+
- [recipes.md](./docs/recipes.md): production compositions (app shell, list-detail dialog, composer form, …) as copyable references.
|
|
269
|
+
- [app-layouts.md](./docs/app-layouts.md): choosing `NavStack`/`SplitView`/`Workbench`/`TabScaffold` by data + interaction + device, and dialog presentation.
|
|
270
|
+
- [webawesome-theme.md](./docs/webawesome-theme.md): the optional Web Awesome theme; catalog coverage means themed-and-supported, not preferred (prefer the Kerf primitive when one exists). The UX sidebar visibly tags superseded and exceptional Web Awesome choices as `Discouraged`; Popup remains an available conditional positioning primitive.
|
|
271
|
+
- [component-catalog.json](./ai/component-catalog.json) + [component-catalog-extension.schema.json](./ai/component-catalog-extension.schema.json) + [catalog-authoring.json](./ai/catalog-authoring.json) + [public-api-signatures-v1.md](./ai/public-api-signatures-v1.md) + [webawesome-jsx-signatures-v1.md](./ai/webawesome-jsx-signatures-v1.md): machine-readable selection facts, a reusable app-component extension contract, Catalog authoring discovery, and exact signatures.
|
|
272
|
+
- [compile-time-contracts-v1.json](./ai/compile-time-contracts-v1.json) + [type-contracts.md](./docs/type-contracts.md): stable compile diagnostics, packed-declaration proof, migrations, and explicit non-goals.
|
|
273
|
+
- [README.md](./README.md): package overview and the component subpath table.
|