@kerfjs/ui 5.0.0-beta.104 → 5.0.0-beta.105
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 +155 -116
- package/ai/application-ui-profile.defaults.json +125 -4
- package/ai/compile-time-contracts-v1.json +11 -11
- package/ai/component-catalog.json +2606 -628
- package/ai/component-composition-rules.json +10 -10
- package/ai/component-composition.json +1688 -300
- package/ai/components/README.md +66 -48
- package/ai/components/application-tabs.md +4 -4
- package/ai/components/badge.md +1 -0
- package/ai/components/button.md +91 -0
- package/ai/components/checkbox.md +89 -0
- package/ai/components/choice-chips.md +9 -3
- package/ai/components/color-field.md +92 -0
- package/ai/components/color-picker.md +90 -0
- package/ai/components/color-swatches.md +82 -0
- package/ai/components/combobox.md +6 -4
- package/ai/components/content-item.md +5 -2
- package/ai/components/disclosure.md +83 -0
- package/ai/components/file-picker.md +1 -0
- package/ai/components/foundation.md +1 -1
- package/ai/components/list-action-row.md +3 -3
- package/ai/components/list-detail-dialog.md +90 -0
- package/ai/components/list.md +2 -0
- package/ai/components/lucide-icon.md +2 -0
- package/ai/components/{composer.md → message-composer.md} +17 -16
- package/ai/components/pane.md +3 -1
- package/ai/components/popup-menu.md +12 -9
- package/ai/components/progress-bar.md +82 -0
- package/ai/components/progress-ring.md +80 -0
- package/ai/components/radio-group.md +88 -0
- package/ai/components/recipe-list-detail-dialog.md +5 -5
- package/ai/components/{token-search-field.md → search-field.md} +23 -23
- package/ai/components/select.md +15 -13
- package/ai/components/slider.md +84 -0
- package/ai/components/surface-scaffold.md +16 -13
- package/ai/components/switch.md +81 -0
- package/ai/components/tab-bar.md +6 -6
- package/ai/components/tab-navigator.md +2 -2
- package/ai/components/tabs.md +7 -7
- package/ai/components/tag-field.md +86 -0
- package/ai/components/text-field.md +98 -0
- package/ai/components/text.md +1 -0
- package/ai/components/toast.md +85 -0
- package/ai/components/toolbar-control-group.md +3 -3
- package/ai/components/tooltip.md +81 -0
- package/ai/components/wa-accordion-item.md +11 -5
- package/ai/components/wa-accordion.md +11 -5
- package/ai/components/wa-animated-image.md +2 -1
- package/ai/components/wa-animation.md +1 -0
- package/ai/components/wa-avatar.md +1 -0
- package/ai/components/wa-badge.md +10 -3
- package/ai/components/wa-breadcrumb-item.md +1 -0
- package/ai/components/wa-breadcrumb.md +1 -0
- package/ai/components/wa-button-group.md +6 -4
- package/ai/components/wa-button.md +7 -5
- package/ai/components/wa-callout.md +7 -5
- package/ai/components/wa-card.md +12 -4
- package/ai/components/wa-carousel-item.md +1 -0
- package/ai/components/wa-carousel.md +1 -0
- package/ai/components/wa-checkbox-group.md +11 -4
- package/ai/components/wa-checkbox.md +10 -4
- package/ai/components/wa-color-picker.md +13 -5
- package/ai/components/wa-comparison.md +2 -1
- package/ai/components/wa-copy-button.md +1 -0
- package/ai/components/wa-details.md +11 -5
- package/ai/components/wa-dialog.md +10 -4
- package/ai/components/wa-divider.md +1 -0
- package/ai/components/wa-drawer.md +12 -5
- package/ai/components/wa-dropdown-item.md +8 -6
- package/ai/components/wa-dropdown.md +8 -6
- package/ai/components/wa-format-bytes.md +1 -0
- package/ai/components/wa-format-date.md +1 -0
- package/ai/components/wa-format-number.md +1 -0
- package/ai/components/wa-icon.md +2 -1
- package/ai/components/wa-include.md +6 -4
- package/ai/components/wa-input.md +9 -6
- package/ai/components/wa-intersection-observer.md +1 -0
- package/ai/components/wa-known-date.md +1 -0
- package/ai/components/wa-markdown.md +1 -0
- package/ai/components/wa-mutation-observer.md +1 -0
- package/ai/components/wa-number-input.md +1 -0
- package/ai/components/wa-option.md +7 -5
- package/ai/components/wa-otp-input.md +1 -0
- package/ai/components/wa-page.md +13 -4
- package/ai/components/wa-pagination.md +1 -0
- package/ai/components/wa-popover.md +11 -5
- package/ai/components/wa-popup.md +11 -4
- package/ai/components/wa-progress-bar.md +11 -4
- package/ai/components/wa-progress-ring.md +11 -4
- package/ai/components/wa-qr-code.md +1 -0
- package/ai/components/wa-radio-group.md +12 -4
- package/ai/components/wa-radio.md +10 -4
- package/ai/components/wa-random-content.md +1 -0
- package/ai/components/wa-rating.md +1 -0
- package/ai/components/wa-relative-time.md +1 -0
- package/ai/components/wa-resize-observer.md +1 -0
- package/ai/components/wa-scroller.md +12 -4
- package/ai/components/wa-select.md +7 -5
- package/ai/components/wa-skeleton.md +10 -3
- package/ai/components/wa-slider.md +11 -5
- package/ai/components/wa-spinner.md +7 -5
- package/ai/components/wa-split-panel.md +7 -5
- package/ai/components/wa-step.md +56 -0
- package/ai/components/wa-stepper.md +56 -0
- package/ai/components/wa-switch.md +10 -3
- package/ai/components/wa-tab-group.md +8 -6
- package/ai/components/wa-tab-panel.md +7 -5
- package/ai/components/wa-tab.md +8 -6
- package/ai/components/wa-tag-input.md +62 -0
- package/ai/components/wa-tag.md +9 -6
- package/ai/components/wa-textarea.md +10 -3
- package/ai/components/wa-time-input.md +1 -0
- package/ai/components/wa-toast-item.md +9 -7
- package/ai/components/wa-toast.md +9 -7
- package/ai/components/wa-tooltip.md +11 -5
- package/ai/components/wa-tree-item.md +2 -1
- package/ai/components/wa-tree.md +2 -1
- package/ai/components/wa-zoomable-frame.md +2 -1
- package/ai/components/workbench-dialog.md +90 -0
- package/ai/public-api-signatures-v1.md +1577 -245
- package/ai/skill.md +83 -50
- package/ai/webawesome-jsx-signatures-v1.md +4 -1
- package/dist/badge.d.ts +9 -1
- package/dist/badge.js +1 -1
- package/dist/browser/button.js +5 -0
- package/dist/browser/catalog.js +3 -2
- package/dist/browser/{icon-button.js → checkbox.js} +2 -2
- package/dist/browser/color-field.js +4 -0
- package/dist/browser/color-picker.js +5 -0
- package/dist/browser/color-swatches.js +3 -0
- package/dist/browser/disclosure.js +5 -0
- package/dist/browser/list-action-row.js +1 -0
- package/dist/browser/list-detail-dialog.js +14 -0
- package/dist/browser/message-composer.js +5 -0
- package/dist/browser/popup-menu.js +1 -0
- package/dist/browser/progress-bar.js +3 -0
- package/dist/browser/progress-ring.js +3 -0
- package/dist/browser/radio-group.js +3 -0
- package/dist/browser/search-field.js +4 -0
- package/dist/browser/slider.js +3 -0
- package/dist/browser/surface-scaffold.js +1 -0
- package/dist/browser/switch.js +3 -0
- package/dist/browser/tab-bar-item.js +4 -0
- package/dist/browser/tag-field.js +5 -0
- package/dist/browser/text-field.js +4 -0
- package/dist/browser/workbench-dialog.js +15 -0
- package/dist/button.d.ts +108 -0
- package/dist/button.js +7 -0
- package/dist/button.js.map +1 -0
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +3 -3
- package/dist/catalog.js +57 -27
- package/dist/catalog.js.map +1 -1
- package/dist/checkbox.d.ts +45 -0
- package/dist/checkbox.js +6 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/choice-chips.d.ts +49 -15
- package/dist/choice-chips.js +1 -1
- package/dist/chunk-23PPPNH6.js +93 -0
- package/dist/chunk-23PPPNH6.js.map +1 -0
- package/dist/{chunk-FNZQOUZ5.js → chunk-2FW7D4IG.js} +2 -2
- package/dist/{chunk-FNZQOUZ5.js.map → chunk-2FW7D4IG.js.map} +1 -1
- package/dist/{chunk-ZYU5WRC3.js → chunk-3GLYIIFR.js} +2 -2
- package/dist/{chunk-ZYU5WRC3.js.map → chunk-3GLYIIFR.js.map} +1 -1
- package/dist/{chunk-5NQF35VO.js → chunk-4RECPEHI.js} +2 -2
- package/dist/{chunk-5NQF35VO.js.map → chunk-4RECPEHI.js.map} +1 -1
- package/dist/{chunk-7IUEBNCO.js → chunk-5USKCWGL.js} +8 -3
- package/dist/chunk-5USKCWGL.js.map +1 -0
- package/dist/chunk-6VVIW7VB.js +69 -0
- package/dist/chunk-6VVIW7VB.js.map +1 -0
- package/dist/{chunk-LL45C7BB.js → chunk-7K6U6FCN.js} +1 -1
- package/dist/chunk-7K6U6FCN.js.map +1 -0
- package/dist/{chunk-HQZYKJ56.js → chunk-7W3GKMN4.js} +110 -74
- package/dist/chunk-7W3GKMN4.js.map +1 -0
- package/dist/chunk-ACUKTVS3.js +371 -0
- package/dist/chunk-ACUKTVS3.js.map +1 -0
- package/dist/{chunk-YQ2AC4E2.js → chunk-AMIHGFLP.js} +2 -2
- package/dist/{chunk-YQ2AC4E2.js.map → chunk-AMIHGFLP.js.map} +1 -1
- package/dist/chunk-ATGAJVZ6.js +268 -0
- package/dist/chunk-ATGAJVZ6.js.map +1 -0
- package/dist/chunk-AYPGXR2E.js +20 -0
- package/dist/chunk-AYPGXR2E.js.map +1 -0
- package/dist/{chunk-ETCWQLJV.js → chunk-BKUMG2KB.js} +38 -28
- package/dist/chunk-BKUMG2KB.js.map +1 -0
- package/dist/chunk-C26Q6P4Q.js +76 -0
- package/dist/chunk-C26Q6P4Q.js.map +1 -0
- package/dist/chunk-C3RLKKFQ.js +452 -0
- package/dist/chunk-C3RLKKFQ.js.map +1 -0
- package/dist/{chunk-T5BJBMW7.js → chunk-CIAUILRR.js} +5 -5
- package/dist/chunk-CIAUILRR.js.map +1 -0
- package/dist/chunk-CNM6ZWP2.js +38 -0
- package/dist/chunk-CNM6ZWP2.js.map +1 -0
- package/dist/{chunk-LPHU44S3.js → chunk-CTQUDCY5.js} +3 -1
- package/dist/chunk-CTQUDCY5.js.map +1 -0
- package/dist/{chunk-MXNIVEVL.js → chunk-D4MXSAMI.js} +5 -3
- package/dist/chunk-D4MXSAMI.js.map +1 -0
- package/dist/{chunk-YBWQR2OK.js → chunk-DDSCVEO5.js} +10 -9
- package/dist/chunk-DDSCVEO5.js.map +1 -0
- package/dist/{chunk-SIW64V65.js → chunk-DF2YKGIX.js} +3 -3
- package/dist/{chunk-SIW64V65.js.map → chunk-DF2YKGIX.js.map} +1 -1
- package/dist/{chunk-3SKAEPPZ.js → chunk-ECFCAKWE.js} +4 -4
- package/dist/{chunk-3SKAEPPZ.js.map → chunk-ECFCAKWE.js.map} +1 -1
- package/dist/chunk-EKBMUXFV.js +298 -0
- package/dist/chunk-EKBMUXFV.js.map +1 -0
- package/dist/{chunk-IXLUZHGT.js → chunk-FG6U7KQQ.js} +5 -5
- package/dist/{chunk-IXLUZHGT.js.map → chunk-FG6U7KQQ.js.map} +1 -1
- package/dist/chunk-FKKJHGN5.js +147 -0
- package/dist/chunk-FKKJHGN5.js.map +1 -0
- package/dist/{chunk-FDZNYD4C.js → chunk-GCAK23PU.js} +34 -3
- package/dist/chunk-GCAK23PU.js.map +1 -0
- package/dist/chunk-GXSX6Q6O.js +42 -0
- package/dist/chunk-GXSX6Q6O.js.map +1 -0
- package/dist/{chunk-LOSRXZAH.js → chunk-HJXVVFBT.js} +14 -6
- package/dist/chunk-HJXVVFBT.js.map +1 -0
- package/dist/{chunk-M5KZ26VV.js → chunk-HQZG3OFL.js} +11 -1
- package/dist/chunk-HQZG3OFL.js.map +1 -0
- package/dist/{chunk-ELCMSQNJ.js → chunk-HTERKONR.js} +8 -8
- package/dist/chunk-HTERKONR.js.map +1 -0
- package/dist/chunk-HYORKKYP.js +8 -0
- package/dist/chunk-HYORKKYP.js.map +1 -0
- package/dist/chunk-IO27YTL3.js +73 -0
- package/dist/chunk-IO27YTL3.js.map +1 -0
- package/dist/chunk-ITUQC4FW.js +163 -0
- package/dist/chunk-ITUQC4FW.js.map +1 -0
- package/dist/chunk-K57NINLH.js +137 -0
- package/dist/chunk-K57NINLH.js.map +1 -0
- package/dist/chunk-KC6WUSNS.js +34 -0
- package/dist/chunk-KC6WUSNS.js.map +1 -0
- package/dist/{chunk-W4IK7AWD.js → chunk-KDQZ3E5C.js} +3 -1
- package/dist/chunk-KDQZ3E5C.js.map +1 -0
- package/dist/{chunk-2MSPNRWJ.js → chunk-KK3S5OTW.js} +27 -11
- package/dist/chunk-KK3S5OTW.js.map +1 -0
- package/dist/chunk-LTBVP6VN.js +59 -0
- package/dist/chunk-LTBVP6VN.js.map +1 -0
- package/dist/chunk-OHPYT2BH.js +82 -0
- package/dist/chunk-OHPYT2BH.js.map +1 -0
- package/dist/{chunk-HZPHCSCS.js → chunk-OY2MXIBB.js} +8 -2
- package/dist/chunk-OY2MXIBB.js.map +1 -0
- package/dist/chunk-PE2KPZDW.js +85 -0
- package/dist/chunk-PE2KPZDW.js.map +1 -0
- package/dist/{chunk-QTSMHH5J.js → chunk-QPTJ5DOO.js} +5 -3
- package/dist/chunk-QPTJ5DOO.js.map +1 -0
- package/dist/{chunk-JOR5LGYE.js → chunk-RFLW4FPL.js} +1 -1
- package/dist/chunk-RFLW4FPL.js.map +1 -0
- package/dist/{chunk-U6QYTMDB.js → chunk-RMWNO6BA.js} +6 -2
- package/dist/chunk-RMWNO6BA.js.map +1 -0
- package/dist/{chunk-TDMHA7C3.js → chunk-SQ2Q3OQI.js} +112 -63
- package/dist/chunk-SQ2Q3OQI.js.map +1 -0
- package/dist/{chunk-K4AT3V3J.js → chunk-T74YB76U.js} +13 -11
- package/dist/chunk-T74YB76U.js.map +1 -0
- package/dist/{chunk-BYFTHA4I.js → chunk-TAHR457X.js} +53 -6
- package/dist/chunk-TAHR457X.js.map +1 -0
- package/dist/{chunk-3VXDSIBJ.js → chunk-TKNVL53O.js} +2 -2
- package/dist/{chunk-3VXDSIBJ.js.map → chunk-TKNVL53O.js.map} +1 -1
- package/dist/chunk-TNJLNLVE.js +115 -0
- package/dist/chunk-TNJLNLVE.js.map +1 -0
- package/dist/chunk-TUID42UE.js +15 -0
- package/dist/chunk-TUID42UE.js.map +1 -0
- package/dist/{chunk-CR5U5FV6.js → chunk-UMNHJSIO.js} +93 -80
- package/dist/chunk-UMNHJSIO.js.map +1 -0
- package/dist/chunk-UTCAOOXU.js +116 -0
- package/dist/chunk-UTCAOOXU.js.map +1 -0
- package/dist/{chunk-ZJC5ND3M.js → chunk-VEME3D7K.js} +35 -35
- package/dist/chunk-VEME3D7K.js.map +1 -0
- package/dist/{chunk-HLDRH23D.js → chunk-WJKHLOP5.js} +2 -2
- package/dist/{chunk-HLDRH23D.js.map → chunk-WJKHLOP5.js.map} +1 -1
- package/dist/chunk-WU57BYYM.js +115 -0
- package/dist/chunk-WU57BYYM.js.map +1 -0
- package/dist/{chunk-TGLUDQP2.js → chunk-ZCDRLN3B.js} +11 -11
- package/dist/chunk-ZCDRLN3B.js.map +1 -0
- package/dist/chunk-ZX2QQJXD.js +249 -0
- package/dist/chunk-ZX2QQJXD.js.map +1 -0
- package/dist/{chunk-6E2H2E5A.js → chunk-ZXZAECHZ.js} +6 -6
- package/dist/{chunk-6E2H2E5A.js.map → chunk-ZXZAECHZ.js.map} +1 -1
- package/dist/collapsible-panel.js +3 -3
- package/dist/color-field.d.ts +51 -0
- package/dist/color-field.js +92 -0
- package/dist/color-field.js.map +1 -0
- package/dist/color-picker.d.ts +88 -0
- package/dist/color-picker.js +8 -0
- package/dist/color-picker.js.map +1 -0
- package/dist/color-swatches.d.ts +56 -0
- package/dist/color-swatches.js +4 -0
- package/dist/color-swatches.js.map +1 -0
- package/dist/combobox.js +1 -1
- package/dist/content-item.d.ts +13 -1
- package/dist/content-item.js +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/disclosure.d.ts +57 -0
- package/dist/disclosure.js +51 -0
- package/dist/disclosure.js.map +1 -0
- package/dist/file-picker.d.ts +7 -0
- package/dist/file-picker.js +1 -1
- package/dist/help-tags-register.d.ts +8 -8
- package/dist/help-tags-register.js +3 -2
- package/dist/help-tags-register.js.map +1 -1
- package/dist/index.d.ts +16 -9
- package/dist/index.js +58 -46
- package/dist/list-action-row.js +4 -1
- package/dist/list-detail-dialog.d.ts +117 -0
- package/dist/list-detail-dialog.js +165 -0
- package/dist/list-detail-dialog.js.map +1 -0
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +17 -2
- package/dist/list.js +1 -1
- package/dist/lucide-icon.d.ts +9 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/{composer.d.ts → message-composer.d.ts} +20 -12
- package/dist/message-composer.js +6 -0
- package/dist/message-composer.js.map +1 -0
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +36 -3
- package/dist/pane.js +1 -1
- package/dist/popup-menu-register.d.ts +6 -5
- package/dist/popup-menu-register.js +3 -326
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.d.ts +41 -23
- package/dist/popup-menu.js +5 -1
- package/dist/progress-bar.d.ts +52 -0
- package/dist/progress-bar.js +68 -0
- package/dist/progress-bar.js.map +1 -0
- package/dist/progress-ring.d.ts +44 -0
- package/dist/progress-ring.js +73 -0
- package/dist/progress-ring.js.map +1 -0
- package/dist/radio-group.d.ts +62 -0
- package/dist/radio-group.js +4 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/row.js +1 -1
- package/dist/{token-search-model-JA1i8z4D.d.ts → search-field-CrGTN5sa.d.ts} +45 -45
- package/dist/search-field-model.d.ts +3 -0
- package/dist/search-field-model.js +3 -0
- package/dist/search-field-model.js.map +1 -0
- package/dist/search-field.d.ts +3 -0
- package/dist/search-field.js +5 -0
- package/dist/search-field.js.map +1 -0
- package/dist/select-register.d.ts +6 -3
- package/dist/select-register.js +383 -241
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +30 -6
- package/dist/select.js +3 -1
- package/dist/selection.d.ts +54 -0
- package/dist/selection.js +3 -0
- package/dist/selection.js.map +1 -0
- package/dist/slider.d.ts +74 -0
- package/dist/slider.js +103 -0
- package/dist/slider.js.map +1 -0
- package/dist/split-button.js +1 -1
- package/dist/split-view.d.ts +5 -2
- package/dist/split-view.js +18 -159
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/badge.css +18 -6
- package/dist/styles/button.css +230 -0
- package/dist/styles/catalog/components/catalog-example.css +13 -4
- package/dist/styles/checkbox.css +121 -0
- package/dist/styles/choice-chips.css +58 -7
- package/dist/styles/color-field.css +125 -0
- package/dist/styles/color-picker.css +331 -0
- package/dist/styles/color-swatches.css +122 -0
- package/dist/styles/combobox.css +7 -5
- package/dist/styles/components/actions/button/button.css +230 -0
- package/dist/styles/components/actions/popup-menu/popup-menu.css +326 -198
- package/dist/styles/components/actions/toolbar/toolbar.css +10 -3
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +67 -104
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +5 -18
- package/dist/styles/components/collections/list/list.css +37 -0
- package/dist/styles/components/feedback/badge/badge.css +18 -6
- package/dist/styles/components/feedback/progress-bar/progress-bar.css +168 -0
- package/dist/styles/components/feedback/progress-ring/progress-ring.css +91 -0
- package/dist/styles/components/feedback/state-banner/state-banner.css +18 -3
- package/dist/styles/components/forms/checkbox/checkbox.css +121 -0
- package/dist/styles/components/forms/choice-chips/choice-chips.css +58 -7
- package/dist/styles/components/forms/color-field/color-field.css +125 -0
- package/dist/styles/components/forms/color-picker/color-picker.css +331 -0
- package/dist/styles/components/forms/color-swatches/color-swatches.css +122 -0
- package/dist/styles/components/forms/combobox/combobox.css +7 -5
- package/dist/styles/components/forms/{composer/composer.css → message-composer/message-composer.css} +17 -33
- package/dist/styles/components/forms/radio-group/radio-group.css +156 -0
- package/dist/styles/{token-search-field.css → components/forms/search-field/search-field.css} +111 -102
- package/dist/styles/components/forms/select/select.css +370 -249
- package/dist/styles/components/forms/slider/slider.css +241 -0
- package/dist/styles/components/forms/switch/switch.css +132 -0
- package/dist/styles/components/forms/tag-field/tag-field.css +8 -0
- package/dist/styles/components/forms/text-field/text-field.css +193 -0
- package/dist/styles/components/layout/pane/pane.css +254 -0
- package/dist/styles/components/layout/resizable-region/resizable-region.css +3 -2
- package/dist/styles/components/layout/row/row.css +11 -0
- package/dist/styles/components/layout/split-view/split-view.css +25 -0
- package/dist/styles/components/layout/workbench/workbench.css +12 -4
- package/dist/styles/components/navigation/disclosure-arrow/disclosure-arrow.css +20 -0
- package/dist/styles/components/navigation/tab-bar/tab-bar.css +7 -7
- package/dist/styles/components/navigation/{app-tab/app-tab.css → tab-bar-item/tab-bar-item.css} +95 -90
- package/dist/styles/components/surfaces/disclosure/disclosure.css +98 -0
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +263 -116
- package/dist/styles/components/typography/text/text.css +14 -12
- package/dist/styles/disclosure-arrow.css +20 -0
- package/dist/styles/disclosure.css +98 -0
- package/dist/styles/foundation.css +6 -4
- package/dist/styles/list-detail-dialog.css +11 -0
- package/dist/styles/list.css +37 -0
- package/dist/styles/{composer.css → message-composer.css} +17 -33
- package/dist/styles/overlay-toast.css +149 -0
- package/dist/styles/overlay-tooltip.css +55 -0
- package/dist/styles/pane.css +254 -0
- package/dist/styles/popup-menu.css +326 -198
- package/dist/styles/progress-bar.css +168 -0
- package/dist/styles/progress-ring.css +91 -0
- package/dist/styles/radio-group.css +156 -0
- package/dist/styles/resizable-region.css +3 -2
- package/dist/styles/row.css +11 -0
- package/dist/styles/{components/forms/token-search-field/token-search-field.css → search-field.css} +111 -102
- package/dist/styles/select.css +370 -249
- package/dist/styles/slider.css +241 -0
- package/dist/styles/split-view.css +25 -0
- package/dist/styles/state-banner.css +18 -3
- package/dist/styles/styles.css +16 -5
- package/dist/styles/surface-scaffold.css +263 -116
- package/dist/styles/switch.css +132 -0
- package/dist/styles/{app-tab.css → tab-bar-item.css} +95 -90
- package/dist/styles/tab-bar.css +7 -7
- package/dist/styles/tag-field.css +8 -0
- package/dist/styles/text-field.css +193 -0
- package/dist/styles/text.css +14 -12
- package/dist/styles/toolbar-control-group.css +67 -104
- package/dist/styles/toolbar-text.css +5 -18
- package/dist/styles/toolbar.css +10 -3
- package/dist/styles/webawesome.css +9 -0
- package/dist/styles/workbench-dialog.css +10 -0
- package/dist/styles/workbench.css +12 -4
- package/dist/surface-scaffold-register.d.ts +7 -5
- package/dist/surface-scaffold-register.js +2 -246
- package/dist/surface-scaffold-register.js.map +1 -1
- package/dist/surface-scaffold.d.ts +70 -7
- package/dist/surface-scaffold.js +5 -1
- package/dist/switch.d.ts +38 -0
- package/dist/switch.js +4 -0
- package/dist/switch.js.map +1 -0
- package/dist/{app-tab.d.ts → tab-bar-item.d.ts} +11 -11
- package/dist/tab-bar-item.js +6 -0
- package/dist/tab-bar-item.js.map +1 -0
- package/dist/tab-bar.d.ts +3 -3
- package/dist/tab-bar.js +1 -1
- package/dist/tab-navigator.js +1 -1
- package/dist/tag-field.d.ts +52 -0
- package/dist/tag-field.js +6 -0
- package/dist/tag-field.js.map +1 -0
- package/dist/text-field.d.ts +83 -0
- package/dist/text-field.js +6 -0
- package/dist/text-field.js.map +1 -0
- package/dist/text.d.ts +6 -1
- package/dist/text.js +1 -1
- package/dist/{types-CVgIwSdq.d.ts → types-DmHWkSd6.d.ts} +19 -1
- package/dist/webawesome.d.ts +3 -0
- package/dist/wire-catalog.d.ts +8 -2
- package/dist/wire-catalog.js +16 -4
- package/dist/wire-catalog.js.map +1 -1
- package/dist/wire-checkboxes.d.ts +10 -0
- package/dist/wire-checkboxes.js +3 -0
- package/dist/{wire-composers.js.map → wire-checkboxes.js.map} +1 -1
- package/dist/wire-choice-chips.d.ts +17 -0
- package/dist/wire-choice-chips.js +4 -0
- package/dist/{wire-token-search-fields.js.map → wire-choice-chips.js.map} +1 -1
- package/dist/wire-color-fields.d.ts +33 -0
- package/dist/wire-color-fields.js +82 -0
- package/dist/wire-color-fields.js.map +1 -0
- package/dist/wire-color-pickers.d.ts +34 -0
- package/dist/wire-color-pickers.js +9 -0
- package/dist/wire-color-pickers.js.map +1 -0
- package/dist/wire-comboboxes.js +2 -1
- package/dist/wire-content-items.d.ts +5 -1
- package/dist/wire-content-items.js +84 -15
- package/dist/wire-content-items.js.map +1 -1
- package/dist/wire-file-pickers.d.ts +3 -2
- package/dist/wire-file-pickers.js +1 -1
- package/dist/{wire-composers.d.ts → wire-message-composers.d.ts} +5 -4
- package/dist/wire-message-composers.js +3 -0
- package/dist/wire-message-composers.js.map +1 -0
- package/dist/wire-overlay-sheets.js +1 -1
- package/dist/wire-pane-chrome.d.ts +21 -0
- package/dist/wire-pane-chrome.js +67 -0
- package/dist/wire-pane-chrome.js.map +1 -0
- package/dist/{wire-token-search-fields.d.ts → wire-search-fields.d.ts} +25 -25
- package/dist/wire-search-fields.js +6 -0
- package/dist/wire-search-fields.js.map +1 -0
- package/dist/wire-sliders.d.ts +12 -0
- package/dist/wire-sliders.js +31 -0
- package/dist/wire-sliders.js.map +1 -0
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tag-fields.d.ts +41 -0
- package/dist/wire-tag-fields.js +258 -0
- package/dist/wire-tag-fields.js.map +1 -0
- package/dist/wire-text-fields.d.ts +12 -0
- package/dist/wire-text-fields.js +3 -0
- package/dist/wire-text-fields.js.map +1 -0
- package/dist/workbench-dialog.d.ts +97 -0
- package/dist/workbench-dialog.js +124 -0
- package/dist/workbench-dialog.js.map +1 -0
- package/dist/workbench.d.ts +5 -0
- package/dist/workbench.js +1 -1
- package/docs/accessibility.md +181 -97
- package/docs/anchored-surface.md +8 -7
- package/docs/app-layouts.md +28 -0
- package/docs/catalog.md +14 -5
- package/docs/color-field.md +65 -0
- package/docs/color-picker.md +71 -0
- package/docs/color-swatches.md +46 -0
- package/docs/component-contract.md +31 -32
- package/docs/component-selection.md +228 -164
- package/docs/design/templates/button/emphasis-dark.svg +1 -0
- package/docs/design/templates/button/emphasis.svg +1 -0
- package/docs/design/templates/button/icons-dark.svg +1 -0
- package/docs/design/templates/button/icons.svg +1 -0
- package/docs/design/templates/button/pill-dark.svg +1 -0
- package/docs/design/templates/button/pill.svg +1 -0
- package/docs/design/templates/button/states-dark.svg +1 -0
- package/docs/design/templates/button/states.svg +1 -0
- package/docs/design/templates/button/toggles-dark.svg +1 -0
- package/docs/design/templates/button/toggles.svg +1 -0
- package/docs/design/templates/button/tones-dark.svg +1 -0
- package/docs/design/templates/button/tones.svg +1 -0
- package/docs/design/templates/button-dark.svg +1 -0
- package/docs/design/templates/button.svg +1 -0
- package/docs/design/templates/checkbox/compact-dark.svg +1 -0
- package/docs/design/templates/checkbox/compact.svg +1 -0
- package/docs/design/templates/checkbox/error-dark.svg +1 -0
- package/docs/design/templates/checkbox/error.svg +1 -0
- package/docs/design/templates/checkbox/mixed-dark.svg +1 -0
- package/docs/design/templates/checkbox/mixed.svg +1 -0
- package/docs/design/templates/checkbox/states-dark.svg +1 -0
- package/docs/design/templates/checkbox/states.svg +1 -0
- package/docs/design/templates/checkbox-dark.svg +1 -0
- package/docs/design/templates/checkbox.svg +1 -0
- package/docs/design/templates/choice-chips/color-palette-dark.svg +1 -1
- package/docs/design/templates/choice-chips/color-palette.svg +1 -1
- package/docs/design/templates/choice-chips/compact-icons-dark.svg +1 -1
- package/docs/design/templates/choice-chips/compact-icons.svg +1 -1
- package/docs/design/templates/choice-chips/multiple-dark.svg +1 -1
- package/docs/design/templates/choice-chips/multiple.svg +1 -1
- package/docs/design/templates/choice-chips-dark.svg +1 -1
- package/docs/design/templates/choice-chips.svg +1 -1
- package/docs/design/templates/color-field/compact-dark.svg +1 -0
- package/docs/design/templates/color-field/compact.svg +1 -0
- package/docs/design/templates/color-field/error-dark.svg +1 -0
- package/docs/design/templates/color-field/error.svg +1 -0
- package/docs/design/templates/color-field/hint-dark.svg +1 -0
- package/docs/design/templates/color-field/hint.svg +1 -0
- package/docs/design/templates/color-field-dark.svg +1 -0
- package/docs/design/templates/color-field.svg +1 -0
- package/docs/design/templates/color-picker/gray-dark.svg +1 -0
- package/docs/design/templates/color-picker/gray.svg +1 -0
- package/docs/design/templates/color-picker/rgb-dark.svg +1 -0
- package/docs/design/templates/color-picker/rgb.svg +1 -0
- package/docs/design/templates/color-picker-dark.svg +1 -0
- package/docs/design/templates/color-picker.svg +1 -0
- package/docs/design/templates/color-swatches/palette-dark.svg +1 -0
- package/docs/design/templates/color-swatches/palette.svg +1 -0
- package/docs/design/templates/color-swatches-dark.svg +1 -0
- package/docs/design/templates/color-swatches.svg +1 -0
- package/docs/design/templates/disclosure/framed-sunken-dark.svg +1 -0
- package/docs/design/templates/disclosure/framed-sunken.svg +1 -0
- package/docs/design/templates/disclosure/plain-dark.svg +1 -0
- package/docs/design/templates/disclosure/plain.svg +1 -0
- package/docs/design/templates/disclosure-dark.svg +1 -0
- package/docs/design/templates/disclosure.svg +1 -0
- 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/message-composer/chat-dark.svg +1 -0
- package/docs/design/templates/message-composer/chat.svg +1 -0
- package/docs/design/templates/{composer → message-composer}/prompt-dark.svg +1 -1
- package/docs/design/templates/{composer → message-composer}/prompt.svg +1 -1
- package/docs/design/templates/message-composer-dark.svg +1 -0
- package/docs/design/templates/message-composer.svg +1 -0
- package/docs/design/templates/progress-bar/determinate-dark.svg +1 -0
- package/docs/design/templates/progress-bar/determinate.svg +1 -0
- package/docs/design/templates/progress-bar/tones-dark.svg +1 -0
- package/docs/design/templates/progress-bar/tones.svg +1 -0
- package/docs/design/templates/progress-bar-dark.svg +1 -0
- package/docs/design/templates/progress-bar.svg +1 -0
- package/docs/design/templates/progress-ring/sizes-dark.svg +1 -0
- package/docs/design/templates/progress-ring/sizes.svg +1 -0
- package/docs/design/templates/progress-ring/tones-dark.svg +1 -0
- package/docs/design/templates/progress-ring/tones.svg +1 -0
- package/docs/design/templates/progress-ring-dark.svg +1 -0
- package/docs/design/templates/progress-ring.svg +1 -0
- package/docs/design/templates/radio-group/horizontal-dark.svg +1 -0
- package/docs/design/templates/radio-group/horizontal.svg +1 -0
- package/docs/design/templates/radio-group/vertical-dark.svg +1 -0
- package/docs/design/templates/radio-group/vertical.svg +1 -0
- package/docs/design/templates/radio-group-dark.svg +1 -0
- package/docs/design/templates/radio-group.svg +1 -0
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
- package/docs/design/templates/segmented-control/equal.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
- package/docs/design/templates/segmented-control/pill-small.svg +1 -1
- package/docs/design/templates/segmented-control-dark.svg +1 -1
- package/docs/design/templates/segmented-control.svg +1 -1
- package/docs/design/templates/select/compact-dark.svg +1 -0
- package/docs/design/templates/select/compact.svg +1 -0
- package/docs/design/templates/select/form-dark.svg +1 -0
- package/docs/design/templates/select/form.svg +1 -0
- package/docs/design/templates/select/icons-dark.svg +1 -0
- package/docs/design/templates/select/icons.svg +1 -0
- package/docs/design/templates/select-dark.svg +1 -0
- package/docs/design/templates/select.svg +1 -0
- package/docs/design/templates/slider/compact-dark.svg +1 -0
- package/docs/design/templates/slider/compact.svg +1 -0
- package/docs/design/templates/slider/readout-dark.svg +1 -0
- package/docs/design/templates/slider/readout.svg +1 -0
- package/docs/design/templates/slider/ticks-dark.svg +1 -0
- package/docs/design/templates/slider/ticks.svg +1 -0
- package/docs/design/templates/slider-dark.svg +1 -0
- package/docs/design/templates/slider.svg +1 -0
- package/docs/design/templates/switch/compact-dark.svg +1 -0
- package/docs/design/templates/switch/compact.svg +1 -0
- package/docs/design/templates/switch/states-dark.svg +1 -0
- package/docs/design/templates/switch/states.svg +1 -0
- package/docs/design/templates/switch-dark.svg +1 -0
- package/docs/design/templates/switch.svg +1 -0
- package/docs/design/templates/tag-field/error-dark.svg +1 -0
- package/docs/design/templates/tag-field/error.svg +1 -0
- package/docs/design/templates/tag-field/tags-dark.svg +1 -0
- package/docs/design/templates/tag-field/tags.svg +1 -0
- package/docs/design/templates/tag-field-dark.svg +1 -0
- package/docs/design/templates/tag-field.svg +1 -0
- package/docs/design/templates/text-field/compact-dark.svg +1 -0
- package/docs/design/templates/text-field/compact.svg +1 -0
- package/docs/design/templates/text-field/error-dark.svg +1 -0
- package/docs/design/templates/text-field/error.svg +1 -0
- package/docs/design/templates/text-field/labeled-dark.svg +1 -0
- package/docs/design/templates/text-field/labeled.svg +1 -0
- package/docs/design/templates/text-field/multiline-dark.svg +1 -0
- package/docs/design/templates/text-field/multiline.svg +1 -0
- package/docs/design/templates/text-field/search-dark.svg +1 -0
- package/docs/design/templates/text-field/search.svg +1 -0
- package/docs/design/templates/text-field-dark.svg +1 -0
- package/docs/design/templates/text-field.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-320.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -1
- package/docs/design/templates/toolbar/width-visibility-600.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/design/templates/value-table/details-dark.svg +1 -1
- package/docs/design/templates/value-table/details.svg +1 -1
- package/docs/design/templates/value-table-dark.svg +1 -1
- package/docs/design/templates/value-table.svg +1 -1
- package/docs/design/templates.md +19 -6
- package/docs/design-philosophy.md +6 -6
- package/docs/disclosure.md +63 -0
- package/docs/examples/component-catalog-extension.json +2 -2
- package/docs/layout.md +16 -7
- package/docs/list-detail-dialog.md +96 -0
- package/docs/manual-test-plan.md +1 -1
- package/docs/{composer.md → message-composer.md} +41 -28
- package/docs/overlay-toast.md +62 -0
- package/docs/overlay-tooltip.md +53 -0
- package/docs/progress.md +62 -0
- package/docs/recipes.md +15 -21
- package/docs/slider.md +64 -0
- package/docs/surface-scaffold.md +155 -88
- package/docs/tag-field.md +66 -0
- package/docs/type-contracts.md +8 -8
- package/docs/ui-analyzer.md +1 -1
- package/docs/ui-doctor.md +11 -6
- package/docs/ux-demo.md +6 -6
- package/docs/webawesome-migration.md +80 -0
- package/docs/webawesome-theme.md +57 -35
- package/docs/workbench-dialog.md +85 -0
- package/docs/workbench.md +10 -6
- package/docs/writing.md +10 -8
- package/doctor/copy-capitalization-checks.mjs +18 -9
- package/llms.txt +127 -57
- package/package.json +156 -39
- package/ux-demo/recipes/composer-form.tsx +18 -19
- package/ux-demo/recipes/list-detail-dialog.tsx +55 -162
- package/ux-demo/recipes/mount-recipe.ts +7 -6
- package/ux-demo/recipes/types.ts +1 -0
- package/ai/components/icon-button.md +0 -82
- package/ai/components/icon-toggle-button.md +0 -80
- package/dist/app-tab.js +0 -6
- package/dist/app-tab.js.map +0 -1
- package/dist/browser/app-tab.js +0 -4
- package/dist/browser/composer.js +0 -4
- package/dist/browser/icon-toggle-button.js +0 -4
- package/dist/browser/token-search-field.js +0 -4
- package/dist/chunk-2MSPNRWJ.js.map +0 -1
- package/dist/chunk-7IUEBNCO.js.map +0 -1
- package/dist/chunk-AV7CPAPT.js +0 -82
- package/dist/chunk-AV7CPAPT.js.map +0 -1
- package/dist/chunk-BYFTHA4I.js.map +0 -1
- package/dist/chunk-CA7LNX3J.js +0 -44
- package/dist/chunk-CA7LNX3J.js.map +0 -1
- package/dist/chunk-CR5U5FV6.js.map +0 -1
- package/dist/chunk-ELCMSQNJ.js.map +0 -1
- package/dist/chunk-ETCWQLJV.js.map +0 -1
- package/dist/chunk-FDZNYD4C.js.map +0 -1
- package/dist/chunk-FR76ZJQC.js +0 -90
- package/dist/chunk-FR76ZJQC.js.map +0 -1
- package/dist/chunk-HQZYKJ56.js.map +0 -1
- package/dist/chunk-HZPHCSCS.js.map +0 -1
- package/dist/chunk-JOR5LGYE.js.map +0 -1
- package/dist/chunk-K4AT3V3J.js.map +0 -1
- package/dist/chunk-LL45C7BB.js.map +0 -1
- package/dist/chunk-LOSRXZAH.js.map +0 -1
- package/dist/chunk-LPHU44S3.js.map +0 -1
- package/dist/chunk-M5KZ26VV.js.map +0 -1
- package/dist/chunk-MXNIVEVL.js.map +0 -1
- package/dist/chunk-NS762OVM.js +0 -222
- package/dist/chunk-NS762OVM.js.map +0 -1
- package/dist/chunk-QTSMHH5J.js.map +0 -1
- package/dist/chunk-T5BJBMW7.js.map +0 -1
- package/dist/chunk-TDMHA7C3.js.map +0 -1
- package/dist/chunk-TGLUDQP2.js.map +0 -1
- package/dist/chunk-U6QYTMDB.js.map +0 -1
- package/dist/chunk-VFYO3UGZ.js +0 -45
- package/dist/chunk-VFYO3UGZ.js.map +0 -1
- package/dist/chunk-W4IK7AWD.js.map +0 -1
- package/dist/chunk-YBWQR2OK.js.map +0 -1
- package/dist/chunk-ZJC5ND3M.js.map +0 -1
- package/dist/composer.js +0 -5
- package/dist/composer.js.map +0 -1
- package/dist/icon-button.d.ts +0 -46
- package/dist/icon-button.js +0 -6
- package/dist/icon-button.js.map +0 -1
- package/dist/icon-toggle-button.d.ts +0 -42
- package/dist/icon-toggle-button.js +0 -6
- package/dist/icon-toggle-button.js.map +0 -1
- package/dist/styles/components/actions/icon-button/icon-button.css +0 -22
- package/dist/styles/components/actions/icon-toggle-button/icon-toggle-button.css +0 -83
- package/dist/styles/icon-button.css +0 -22
- package/dist/styles/icon-toggle-button.css +0 -83
- package/dist/token-search-field.d.ts +0 -3
- package/dist/token-search-field.js +0 -5
- package/dist/token-search-field.js.map +0 -1
- package/dist/token-search-model.d.ts +0 -3
- package/dist/token-search-model.js +0 -3
- package/dist/token-search-model.js.map +0 -1
- package/dist/wire-composers.js +0 -3
- package/dist/wire-token-search-fields.js +0 -6
- package/docs/design/templates/composer/chat-dark.svg +0 -1
- package/docs/design/templates/composer/chat.svg +0 -1
- package/docs/design/templates/composer-dark.svg +0 -1
- package/docs/design/templates/composer.svg +0 -1
- /package/docs/design/templates/{token-search-field → search-field}/empty-dark.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/empty.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/tokens-dark.svg +0 -0
- /package/docs/design/templates/{token-search-field → search-field}/tokens.svg +0 -0
- /package/docs/design/templates/{token-search-field-dark.svg → search-field-dark.svg} +0 -0
- /package/docs/design/templates/{token-search-field.svg → search-field.svg} +0 -0
package/docs/accessibility.md
CHANGED
|
@@ -9,20 +9,20 @@ These are normative contracts for package components and consuming applications.
|
|
|
9
9
|
- `ListItem` uses native button Enter/Space behavior. `selected` maps to `aria-current="page"`; `pressed` maps to `aria-pressed`. Selected rows keep the normal foreground over their brand-tinted fill so text retains WCAG AA contrast in light and dark themes. Its leading icon visual is 18px while the row retains its 44px minimum target; multiline icons align to the first text line. Its `trailing` content is dormant and must not contain controls. Its `rootAttributes` slot accepts only application `data-*` metadata and deliberately cannot emit `role="menuitem"` in isolation—a true ARIA menu must own arrow, Home/End, Escape, and focus behavior as one widget.
|
|
10
10
|
- `ListItemLink` shares that row content and geometry but uses native anchor Enter behavior and requires `href`. It has no `action` or `pressed` state. `external` opens a new tab with `rel="noopener noreferrer"`; the default accessible name announces the new tab for a string label, so an explicit `accessibleLabel` should do the same. Disabled and loading links omit `href`, expose `aria-disabled`, and leave the tab order. Its trailing content remains dormant.
|
|
11
11
|
- `ListHeader` owns action naming, disabled state, and disclosure `aria-expanded`. Toggle mode supplies one decorative 18px `DisclosureArrow` when `actionIcon` is omitted; it mirrors `expanded` while the native button's accessible name stays stable. The application must update that controlled state and reveal or hide real content. A valid `count` is visually rendered in an `aria-hidden` neutral pill while the required localized `countLabel` becomes part of the owning heading or disclosure button's accessible name; zero remains a real count. Optional `badge` and `status` content can appear together and should each carry meaningful text. Its narrow `triggerAttributes` slot may describe a native popover or controlled-content relationship with `popoverTarget`, `popoverTargetAction`, `aria-controls`, and `aria-haspopup`; the application owns the target surface and its focus/dismissal behavior.
|
|
12
|
-
- Dispose `wireTabBars` and `
|
|
12
|
+
- Dispose `wireTabBars` and `wireSearchFields` with their owning view. Disposal cancels queued controlled-render focus restoration, so a torn-down view cannot reclaim focus from its successor.
|
|
13
13
|
- `wireNavStack` moves focus into every newly active top view and remembers the last focused descendant of each mounted view for pop restoration. Mark a preferred initial heading or control with `data-nav-focus` (and `tabindex="-1"` when it is not normally tabbable); otherwise the helper uses the first enabled focusable descendant, then a programmatically focusable view-container fallback.
|
|
14
14
|
- In any `.kui-pane`, menu rows, `ListHeader` actions, and toolbar groups keep a minimum 44px target in both dimensions. A `ListHeader` fills the available inline width and keeps that action at the logical end, including in RTL. Its action visual defaults to 18px through `--kui-list-header-action-icon-size` inside a fitted 36px hover square; a transparent hit layer extends the pointer target to at least 44 × 44 around that square without moving layout or enlarging the painted surface. Compact headers are 36px tall like the rest of the compact List family, so their action target is 44px wide and clamped to the 36px header height instead of reaching into a neighboring row. Do not reduce the target to the visible icon, and do not force the button itself to 44px.
|
|
15
15
|
- `LoadingSpinner` is either labeled (`role="img"`) or hidden. Its rotation stops for reduced motion.
|
|
16
16
|
- A busy `ToolbarControlGroup` makes its controls inert and exposes `aria-busy`; its `busyLabel` is announced by an adjacent status node outside the inert group. Clear `busy` when the operation finishes so the controls rejoin the focus order.
|
|
17
17
|
- A bottom `Toolbar` uses `position="footer"` for footer semantics; top toolbars keep the default `header`. Workbench's main bottom toolbar sets this automatically.
|
|
18
|
-
- Interactive `ContentItem` cards are keyboard reachable. Set `selectionMode="toggle"` for a pressed button, `selectionMode="single"` for an option inside a listbox, or `selectionMode="multiple"` for a selectable row with a gridcell that can contain native controls. Place multiple-mode rows inside a labeled `List` or `Grid` with `selectionMode="multiple"`; the app owns the selection set and range gestures. Wire `wireContentItems` once so Enter and Space on the card activate its delegated action without activating it from a nested control. Disabled cards expose `aria-disabled` and leave the Tab order.
|
|
18
|
+
- Interactive `ContentItem` cards are keyboard reachable. Set `selectionMode="toggle"` for a pressed button, `selectionMode="single"` for an option inside a listbox, or `selectionMode="multiple"` for a selectable row with a gridcell that can contain native controls. Place multiple-mode rows inside a labeled `List` or `Grid` with `selectionMode="multiple"`; the app owns the selection set and range gestures. Wire `wireContentItems` once so Enter and Space on the card activate its delegated action without activating it from a nested control. The activation click mirrors the key's Shift, Ctrl, and Cmd state, so Shift+Enter or Shift+Space can extend a range and Cmd/Ctrl+Enter or Cmd/Ctrl+Space can toggle one item through the same click handler a pointer uses. Disabled cards expose `aria-disabled` and leave the Tab order.
|
|
19
19
|
- An unlabeled `Skeleton` (including the value slots a component's `placeholder` prop renders) is decorative loading chrome: it is `aria-hidden`, conveys no information a user needs to act on, and is deliberately exempt from the WCAG 3:1 non-text-contrast target. Inside a solid `Badge` it stays subtle (about 2.1–4.4:1 in light, 2.4–2.8:1 in dark, depending on tone); `tests/browser/tone-contrast.spec.ts` holds those values as a regression floor rather than an accessibility threshold. Announce loading through a labeled `Skeleton`, `LoadingSpinner`, or `aria-busy` on the owning region, never through the skeleton's visibility.
|
|
20
20
|
- `StateBanner` defaults to polite `role="status"`; use `urgency="alert"` only for an attention-requiring failure. Its optional `badge` is persistent inline status/count content beside the title and is announced as part of the banner; keep it terse and do not rely on color alone for its meaning.
|
|
21
21
|
- A removable `Chip` has a native button with a specific `removeLabel`, such as "Remove Urgent tag". The button is absent for a plain chip and disabled for a disabled chip. Its leading `icon` is decorative; the visible label names the tag. `truncate` retains the full plain-text label as a native tooltip. Tag text remains visible because tone does not convey meaning alone. A link `Chip` (`href`) is a native anchor named by its visible label, with no remove button; `external` adds `target="_blank"`, `rel="noopener noreferrer"`, and an "(opens in new tab)" name suffix for a text label, and a disabled link chip drops `href`, sets `aria-disabled`, and leaves the tab order. `tone="inherit"` paints no fill, so its label keeps the surrounding text's contrast (a brand-loud bubble's white text included), and its focus ring is drawn in the surrounding foreground so it stays visible on a brand-colored surface. An action `Chip` (`action`) is one native `<button type="button">` with no nested control: its visible label names it unless `actionLabel` supplies a fuller name, which should contain that label ("Insert filter is:mine"). Enter and Space activate it, keyboard focus draws the focus ring (in the surrounding foreground for `tone="inherit"`), and a disabled action chip is a disabled button that leaves the tab order.
|
|
22
22
|
- `EmptyState` reports busy state through `aria-busy` and never relies on an illustration as its label.
|
|
23
23
|
- `Select` follows the Web Awesome host's standard `input`/`change` events. Application tests verify the live `value`, focus, and events—not attributes alone. Its decorative option icons and value-dependent selected content remain present after controlled rerenders, so the visible choice does not silently lose its non-text cue.
|
|
24
24
|
- `DisclosureArrow` is an 18px root-scaled decorative visual by default, not an interaction target. Its owning native control supplies a stable accessible name, pointer and keyboard interaction, and `aria-expanded`; multiple arrows keep independently controlled state. Consumers may resize it with the typed `size` prop without changing that ownership. Configured directions animate over the shortest path; a 180-degree closed-to-open tie uses counterclockwise rotation.
|
|
25
|
-
- `List` is layout-only by default and adds no `list` role. With `selectionMode="multiple"` and a required `ariaLabel`, it becomes a multi-select grid for `ContentItem` rows. Give a scrollable List a bounded block size, avoid nested scroll owners, and keep focused children visible while scrolling.
|
|
25
|
+
- `List` is layout-only by default and adds no `list` role. With `selectionMode="multiple"` and a required `ariaLabel`, it becomes a multi-select grid for `ContentItem` rows. With `wireContentItems` the grid is one Tab stop (roving `tabindex` on the last focused row, else the first selected, else the first enabled), kept across re-renders. Content that sits between rows but is not selectable (an activity group, a "messages skipped" divider) is a `ContentItem gridRow`: a `role="row"` with a `gridcell`, no `aria-selected`, and no Tab stop of its own; arrow keys skip it and its controls stay reachable by Tab. Give a scrollable List a bounded block size, avoid nested scroll owners, and keep focused children visible while scrolling.
|
|
26
26
|
- `Grid` is layout-only by default. With `selectionMode="multiple"` and a required `ariaLabel`, it becomes a multi-select grid for `ContentItem` tiles; each tile remains a row with a gridcell, including when the CSS grid wraps.
|
|
27
27
|
|
|
28
28
|
In a multi-select ContentItem grid, `wireContentItems` moves focus between
|
|
@@ -32,7 +32,9 @@ tiles on the same rendered line and Up/Down moves to the nearest tile in the
|
|
|
32
32
|
adjacent rendered line; Home/End reaches the first/last enabled tile. The
|
|
33
33
|
navigation reads live geometry, so responsive column changes need no rewiring.
|
|
34
34
|
The application changes selection
|
|
35
|
-
on card activation and
|
|
35
|
+
on card activation; `applySelection` and `selectionGesture` from
|
|
36
|
+
`@kerfjs/ui/selection` give it the platform-normalized replace,
|
|
37
|
+
Cmd/Ctrl-toggle, and Shift-range model.
|
|
36
38
|
With delegated click actions, use `isContentItemActivation(event, card)` in the
|
|
37
39
|
card's selection handler so a nested menu trigger or other control does not
|
|
38
40
|
also select the card.
|
|
@@ -110,32 +112,30 @@ even when the selected content shows its own short text.
|
|
|
110
112
|
|
|
111
113
|
Use `hint` for persistent supporting text below the control; use
|
|
112
114
|
`placeholderText` only for the empty value shown inside the closed control.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
inspect or test the element returned by the `combobox` role. Both the `hint`
|
|
117
|
-
attribute used by Kerf and Web Awesome's explicit `hint` slot produce a computed
|
|
118
|
-
accessible description in Chromium, Firefox, and WebKit, so applications do not
|
|
119
|
-
need an `aria-description` mirror or a shadow-DOM patch.
|
|
115
|
+
The hint renders below the control and is the trigger's `aria-description`. The
|
|
116
|
+
accessible control is the light-DOM trigger button (`role="combobox"`), not the
|
|
117
|
+
`kui-select` root; inspect or test the element returned by the `combobox` role.
|
|
120
118
|
Loading placeholders keep the same visible hint while replacing the interactive
|
|
121
119
|
control with inert chrome.
|
|
122
120
|
|
|
123
121
|
`tests/unit/components.test.tsx` covers name projection and visible/hidden label
|
|
124
122
|
variants. `tests/browser/select-accessibility.spec.ts` verifies actual accessible
|
|
125
123
|
names, unchanged unlabeled geometry, keyboard selection, controlled rerenders,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
The explicit `@kerfjs/ui/select/register` import
|
|
129
|
-
Select
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
124
|
+
hint wiring, and wide/narrow presentation in Chromium, Firefox, and WebKit.
|
|
125
|
+
|
|
126
|
+
The explicit `@kerfjs/ui/select/register` import defines the form-associated
|
|
127
|
+
`kui-select` root and wires every Select in the document. The trigger opens the
|
|
128
|
+
listbox (`role="listbox"`, `aria-multiselectable` when `multiple`) as a manual
|
|
129
|
+
popover in the top layer, below the trigger and flipping above when short, with
|
|
130
|
+
focus on the chosen option. In the listbox the arrow keys move and wrap,
|
|
131
|
+
Home/End jump, typing a label's first letters moves to it, and Enter or Space
|
|
132
|
+
chooses; a single Select then closes and returns focus to the trigger, while a
|
|
133
|
+
multiple Select stays open. Escape closes and returns focus to the trigger; Tab
|
|
134
|
+
and an outside press close it. Options are `role="option"` elements with
|
|
135
|
+
`aria-selected` and, for a disabled choice, `aria-disabled`; the template
|
|
136
|
+
renders them, so a re-render keeps them. `tests/unit/select-controller.test.tsx`
|
|
137
|
+
covers the keyboard, choice, and form contracts;
|
|
138
|
+
`tests/browser/select-lifecycle.spec.ts` repeats open/close/resize/reopen
|
|
139
139
|
sequences at wide and narrow widths in Chromium, Firefox, and WebKit.
|
|
140
140
|
|
|
141
141
|
### Help tags on icon-only triggers
|
|
@@ -158,9 +158,13 @@ all three kinds, and any of `@kerfjs/ui/select/register`,
|
|
|
158
158
|
`@kerfjs/ui/popup-menu/register`, or `@kerfjs/ui/help-tags/register` installs
|
|
159
159
|
it (once per document, however many are imported). An application whose
|
|
160
160
|
toolbars have icon-only buttons but no registered `Select` or `PopupMenu`
|
|
161
|
-
imports `@kerfjs/ui/help-tags/register`, which
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
imports `@kerfjs/ui/help-tags/register`, which installs only the help tags.
|
|
162
|
+
The tag is Kerf's own element (no Web Awesome): one `aria-hidden`,
|
|
163
|
+
`popover="manual"` element in the top layer, placed 8px below its trigger
|
|
164
|
+
(flipping above when short, kept 8px clear of the viewport edge), styled by a
|
|
165
|
+
zero-specificity stylesheet the installer adopts so a theme can restyle it.
|
|
166
|
+
Pure `SafeHtml` rendering stays zero-JS: without an installer, nothing shows a
|
|
167
|
+
tag.
|
|
164
168
|
|
|
165
169
|
- **Text.** The tag says what the accessible name says: a filter's name and
|
|
166
170
|
chosen labels ("Filter by label: Bug, Docs", or "Filter by label" when none
|
|
@@ -200,7 +204,7 @@ visible text get no tag: their visible text already names them. A button that
|
|
|
200
204
|
carries a native `title`, or that the application has already given a
|
|
201
205
|
`wa-tooltip` `for` its `id`, keeps that and gets no second tag, so nothing is
|
|
202
206
|
shown twice. Zero-JS components that name an icon control with a native `title`
|
|
203
|
-
(the `ListHeader` action, the `
|
|
207
|
+
(the `ListHeader` action, the `TabBarItem` close button, the `SearchField`
|
|
204
208
|
reveal and clear buttons, and `SegmentedControl` choice titles) keep the
|
|
205
209
|
browser's own tooltip, which needs no script; the installer deliberately skips
|
|
206
210
|
them rather than stacking a second tag on the first. Icon-only buttons outside
|
|
@@ -213,43 +217,55 @@ Chromium.
|
|
|
213
217
|
|
|
214
218
|
## PopupMenu
|
|
215
219
|
|
|
216
|
-
`PopupMenu`
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
The open menu carries that same name
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
a
|
|
232
|
-
|
|
233
|
-
`
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
are
|
|
237
|
-
with the Select's current-option fill rather than a second
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
its
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
item
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
220
|
+
`PopupMenu` is Kerf's own menu: a native trigger `<button>` and a `role="menu"`
|
|
221
|
+
panel that opens as a manual popover in the top layer, wired by
|
|
222
|
+
`@kerfjs/ui/popup-menu/register`. The trigger carries `aria-haspopup="menu"`
|
|
223
|
+
and an `aria-expanded` that follows the menu. An icon-only trigger requires
|
|
224
|
+
`label`, which renders as visually hidden text inside the button; a trigger
|
|
225
|
+
with visible `text` is named by that text. An icon-only trigger also shows its
|
|
226
|
+
`label` as an `aria-hidden` help tag on hover and keyboard focus (see
|
|
227
|
+
[Help tags on icon-only triggers](#help-tags-on-icon-only-triggers)).
|
|
228
|
+
The open menu carries that same name as its `aria-label` (a context or
|
|
229
|
+
icon-only `label`, or the visible `text`), and each submenu panel is named by
|
|
230
|
+
its parent item's label, so it is announced as, for example, "More Actions,
|
|
231
|
+
menu". `tests/browser/popup-menu-accessible-name.spec.ts` finds each panel with
|
|
232
|
+
`getByRole('menu', { name })` in Chromium, Firefox, and WebKit.
|
|
233
|
+
|
|
234
|
+
Items are `menuitem` (or `menuitemcheckbox`, with `aria-checked`) buttons;
|
|
235
|
+
a disabled item keeps `aria-disabled="true"`, stays in the menu, is skipped by
|
|
236
|
+
the arrow keys, and cannot be chosen (its click never reaches the
|
|
237
|
+
application's `data-action`). Disable the whole trigger only when every command
|
|
238
|
+
is unavailable. A heading names the `role="group"` that holds the items under
|
|
239
|
+
it and is itself hidden from assistive technology, so its words are announced
|
|
240
|
+
once; dividers are `role="separator"`. A keyboard-focused item is the menu's
|
|
241
|
+
current row, painted with the Select's current-option fill rather than a second
|
|
242
|
+
focus ring inside the open popup.
|
|
243
|
+
|
|
244
|
+
The keyboard follows the menu-button pattern. Enter, Space, or ArrowDown on the
|
|
245
|
+
trigger opens the menu on its first item, and ArrowUp on its last. ArrowUp and
|
|
246
|
+
ArrowDown move and wrap, Home and End jump, and typing the first letters of a
|
|
247
|
+
label moves to it. Enter or Space chooses the current item; a choice closes the
|
|
248
|
+
menu and returns focus to the trigger. ArrowRight opens a submenu on its first
|
|
249
|
+
item and ArrowLeft returns to the parent item (mirrored right to left); a key
|
|
250
|
+
pressed while a submenu is still fading in lands on the item it names. Escape
|
|
251
|
+
closes the current level and returns focus to its opener, so an enclosing
|
|
252
|
+
dialog stays open; Tab closes the menu and continues from the trigger. A press
|
|
253
|
+
anywhere outside an open menu closes it, including a context menu opened by
|
|
254
|
+
that same press.
|
|
255
|
+
|
|
256
|
+
Hovering an item that has a submenu opens it. While a pointer-opened submenu
|
|
257
|
+
is showing, a "safe triangle" from the pointer to the submenu's near edge keeps
|
|
258
|
+
a diagonal move toward the submenu from closing it as the pointer crosses the
|
|
259
|
+
parent's other rows; moving onto another item of the parent closes it after a
|
|
260
|
+
short grace period. Set `checked` to `true` or `false` for checkbox menu
|
|
261
|
+
semantics; omit it for a plain command. The application owns that state: a
|
|
262
|
+
choice reports the state it asks for in the root's `kui-menu-select` event, and the
|
|
263
|
+
menu shows the new state once the application renders it. `details` supplies
|
|
264
|
+
optional trailing visual content without changing a command's accessible
|
|
265
|
+
label. A `context` menu's invisible anchor is outside the accessibility tree
|
|
266
|
+
and normal Tab order; opening the menu moves focus into its commands and Escape
|
|
267
|
+
dismisses it. Keep a separate visible row action named even when it is
|
|
268
|
+
disabled.
|
|
253
269
|
|
|
254
270
|
## ListActionRow
|
|
255
271
|
|
|
@@ -386,7 +402,7 @@ overlay's own floating toolbars stay.
|
|
|
386
402
|
|
|
387
403
|
## Tabs
|
|
388
404
|
|
|
389
|
-
`
|
|
405
|
+
`TabBarItem` renders one controlled tab. `TabBar` supplies the containing tab list,
|
|
390
406
|
fixed leading/trailing/end regions, and a horizontally scrollable strip.
|
|
391
407
|
Use `TabBar.presentation` for rail, segmented, or inspector chrome,
|
|
392
408
|
`allocation="fill"` when peers should divide the strip, and
|
|
@@ -397,9 +413,8 @@ the shrinkable/scrolling tabs and pins `end` at the far edge. Leading,
|
|
|
397
413
|
trailing, and end actions remain visible and do not shrink. The component owns
|
|
398
414
|
that geometry; applications must not override its anatomy to create the split.
|
|
399
415
|
`trailing` and `end` each accept one `ToolbarControlGroup` for grouped controls
|
|
400
|
-
or one standalone `
|
|
401
|
-
|
|
402
|
-
`AppTab` provides compact 32px, segmented, truncating-label, and icon-only
|
|
416
|
+
or one standalone `Button` when a primary action needs its own chrome. Do not add a wrapper or flex margins to position the action.
|
|
417
|
+
`TabBarItem` provides compact 32px, segmented, truncating-label, and icon-only
|
|
403
418
|
presentations. Icon-only tabs keep the required `name` as the tab button's
|
|
404
419
|
accessible name while visually hiding the duplicate label. The default name
|
|
405
420
|
overflow is an ellipsis; `nameOverflow="visible"` lets an inline loading
|
|
@@ -413,12 +428,12 @@ show placeholder content in its panel until loading completes; its close
|
|
|
413
428
|
button is disabled and hidden and it is not draggable. A `placeholder` tab
|
|
414
429
|
(unknown) is instead disabled, out of the tab order, and not draggable. These props own
|
|
415
430
|
component appearance only; the application still owns the bar's outer placement.
|
|
416
|
-
`
|
|
431
|
+
`TabBarItem.rootAttributes` accepts application `data-*` metadata only; runtime
|
|
417
432
|
filtering rejects roles plus case variants of component- or wiring-owned
|
|
418
433
|
action, identity, selection, drag, drop, and component attributes. An optional
|
|
419
434
|
`closeIcon` is decorative dormant content inside the already named close button
|
|
420
435
|
and must not contain interactive descendants.
|
|
421
|
-
The first `
|
|
436
|
+
The first `TabBarItem` can set `pinned` to stay at the inline start while its peers
|
|
422
437
|
scroll. It remains a normal tab within the same tablist and roving-focus order;
|
|
423
438
|
focus and controlled selection reveal peers beyond the pinned tab. Pin only the
|
|
424
439
|
leading tab of a strip.
|
|
@@ -477,20 +492,89 @@ focused radio, and the checked pill adds a second pixel of border so the
|
|
|
477
492
|
selection does not rely on hue alone; forced-colors mode paints it with
|
|
478
493
|
`Highlight`.
|
|
479
494
|
|
|
480
|
-
With `multiple`, the group renders `role="group"` with the same
|
|
481
|
-
each choice is a native `<input type="checkbox">` inside its pill.
|
|
482
|
-
is its own Tab stop, Space toggles it, assistive technology reads
|
|
483
|
-
checked state, and every checked box submits its value under
|
|
484
|
-
(`FormData.getAll(name)`). Native `required` on a checkbox demands that
|
|
485
|
-
box, so a multiple group takes no `required`; validate an "at least one"
|
|
486
|
-
in the application.
|
|
495
|
+
With `multiple: 'toggle'`, the group renders `role="group"` with the same
|
|
496
|
+
naming, and each choice is a native `<input type="checkbox">` inside its pill.
|
|
497
|
+
Every pill is its own Tab stop, Space toggles it, assistive technology reads
|
|
498
|
+
its native checked state, and every checked box submits its value under
|
|
499
|
+
`name` (`FormData.getAll(name)`). Native `required` on a checkbox demands that
|
|
500
|
+
one box, so a multiple group takes no `required`; validate an "at least one"
|
|
501
|
+
rule in the application.
|
|
502
|
+
|
|
503
|
+
With `multiple: true`, the group is a named `role="listbox"` with
|
|
504
|
+
`aria-multiselectable="true"` and `aria-orientation="horizontal"`, and each
|
|
505
|
+
pill is a `role="option"` whose `aria-selected` reports its state and whose
|
|
506
|
+
visible label is its name; a disabled chip is `aria-disabled`. The listbox is
|
|
507
|
+
one Tab stop (roving `tabindex` on the first selected enabled chip). With
|
|
508
|
+
`wireChoiceChips`: Left/Right (mirrored in right-to-left text), Up/Down,
|
|
509
|
+
Home, and End move focus and select only that chip; Shift with them extends
|
|
510
|
+
the range from the anchor; Cmd on Apple platforms or Ctrl elsewhere with them
|
|
511
|
+
moves focus without changing the selection; Space toggles the focused chip
|
|
512
|
+
and Shift+Space extends to it; Cmd/Ctrl+A selects every enabled chip. A
|
|
513
|
+
click selects one chip, Cmd/Ctrl-click toggles one, and Shift-click extends.
|
|
514
|
+
Hidden inputs submit each selected value under `name`. The focus ring follows
|
|
515
|
+
`:focus-visible` on the option. Every chip color is a theme token resolved through
|
|
487
516
|
`light-dark()`, so inside a dark appearance scope (`.wa-dark`, `.wa-invert`,
|
|
488
517
|
or any `color-scheme: dark` ancestor) the pills, labels, checked tint, and
|
|
489
518
|
focus ring read on inverse chrome without overrides.
|
|
490
519
|
|
|
491
|
-
##
|
|
520
|
+
## TextField
|
|
521
|
+
|
|
522
|
+
`TextField` renders a native `<input>` (or, with `multiline`, a `<textarea>`)
|
|
523
|
+
inside one `<label>`, so a click anywhere on the field focuses it. The input is
|
|
524
|
+
named explicitly — `aria-label` from `label`, whose visible text is
|
|
525
|
+
`aria-hidden`, or from `ariaLabel` — so the clear button and the character
|
|
526
|
+
count inside the label never join its name. `hint` and `error` are visible
|
|
527
|
+
below the field and together form its `aria-description`; `error` also sets
|
|
528
|
+
`aria-invalid="true"`, draws the box border in the danger color, and shows the
|
|
529
|
+
message in the danger text color, so validity never relies on hue alone.
|
|
530
|
+
`required`, `disabled`, `readOnly`, `maxLength`, `type`, and `autocomplete`
|
|
531
|
+
are native attributes. A required field shows an `aria-hidden` asterisk after
|
|
532
|
+
its label; the input itself reports `required`. The focus ring is drawn on the
|
|
533
|
+
box around the input (`:focus-within`), 3px with a 1px offset like every Kerf
|
|
534
|
+
control.
|
|
492
535
|
|
|
493
|
-
`
|
|
536
|
+
`clearable` adds a native `<button>` named by `clearLabel` (default "Clear")
|
|
537
|
+
after the input. It is hidden while the field is empty, is a normal Tab stop,
|
|
538
|
+
and with `wireTextFields(root)` empties the field, dispatches bubbling `input`
|
|
539
|
+
and `change` events as typing would, and returns focus to the field. A
|
|
540
|
+
disabled or read-only field's clear button is disabled. `showCount` (with
|
|
541
|
+
`maxLength`) shows a live `count / maxLength` beside the hint that
|
|
542
|
+
`wireTextFields` keeps current. Compact text grows to 16px on coarse-pointer
|
|
543
|
+
touch screens so focusing a field never zooms the page in iOS.
|
|
544
|
+
|
|
545
|
+
## Checkbox, RadioGroup, and Switch
|
|
546
|
+
|
|
547
|
+
Each control is a native input inside its `<label>`, positioned invisibly over
|
|
548
|
+
an `aria-hidden` drawn box, circle, or track. The label names it, and pointer,
|
|
549
|
+
keyboard, touch exploration, and form submission all reach the real input.
|
|
550
|
+
Keyboard focus draws the 3px focus ring with a 1px offset on the drawn shape;
|
|
551
|
+
forced-colors mode paints checked state with `Highlight`.
|
|
552
|
+
|
|
553
|
+
- `Checkbox` is an `<input type="checkbox">`; Space toggles it. `hint` and
|
|
554
|
+
`error` form its `aria-description`, and `error` sets `aria-invalid="true"`
|
|
555
|
+
and a danger border. `indeterminate` renders a `data-indeterminate` marker
|
|
556
|
+
that `wireCheckboxes(root)` turns into the native `indeterminate` property
|
|
557
|
+
(the only way to set it), so assistive technology reports a mixed state; a
|
|
558
|
+
click clears it natively and the app's next render decides it again.
|
|
559
|
+
- `RadioGroup` is a `<fieldset role="radiogroup">` named by its `<legend>`
|
|
560
|
+
(`label`) or `ariaLabel`. The browser owns the interaction: one Tab stop,
|
|
561
|
+
arrow keys move and select (skipping disabled choices), and the checked
|
|
562
|
+
radio submits its value under `name`. The group's `hint` and `error` form
|
|
563
|
+
its `aria-description`; `error` sets `aria-invalid` on the group, `required`
|
|
564
|
+
sets native `required` on each radio plus `aria-required` on the group, and a
|
|
565
|
+
choice's `hint` is that radio's `aria-description`.
|
|
566
|
+
- `Switch` is an `<input type="checkbox" role="switch">`, so assistive
|
|
567
|
+
technology announces on and off; Space toggles it. Its `hint` is its
|
|
568
|
+
`aria-description`. The thumb's slide is skipped when reduced motion is
|
|
569
|
+
preferred. Use it only for a setting that applies immediately.
|
|
570
|
+
|
|
571
|
+
Hints sit on the label's text column, not under the drawn shape. Safari's
|
|
572
|
+
default Tab order skips checkboxes and radios as it does buttons; the
|
|
573
|
+
controls keep that platform setting.
|
|
574
|
+
|
|
575
|
+
## MessageComposer
|
|
576
|
+
|
|
577
|
+
`MessageComposer`'s message field is a native `<textarea>` named by `label`
|
|
494
578
|
(`aria-label`, title style). With an `id`, the `hint` renders with the id
|
|
495
579
|
`<id>-hint` and becomes the field's `aria-describedby`; without an `id`, the
|
|
496
580
|
hint is visible only. The field draws no border or outline of its own: the
|
|
@@ -500,7 +584,7 @@ outline). Each trailing action keeps its own name and focus ring. `disabled`
|
|
|
500
584
|
disables the field only; the app disables its actions. Sending and
|
|
501
585
|
announcing a sent message stay with the app.
|
|
502
586
|
|
|
503
|
-
With `submitOnEnter` and `
|
|
587
|
+
With `submitOnEnter` and `wireMessageComposers`, the field carries
|
|
504
588
|
`aria-keyshortcuts="Enter"`, so assistive technology announces the shortcut.
|
|
505
589
|
Enter and Cmd/Ctrl+Enter activate the first trailing action, the same control
|
|
506
590
|
a pointer or Tab-and-Space user reaches; Shift+Enter inserts a newline. An
|
|
@@ -512,20 +596,20 @@ disabled field, or a disabled, loading, or `aria-disabled` action sends
|
|
|
512
596
|
nothing. A visible hint may also state the shortcut when the audience may not
|
|
513
597
|
expect it.
|
|
514
598
|
|
|
515
|
-
##
|
|
599
|
+
## SearchField
|
|
516
600
|
|
|
517
601
|
Use `presentation="form-field"` when a structured search query sits beside
|
|
518
602
|
Web Awesome form controls. It renders the visible `label` with the same inset
|
|
519
603
|
and typography, an optional `hint`, and an optional `required` marker. The
|
|
520
604
|
searchbox references the label and hint with `aria-labelledby` and
|
|
521
605
|
`aria-describedby`, and `required` sets `aria-required`; the application
|
|
522
|
-
validates the value before submission. `
|
|
606
|
+
validates the value before submission. `wireSearchFields()` also moves
|
|
523
607
|
focus to the editor when the visible label is clicked. The field stands outside
|
|
524
|
-
a Toolbar and fills the same inline space as a neighboring `
|
|
525
|
-
Its control radius
|
|
526
|
-
|
|
608
|
+
a Toolbar and fills the same inline space as a neighboring `TextField`.
|
|
609
|
+
Its control radius follows the shared `--kui-layout-rounded-radius`, so the two
|
|
610
|
+
controls read as one form.
|
|
527
611
|
|
|
528
|
-
`
|
|
612
|
+
`SearchField` exposes the editable surface as a named `searchbox`. Each
|
|
529
613
|
chip is atomic (`contenteditable="false"`) and contains separately named edit
|
|
530
614
|
and remove buttons; the clear action is also named. A `trailingAction` is a
|
|
531
615
|
named button whose `label` is also its tooltip; a help toggle sets `expanded`
|
|
@@ -533,10 +617,10 @@ named button whose `label` is also its tooltip; a help toggle sets `expanded`
|
|
|
533
617
|
an on/off toggle sets `pressed` (`aria-pressed`). Disabled fields publish
|
|
534
618
|
`aria-disabled` and stop editing without hiding the current expression. The
|
|
535
619
|
application owns query parsing and must announce result-count or loading
|
|
536
|
-
changes separately when that feedback is useful. Use `
|
|
620
|
+
changes separately when that feedback is useful. Use `readSearchField()`
|
|
537
621
|
to ignore the chip buttons' visible text when reading browser-edited content,
|
|
538
|
-
and `
|
|
539
|
-
chip. Call `
|
|
622
|
+
and `placeSearchFieldCaret()` to restore a text caret without landing inside a
|
|
623
|
+
chip. Call `wireSearchFields()` once at a stable root so Enter submits
|
|
540
624
|
without inserting a contenteditable line break and keyboard chip deletion
|
|
541
625
|
restores focus plus the text-relative caret after controlled rendering replaces
|
|
542
626
|
the editor. Restoration finishes after synchronous input listeners and before
|
|
@@ -566,12 +650,12 @@ the complete component. Text or tokens keep the field expanded even when that
|
|
|
566
650
|
transient state is false. Width animation is disabled under reduced motion.
|
|
567
651
|
Clearing with ✕ follows where focus was when it was pressed: from inside the
|
|
568
652
|
field (the editor, or ✕ reached by keyboard) the caret returns to the emptied
|
|
569
|
-
editor; with focus elsewhere, `
|
|
653
|
+
editor; with focus elsewhere, `wireSearchFields` leaves focus where it is
|
|
570
654
|
and collapses the emptied field, as it would on blur.
|
|
571
655
|
|
|
572
656
|
When the field is composed with a caller-owned surface rendered outside it — a
|
|
573
657
|
suggestions listbox, date picker, or help popover — mark that surface (or wrap
|
|
574
|
-
it) with `data-
|
|
658
|
+
it) with `data-search-field-keep-open`, or pass `collapsible.keepOpenOn(target)`,
|
|
575
659
|
so focus or pointer activation moving into it does not collapse an empty field.
|
|
576
660
|
The helper preserves the pointer target when a browser omits
|
|
577
661
|
`focusout.relatedTarget`, preventing the field or target from disappearing
|
|
@@ -579,7 +663,7 @@ between pointerdown and click. For an empty field losing focus during a pointer
|
|
|
579
663
|
press, managed collapse waits until that press's click has dispatched (or the
|
|
580
664
|
press ends without a click), then rechecks focus and content before closing.
|
|
581
665
|
This keeps a shifting search row from moving the pressed control mid-click.
|
|
582
|
-
`
|
|
666
|
+
`wireSearchFields`
|
|
583
667
|
can also, opt-in via `keyboard`, own atomic-chip editing keys: from a collapsed
|
|
584
668
|
caret with no selection, Backspace removes the token before the caret and Delete
|
|
585
669
|
the token after it (reported through `onRemoveToken` for the app to apply to its
|
|
@@ -587,10 +671,10 @@ controlled state), and ArrowRight moves the caret past a trailing chip so typed
|
|
|
587
671
|
text lands after it. An optional `onEdit({ id, editor, event })` — with the
|
|
588
672
|
originating `InputEvent` so a caller can gate on `inputType`/`data` — fires on every editor
|
|
589
673
|
`input`, letting a caller drop its own `input` listener; the application still
|
|
590
|
-
owns query parsing and result-count/loading announcements. When the app's `onEdit` or `onRemoveToken` changes tokens and the controlled render replaces the focused editor, `
|
|
674
|
+
owns query parsing and result-count/loading announcements. When the app's `onEdit` or `onRemoveToken` changes tokens and the controlled render replaces the focused editor, `wireSearchFields` moves focus and caret to the replacement at the same mutation checkpoint (a caret at the end of the query stays at the end; any other caret keeps its place in the remaining text), so keys typed at full speed are not lost.
|
|
591
675
|
|
|
592
|
-
With a `
|
|
593
|
-
`
|
|
676
|
+
With a `createSearchFieldModel` passed to the field and registered in
|
|
677
|
+
`wireSearchFields(root, { models })`, grammar parsing, chips, clear/edit/
|
|
594
678
|
remove actions, and suggestions are managed. Arrow Down moves from the editor
|
|
595
679
|
to suggestions, arrow keys move between suggestions, Enter selects one, and
|
|
596
680
|
Escape returns focus to the editor. The application still announces results
|
|
@@ -708,7 +792,7 @@ panel behind it. The same rule and fallbacks apply.
|
|
|
708
792
|
controls take `--kui-color-text` there. An overlay `TabNavigator` bar's
|
|
709
793
|
unselected labels lift halfway toward `--kui-color-text`, and its selected
|
|
710
794
|
label mixes 40% of it into the brand color: the plain brand color measured
|
|
711
|
-
about 3.2:1 (light) over the worst case. `
|
|
795
|
+
about 3.2:1 (light) over the worst case. A `DialogSurface`'s close button is an
|
|
712
796
|
icon, held to the 3:1 non-text bar, and measures about 3.8:1 (light) and
|
|
713
797
|
4.1:1 (dark) over the raised material. Any other quiet copy you place in
|
|
714
798
|
overlay chrome yourself has no such lift; keep it in the content.
|
package/docs/anchored-surface.md
CHANGED
|
@@ -41,12 +41,13 @@ openAnchoredSurfaceAt(
|
|
|
41
41
|
);
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
Pass `context` for a pointer opened inside a modal dialog. Inside a
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
Pass `context` for a pointer opened inside a modal dialog. Inside a
|
|
45
|
+
`DialogSurface`, the surface stays interactive with no extra markup: the
|
|
46
|
+
dialog renders the host `kerfjs/overlay` uses. Inside a Web Awesome
|
|
47
|
+
`wa-dialog` or `wa-drawer`, `kerfjs/overlay` finds the modal `<dialog>` in the
|
|
48
|
+
element's shadow root and hosts the surface in the element's light DOM,
|
|
49
|
+
slotted inside the dialog. Dialogs opened by `kerfjs/overlay` get a host
|
|
50
|
+
automatically too. For another app-owned native `<dialog>`, include
|
|
50
51
|
`<div data-kerf-overlay-host data-morph-skip></div>` in the dialog markup so
|
|
51
52
|
controls in the anchored surface stay interactive. For any other modal context,
|
|
52
53
|
pass `container`: an element inside the open modal, where the surface is
|
|
@@ -79,7 +80,7 @@ or an ancestor wins; `light dark` follows the user's preference), and the
|
|
|
79
80
|
surface is marked `data-tone="dark"`. Nothing else changes. Every semantic
|
|
80
81
|
color token is a `light-dark()` pair, so the surface fill, border, and shadow,
|
|
81
82
|
and the text, borders, and focus rings of the Kerf UI and Web Awesome
|
|
82
|
-
components inside it (a `ListItem` mute row, a `
|
|
83
|
+
components inside it (a `ListItem` mute row, a `Slider`), resolve to the
|
|
83
84
|
other side by inheritance. The content needs no tone props and no overrides.
|
|
84
85
|
Text and focus rings keep WCAG AA in both page schemes. A theme that replaces a
|
|
85
86
|
semantic token with a single color instead of a `light-dark()` pair opts that
|
package/docs/app-layouts.md
CHANGED
|
@@ -158,6 +158,34 @@ its block padding and `scroll-padding`, alongside the safe-area and
|
|
|
158
158
|
`deepInset` insets, so its first and last items still rest clear of the
|
|
159
159
|
chrome. See `docs/layout.md` "Scroll clearance".
|
|
160
160
|
|
|
161
|
+
### Compact chrome
|
|
162
|
+
|
|
163
|
+
A `Pane` declares what its header and footer do when its container presents
|
|
164
|
+
compactly, with `compactChrome: { header?, footer? }`:
|
|
165
|
+
|
|
166
|
+
- `fixed` (default) keeps the chrome docked; it shrinks the content area.
|
|
167
|
+
- `scroll` puts the chrome inline with the content: the pane scrolls as one
|
|
168
|
+
column, and a footer settles at the bottom of short content and scrolls
|
|
169
|
+
past long content. Chrome left `fixed` stays stuck to its edge.
|
|
170
|
+
- `overlay` lays the chrome over the content's edge on the chrome material,
|
|
171
|
+
hidden until the app opens it with `compactChromeOpen` from a control the
|
|
172
|
+
person can reach (a toolbar button in the view).
|
|
173
|
+
|
|
174
|
+
The Pane only declares the policy. Its container applies it in its compact
|
|
175
|
+
presentation — a `NavStack` view (so a compact `SplitView` and
|
|
176
|
+
`ListDetailDialog` too), a `TabNavigator` scene, a full-screen
|
|
177
|
+
`DialogSurface` (so a compact `WorkbenchDialog`), or a `Workbench` at its
|
|
178
|
+
compact width (448px or less) — and ignores it when roomy. Pass it through a
|
|
179
|
+
view's or panel's `pane` configuration (`pane: { compactChrome: { footer:
|
|
180
|
+
'scroll' } }`).
|
|
181
|
+
|
|
182
|
+
Make open `overlay` chrome transient with `wirePaneChrome(root, { header,
|
|
183
|
+
footer })` from `@kerfjs/ui/wire-pane-chrome`, passing the signals the Pane
|
|
184
|
+
renders as `compactChromeOpen`: Escape, or a press that starts and ends outside
|
|
185
|
+
the open chrome, sets its signal to false, and focus left inside the chrome
|
|
186
|
+
returns to the control that opened it. The app's own toggle keeps working,
|
|
187
|
+
because the dismissal is decided at the click.
|
|
188
|
+
|
|
161
189
|
## Decision matrix
|
|
162
190
|
|
|
163
191
|
| Situation | Layout | Device threshold |
|
package/docs/catalog.md
CHANGED
|
@@ -62,6 +62,15 @@ description?, tags?, resources?, related? }] }`. Each entry becomes a sidebar
|
|
|
62
62
|
primary sections with a quieter treatment: `{ label, sections, collapsible?,
|
|
63
63
|
expanded? }`. When `collapsible`, the label is a disclosure toggle controlling
|
|
64
64
|
`expanded` (the app owns it; wire it with `wireCatalog`'s `onToggleSecondary`).
|
|
65
|
+
An optional `tagFilter: { tag, label, show }` adds a compact `Switch` at the
|
|
66
|
+
top of the open group that leaves out every entry carrying `tag` (and any
|
|
67
|
+
section it empties) until `show` is true. The active entry is always listed,
|
|
68
|
+
so a direct route still shows where it is. The app owns `show`; wire it with
|
|
69
|
+
`wireCatalog`'s `onToggleSecondaryFilter(show)` (action
|
|
70
|
+
`catalog-toggle-secondary-filter`, configurable through
|
|
71
|
+
`toggleSecondaryFilterAction`). Hidden entries are not rendered, so the
|
|
72
|
+
sidebar filter does not search them. The UX catalog uses it to hide
|
|
73
|
+
`Discouraged` Web Awesome entries by default.
|
|
65
74
|
- Optional slots: `headerActions` (extra header controls), `sidebarFooter` (extra
|
|
66
75
|
sidebar content), and `status` (a footer status line).
|
|
67
76
|
- **`settings`** — the active entry's settings (variant and state controls for
|
|
@@ -73,7 +82,7 @@ expanded? }`. When `collapsible`, the label is a disclosure toggle controlling
|
|
|
73
82
|
`ListInsetControl` + `Select` (or other form components) so they share the
|
|
74
83
|
pane's text column; the Catalog owns the pane, its title, and its toggle.
|
|
75
84
|
|
|
76
|
-
The sidebar includes a `
|
|
85
|
+
The sidebar includes a `SearchField` in its fixed header for every Catalog
|
|
77
86
|
consumer, so the filter remains visible while the entries scroll. `wireCatalog`
|
|
78
87
|
filters entry names and section headings as text is typed,
|
|
79
88
|
ignoring case. A heading match shows all its entries; a matching secondary
|
|
@@ -206,9 +215,9 @@ entry's `tags` array.
|
|
|
206
215
|
|
|
207
216
|
Use `align="glyph"` for a bare glyph/text specimen, `align="inline-control"`
|
|
208
217
|
for a control whose own inline padding contributes about 8px, and
|
|
209
|
-
`align="text-trigger"` for a
|
|
210
|
-
|
|
211
|
-
|
|
218
|
+
`align="text-trigger"` for a text menu trigger whose visible label needs an
|
|
219
|
+
8px inset (such as a plain `PopupMenu` trigger), so its text lines up with the
|
|
220
|
+
example label past the trigger's own padding and border. Use
|
|
212
221
|
`align="none"` (the default) for a content item or composition that owns its
|
|
213
222
|
geometry.
|
|
214
223
|
|
|
@@ -324,7 +333,7 @@ facts that source can prove without guessing at rendered intent:
|
|
|
324
333
|
- every `@kerfjs/ui` import is a published package export and relative imports
|
|
325
334
|
do not reach into `ui/src`;
|
|
326
335
|
- focused demos have no relative stylesheet imports, inline style attributes,
|
|
327
|
-
or styling-only `demo-*`, `wa-demo-*`, and
|
|
336
|
+
or styling-only `demo-*`, `wa-demo-*`, and search-field class names;
|
|
328
337
|
- demo JSX does not copy private `kui-catalog-*` structural classes;
|
|
329
338
|
- recipe sources (checked by `npm run check:recipes` with the same shared
|
|
330
339
|
analyzer) import no stylesheet other than public `@kerfjs/ui` CSS, set no
|