@kerfjs/ui 5.0.0-beta.103 → 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 +163 -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 -627
- package/ai/component-composition-rules.json +11 -10
- package/ai/component-composition.json +1689 -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/search-field.md +108 -0
- 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-IM3GKYOG.js → chunk-CIAUILRR.js} +52 -32
- 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-PKL6QJKK.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-MF6ZUUJZ.js → chunk-VEME3D7K.js} +38 -40
- 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-aYR0YAei.d.ts → search-field-CrGTN5sa.d.ts} +67 -43
- 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 +25 -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 +25 -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 +232 -165
- 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 +131 -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/ai/components/token-search-field.md +0 -107
- 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-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-IM3GKYOG.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-MF6ZUUJZ.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-PKL6QJKK.js.map +0 -1
- package/dist/chunk-QTSMHH5J.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/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/slider.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Slider
|
|
2
|
+
|
|
3
|
+
`@kerfjs/ui/slider` picks a value on a range. It is a native
|
|
4
|
+
`<input type="range">` drawn as a track, a brand fill up to the value, and a
|
|
5
|
+
round thumb, identically in Chromium, Firefox, and WebKit.
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Slider } from "@kerfjs/ui/slider";
|
|
9
|
+
import { wireSliders } from "@kerfjs/ui/wire-sliders";
|
|
10
|
+
|
|
11
|
+
<Slider
|
|
12
|
+
id="volume"
|
|
13
|
+
label="Volume"
|
|
14
|
+
value={volume.value}
|
|
15
|
+
showValue
|
|
16
|
+
unit="%"
|
|
17
|
+
hint="Applies to every output device."
|
|
18
|
+
action="set-volume"
|
|
19
|
+
/>;
|
|
20
|
+
|
|
21
|
+
const stop = wireSliders(root);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
- `id` (required) identifies the input and derives the readout, hint, and
|
|
27
|
+
tick ids.
|
|
28
|
+
- `min` (default 0), `max` (default 100), `step` (default 1), and `value`
|
|
29
|
+
(default the midpoint, snapped to `step`; clamped to the range).
|
|
30
|
+
- `label` names it in a row above the track; `ariaLabel` names one without a
|
|
31
|
+
visible label.
|
|
32
|
+
- `showValue` adds the current value at the end of the label row, followed by
|
|
33
|
+
`unit` (such as `%`). With a `unit`, the spoken value includes it too.
|
|
34
|
+
- `ticks` labels stops under the track (`{ value, label? }`). The labels are
|
|
35
|
+
visual; the input still reports its value.
|
|
36
|
+
- `hint` is supporting text below it and its accessible description.
|
|
37
|
+
- `size="compact"` is a 3px track, a 16px thumb, and 14px text; `disabled`
|
|
38
|
+
dims it.
|
|
39
|
+
- `orientation="vertical"` stands it up, minimum at the bottom, `length`
|
|
40
|
+
tall (default 160px), with the label row above and the fill running upward.
|
|
41
|
+
A vertical Slider takes no `ticks`. Arrow keys still step it.
|
|
42
|
+
- `action` puts a `data-action` on the input. Listen for `input` (live) or
|
|
43
|
+
`change` (committed) and store the value the app re-renders with.
|
|
44
|
+
|
|
45
|
+
## Live readout
|
|
46
|
+
|
|
47
|
+
The fill and the readout come from the rendered value. Call
|
|
48
|
+
`wireSliders(root)` once above your Sliders: one delegated `input` listener
|
|
49
|
+
keeps the fill, the readout, and the spoken value text in step with a drag
|
|
50
|
+
before the app re-renders. `syncSlider(input)` recomputes one by hand.
|
|
51
|
+
|
|
52
|
+
## Geometry and accessibility
|
|
53
|
+
|
|
54
|
+
A horizontal Slider fills the available width (a vertical one is as wide as
|
|
55
|
+
its label row) with the shared block-content inset (a
|
|
56
|
+
transparent 1px border and 8px padding), so its label sits on the same text
|
|
57
|
+
column as `Text`. Keyboard and screen-reader behavior are the platform's:
|
|
58
|
+
arrow keys, Page Up and Down, Home, and End step it. The readout is hidden
|
|
59
|
+
from assistive technology because the input already reports its value.
|
|
60
|
+
Forced colors draw a `Highlight` fill on a `GrayText` track.
|
|
61
|
+
|
|
62
|
+
Use a numeric `TextField` when the exact number matters, a `Switch` for on or
|
|
63
|
+
off, and a `SegmentedControl` for a few named options. Use this instead of
|
|
64
|
+
`wa-slider`, which is Discouraged.
|
package/docs/surface-scaffold.md
CHANGED
|
@@ -1,23 +1,78 @@
|
|
|
1
1
|
# Dialog and popup surface scaffolds
|
|
2
2
|
|
|
3
|
-
`DialogSurface`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
`
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
`DialogSurface` is Kerf's modal dialog: a native `<dialog>` with a header
|
|
4
|
+
(title, header actions, close button), a body, and an optional footer, sized
|
|
5
|
+
and presented by its props. `PopoverDialogSurface` is its non-modal sibling,
|
|
6
|
+
and `PopupSurface` insets a raw Web Awesome dropdown. The application owns
|
|
7
|
+
open state, dismissal policy, ids, names, and content.
|
|
8
|
+
|
|
9
|
+
`DialogSurface` is the single-pane dialog type. For a modal that picks a
|
|
10
|
+
record from a list and shows its detail beside it, use
|
|
11
|
+
[`ListDetailDialog`](./list-detail-dialog.md) instead of wrapping a
|
|
12
|
+
`SplitView` in a `DialogSurface`: it draws no surface header, so the title and
|
|
13
|
+
close control sit in the detail column and the divider runs the full height.
|
|
14
|
+
For an editing task with side panels, use
|
|
15
|
+
[`WorkbenchDialog`](./workbench-dialog.md), a header-less dialog around a
|
|
16
|
+
`Workbench` whose rails become overlays on compact devices.
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { DialogSurface, openDialog } from '@kerfjs/ui/surface-scaffold';
|
|
20
|
+
|
|
21
|
+
<Button action="edit-workspace">Edit Workspace</Button>
|
|
22
|
+
<DialogSurface
|
|
23
|
+
id="edit-workspace"
|
|
24
|
+
label="Edit Workspace"
|
|
25
|
+
bodyInset="none"
|
|
26
|
+
footer={
|
|
27
|
+
<>
|
|
28
|
+
<Button rootAttributes={{ 'data-dialog-close': '' }}>Cancel</Button>
|
|
29
|
+
<Button tone="brand" action="save-workspace">Save</Button>
|
|
30
|
+
</>
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<List>
|
|
34
|
+
<ListInsetText>Changes apply to every project in this workspace.</ListInsetText>
|
|
35
|
+
</List>
|
|
36
|
+
</DialogSurface>;
|
|
37
|
+
|
|
38
|
+
openDialog(document.getElementById('edit-workspace') as HTMLDialogElement);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- **Name.** `label` names the dialog and is its title text. With `heading`
|
|
42
|
+
(title content such as an xl `ToolbarText` with a description), pass
|
|
43
|
+
`labelledBy`, the id of the element that names it, or keep `label`.
|
|
44
|
+
- **Header.** The title, then `headerActions` and a close button (`closeLabel`,
|
|
45
|
+
default `Close`). `withoutHeader` renders none, for content that owns its
|
|
46
|
+
heading and close control.
|
|
47
|
+
- **Body and footer.** `children` is the body; `footer` sits below it (or
|
|
48
|
+
floats over it, see [Chat dialogs](#chat-dialogs-a-floating-footer-over-a-filling-transcript)).
|
|
49
|
+
- **Opening and closing.** Render the dialog closed and open it with
|
|
50
|
+
`openDialog(dialog)`: it opens modally in the top layer, the rest of the
|
|
51
|
+
page is inert, and focus moves to an `autofocus` element or else the panel.
|
|
52
|
+
`closeDialog(dialog)` closes it after its exit motion; the browser returns
|
|
53
|
+
focus to the element that opened it. Do not toggle its `open` attribute,
|
|
54
|
+
which opens a dialog without modality.
|
|
55
|
+
- **Close requests.** The close button, any element inside with
|
|
56
|
+
`data-dialog-close` (a Cancel button), Escape, and, with `lightDismiss`, a
|
|
57
|
+
press on the backdrop ask to close: the dialog dispatches a cancelable
|
|
58
|
+
`kui-request-close` whose `detail.source` is `close-button`, `escape`, or
|
|
59
|
+
`backdrop`. Call `preventDefault()` to keep it open (unsaved changes); the
|
|
60
|
+
panel then pulses, as it does for a backdrop press without `lightDismiss`.
|
|
61
|
+
The native `close` event fires once it has closed. Your own
|
|
62
|
+
`closeDialog()` is never refused.
|
|
63
|
+
|
|
64
|
+
Choose `size` (`small`, `medium`, or `large`), `presentation` (`modal`,
|
|
65
|
+
`side-sheet`, `fullscreen`, or `bottom-sheet`; see
|
|
66
|
+
[Bottom sheets](#bottom-sheets)), and independent `bodyInset` / `footerInset`
|
|
67
|
+
(`none`, `compact`, or `comfortable`). The defaults match Kerf's medium modal,
|
|
68
|
+
8px body, and 16px footer rhythm. The dialog scales and fades in and out
|
|
69
|
+
(150ms), unless motion is reduced or the document's static effects mode is on.
|
|
15
70
|
|
|
16
71
|
The panel corner is concentric with a pill `ToolbarControlGroup` (22px) resting
|
|
17
72
|
at the body inset: 30px for `compact` (and `none`) and 38px for `comfortable`,
|
|
18
73
|
so header and body controls nest into the curve. A side sheet uses the same
|
|
19
|
-
radius on its leading corners, and a
|
|
20
|
-
|
|
74
|
+
radius on its leading corners, and a `PopoverDialogSurface` takes the 30px
|
|
75
|
+
default.
|
|
21
76
|
|
|
22
77
|
The modal size presets have preferred widths of 400px, 560px, and 800px,
|
|
23
78
|
respectively, before the viewport width cap. Set `preferredWidth` to a branded
|
|
@@ -31,14 +86,12 @@ resource tracks or preview aspect sizing.
|
|
|
31
86
|
Every `DialogSurface` root has the same structure, so two sibling dialogs that
|
|
32
87
|
are rendered conditionally are matched by position when the page re-renders:
|
|
33
88
|
one open dialog's element (with its accessible name and open state) can be
|
|
34
|
-
reused for another, and
|
|
35
|
-
|
|
36
|
-
|
|
89
|
+
reused for another, and its `close` event fires on the wrong dialog. Give each
|
|
90
|
+
sibling a stable key on its root with `rootAttributes` (or an `id`), instead
|
|
91
|
+
of wrapping it in an app `div`:
|
|
37
92
|
|
|
38
93
|
```tsx
|
|
39
|
-
<DialogSurface rootAttributes={{ "data-key": "project-setup" }}>
|
|
40
|
-
<wa-dialog label="Set up project">…</wa-dialog>
|
|
41
|
-
</DialogSurface>
|
|
94
|
+
<DialogSurface label="Set up project" rootAttributes={{ "data-key": "project-setup" }}>…</DialogSurface>
|
|
42
95
|
```
|
|
43
96
|
|
|
44
97
|
`rootAttributes` takes `data-*` identity only; the surface's own configuration
|
|
@@ -51,26 +104,25 @@ It sets the minimum horizontal clearance; `preferredWidth` overrides the `size`
|
|
|
51
104
|
preset when supplied. `maxHeight` accepts a branded length or `"viewport"`; explicit caps are
|
|
52
105
|
clamped to the dynamic viewport height minus twice the gutter (16px per edge
|
|
53
106
|
when the gutter is omitted). Negative gutters/caps clamp to zero. Omitting
|
|
54
|
-
both options
|
|
107
|
+
both options keeps the default caps: 20px clear of each viewport edge, and
|
|
108
|
+
80% of the viewport height at 420px wide or narrower.
|
|
55
109
|
These options apply only to `presentation="modal"`; side sheets and fullscreen
|
|
56
110
|
surfaces keep their own geometry, and a bottom sheet reads `height` and
|
|
57
111
|
`maxHeight` as described in [Bottom sheets](#bottom-sheets).
|
|
58
112
|
|
|
59
113
|
```tsx
|
|
60
|
-
import '@kerfjs/ui/surface-scaffold/register';
|
|
61
114
|
import { remify } from '@kerfjs/ui/css-values';
|
|
62
115
|
import { DialogSurface } from '@kerfjs/ui/surface-scaffold';
|
|
63
116
|
|
|
64
|
-
<DialogSurface preferredWidth={remify(832)} viewportGutter={remify(8)} maxHeight="viewport" bodyInset="none">
|
|
65
|
-
|
|
117
|
+
<DialogSurface id="close-workspace" label="Close Workspace" preferredWidth={remify(832)} viewportGutter={remify(8)} maxHeight="viewport" bodyInset="none" footer={actions}>
|
|
118
|
+
{/* Application-owned content */}
|
|
66
119
|
</DialogSurface>;
|
|
67
120
|
```
|
|
68
121
|
|
|
69
122
|
This gives a desktop modal an 832px preferred width and a phone modal an 8px edge gutter with a `calc(100dvh - 16px)` height
|
|
70
|
-
cap without application selectors on Kerf roots
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
scroll owner. Choosing a larger cap cannot guarantee that arbitrary content
|
|
123
|
+
cap without application selectors on Kerf roots. A cap is not a fixed
|
|
124
|
+
height: short content stays naturally sized, and taller content scrolls in the
|
|
125
|
+
dialog body while its header/footer remain outside that scroll owner. Choosing a larger cap cannot guarantee that arbitrary content
|
|
74
126
|
fits without scrolling; preview tracks, canvas aspect ratios and content sizing
|
|
75
127
|
remain application-owned.
|
|
76
128
|
|
|
@@ -95,7 +147,7 @@ edit sheet. The default `modal` presentation is unchanged.
|
|
|
95
147
|
- **Safe area and keyboard.** The panel runs to the edge, behind the home
|
|
96
148
|
indicator and any virtual keyboard, while a block-end padding keeps its
|
|
97
149
|
content above them. The padding is the largest of
|
|
98
|
-
`--kui-safe-area-block-end`, the keyboard overlap
|
|
150
|
+
`--kui-safe-area-block-end`, the keyboard overlap `openDialog` measures from
|
|
99
151
|
`visualViewport` (layout height minus the visual viewport's height and top
|
|
100
152
|
offset, ignored while pinch-zoomed), and the VirtualKeyboard API's
|
|
101
153
|
`env(keyboard-inset-height)`. A page whose viewport meta sets
|
|
@@ -113,31 +165,27 @@ edit sheet. The default `modal` presentation is unchanged.
|
|
|
113
165
|
horizontal `separator` named "Resize sheet" with `aria-valuemin`,
|
|
114
166
|
`aria-valuenow`, and `aria-valuemax` in visible px. Drag it, or use the
|
|
115
167
|
arrow keys (16px), Page Up/Down (64px), Home (`minHeight`, default 160px),
|
|
116
|
-
and End (the cap). The
|
|
117
|
-
|
|
118
|
-
Each opening starts again at
|
|
168
|
+
and End (the cap). The grabber sits at the panel's top edge, outside the
|
|
169
|
+
body, so it never disturbs `bodyLayout` children, and the resized height
|
|
170
|
+
survives a re-render while the sheet is open. Each opening starts again at
|
|
171
|
+
`height`.
|
|
119
172
|
- **Motion.** The sheet slides up from the bottom edge when it opens and back
|
|
120
173
|
down when it is dismissed. `enterMotion="standard"` or
|
|
121
|
-
`exitMotion="standard"` keeps
|
|
122
|
-
transition.
|
|
123
|
-
|
|
124
|
-
|
|
174
|
+
`exitMotion="standard"` keeps the dialog's scale-and-fade for that
|
|
175
|
+
transition. There is no motion under `prefers-reduced-motion: reduce` or
|
|
176
|
+
the document's static effects mode (`:root[data-kui-effects="static"]`). A
|
|
177
|
+
refused close still pulses.
|
|
125
178
|
|
|
126
179
|
```tsx
|
|
127
|
-
import '@kerfjs/ui/surface-scaffold/register';
|
|
128
180
|
import { remify } from '@kerfjs/ui/css-values';
|
|
129
181
|
import { DialogSurface } from '@kerfjs/ui/surface-scaffold';
|
|
130
182
|
|
|
131
|
-
<DialogSurface presentation="bottom-sheet" height={remify(360)} minHeight={remify(200)} resizable bodyInset="none">
|
|
132
|
-
|
|
133
|
-
{/* Application-owned fields */}
|
|
134
|
-
</wa-dialog>
|
|
183
|
+
<DialogSurface id="new-message" label="New Message" lightDismiss presentation="bottom-sheet" height={remify(360)} minHeight={remify(200)} resizable bodyInset="none">
|
|
184
|
+
{/* Application-owned fields */}
|
|
135
185
|
</DialogSurface>;
|
|
136
186
|
```
|
|
137
187
|
|
|
138
|
-
|
|
139
|
-
entry. Without it the sheet keeps its bottom-edge geometry and safe-area
|
|
140
|
-
padding, shows no grabber, and opens with Web Awesome's own animation.
|
|
188
|
+
`openDialog` wires the resize grabber, keyboard clearance, and slide.
|
|
141
189
|
`preferredWidth`, `bodyLayout`, the floating header and footer, and the
|
|
142
190
|
insets compose with a bottom sheet as they do with a modal.
|
|
143
191
|
|
|
@@ -231,10 +279,8 @@ body's whole height to its one child, which owns its own scrolling; the body
|
|
|
231
279
|
itself stops scrolling. Combine it with `bodyInset="none"`.
|
|
232
280
|
|
|
233
281
|
```tsx
|
|
234
|
-
<DialogSurface size="large" height={remify(640)} viewportGutter={remify(8)} bodyInset="none" bodyLayout="fill">
|
|
235
|
-
<
|
|
236
|
-
<SplitView id="repo-split" label="Changes" listWidth={{ size: 432, maxFraction: 0.5 }} list={list} detail={detail} />
|
|
237
|
-
</wa-dialog>
|
|
282
|
+
<DialogSurface label="Repository Status" size="large" height={remify(640)} viewportGutter={remify(8)} bodyInset="none" bodyLayout="fill">
|
|
283
|
+
<SplitView id="repo-split" label="Changes" listWidth={{ size: 432, maxFraction: 0.5 }} list={list} detail={detail} />
|
|
238
284
|
</DialogSurface>;
|
|
239
285
|
```
|
|
240
286
|
|
|
@@ -253,8 +299,8 @@ and floats its composer over the body's block end. Two props compose it:
|
|
|
253
299
|
The modal panel is its positioning context. The default `docked` footer
|
|
254
300
|
sits below the body as before.
|
|
255
301
|
|
|
256
|
-
|
|
257
|
-
hides) and the body reserves that height plus the offset after its own inset,
|
|
302
|
+
An open dialog measures its footer (it follows a composer that grows, wraps,
|
|
303
|
+
or hides) and the body reserves that height plus the offset after its own inset,
|
|
258
304
|
with a matching `scroll-padding`. Flowing body content scrolls beneath the
|
|
259
305
|
floating footer and its end stays reachable above it; with `fill` or
|
|
260
306
|
`fill-last` the filling child's scrollport ends at the footer's top. Content
|
|
@@ -278,24 +324,31 @@ Choose the offset like any other responsive value: the scaffold adds no
|
|
|
278
324
|
breakpoint. An 8px offset lines a composer up with the transcript's
|
|
279
325
|
content-item edges when the body has `bodyInset="none"` and list geometry;
|
|
280
326
|
`viewportGutter` and `footerOffset` can follow `deviceClass()` when a phone
|
|
281
|
-
needs tighter edges. Put a [`
|
|
327
|
+
needs tighter edges. Put a [`MessageComposer`](./message-composer.md) in the floating footer
|
|
282
328
|
with `footerInset="none"`: its raised frame and shadow lift it over the
|
|
283
329
|
transcript, and its field grows the measured footer. With `submitOnEnter` and
|
|
284
|
-
`
|
|
330
|
+
`wireMessageComposers(root)`, Enter sends through the same action as the Send button.
|
|
285
331
|
|
|
286
332
|
```tsx
|
|
287
|
-
<DialogSurface
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
333
|
+
<DialogSurface
|
|
334
|
+
label="Assistant"
|
|
335
|
+
height={remify(560)}
|
|
336
|
+
viewportGutter={remify(8)}
|
|
337
|
+
bodyInset="none"
|
|
338
|
+
bodyLayout="fill-last"
|
|
339
|
+
footerPresentation="floating"
|
|
340
|
+
footerOffset={remify(8)}
|
|
341
|
+
footerInset="none"
|
|
342
|
+
footer={<MessageComposer submitOnEnter id="assistant-message" name="message" label="Message" placeholder="Ask about this build" trailing={<Button tone="brand" action="send-message">Send</Button>} />}
|
|
343
|
+
>
|
|
344
|
+
<StateBanner title="Answers use the latest nightly build." tone="neutral" />
|
|
345
|
+
<List gap="xs" controlInsets="tb" scrollable scrollClearance="block-end">
|
|
346
|
+
{messages.map((message) => (
|
|
347
|
+
<ContentItem bubble={message.mine ? 'end' : 'start'} appearance={message.mine ? 'brand-loud' : 'neutral'}>
|
|
348
|
+
<Text variant="span">{message.text}</Text>
|
|
349
|
+
</ContentItem>
|
|
350
|
+
))}
|
|
351
|
+
</List>
|
|
299
352
|
</DialogSurface>;
|
|
300
353
|
```
|
|
301
354
|
|
|
@@ -308,11 +361,11 @@ behind `--kui-chrome-material-filter` (a blur and saturation backdrop filter).
|
|
|
308
361
|
Content passing beneath the title bar reads as softened color, not as
|
|
309
362
|
competing text. The default `docked` header sits above the body as before.
|
|
310
363
|
|
|
311
|
-
|
|
312
|
-
follows a title that wraps, text that grows, or a `
|
|
364
|
+
An open dialog measures its header the same way it measures the footer (it
|
|
365
|
+
follows a title that wraps, text that grows, or a `withoutHeader` toggle).
|
|
313
366
|
The body reserves the measured height before its own inset, with a matching
|
|
314
367
|
`scroll-padding`, so flowing content starts below the title bar and scrolls
|
|
315
|
-
beneath it.
|
|
368
|
+
beneath it. Unmeasured (a dialog opened without `openDialog`), the header
|
|
316
369
|
stays docked rather than covering content.
|
|
317
370
|
|
|
318
371
|
To let a filling transcript scroll visibly beneath the title bar, make it the
|
|
@@ -325,21 +378,29 @@ reservation: they never sit beneath the title bar. Combined with a floating
|
|
|
325
378
|
composer and `scrollClearance="both"`, the transcript scrolls beneath both:
|
|
326
379
|
|
|
327
380
|
```tsx
|
|
328
|
-
<DialogSurface
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
381
|
+
<DialogSurface
|
|
382
|
+
label="Release Thread"
|
|
383
|
+
heading={<ToolbarText text="Release Thread" size="xlarge" description="Engineering · 5.2 candidate" />}
|
|
384
|
+
height={remify(560)}
|
|
385
|
+
viewportGutter={remify(8)}
|
|
386
|
+
bodyInset="none"
|
|
387
|
+
bodyLayout="fill"
|
|
388
|
+
headerPresentation="floating"
|
|
389
|
+
footerPresentation="floating"
|
|
390
|
+
footerOffset={remify(8)}
|
|
391
|
+
footerInset="none"
|
|
392
|
+
footer={<MessageComposer submitOnEnter id="thread-message" name="message" label="Message" placeholder="Reply to the thread" trailing={<Button tone="brand" action="send-message">Send</Button>} />}
|
|
393
|
+
>
|
|
394
|
+
<List gap="xs" controlInsets="tb" scrollable scrollClearance="both">
|
|
395
|
+
{bubbles}
|
|
396
|
+
</List>
|
|
336
397
|
</DialogSurface>;
|
|
337
398
|
```
|
|
338
399
|
|
|
339
400
|
Like a `Pane`'s overlay header, the title bar draws its divider as scroll
|
|
340
401
|
state: a 1px line along its bottom edge only while the body, or a filling
|
|
341
402
|
child that reaches beneath it, is scrolled away from its top, and none at
|
|
342
|
-
rest. The
|
|
403
|
+
rest. The open dialog follows those scrollers (a nested scroller that starts
|
|
343
404
|
below the title bar never counts), and the line is an inset shadow, so it
|
|
344
405
|
never moves the header or the content.
|
|
345
406
|
|
|
@@ -347,8 +408,8 @@ The material turns opaque under `prefers-reduced-transparency: reduce` or
|
|
|
347
408
|
`prefers-contrast: more`, and where the browser lacks `backdrop-filter`; in
|
|
348
409
|
forced colors the header paints `Canvas` with a `CanvasText` bottom edge.
|
|
349
410
|
|
|
350
|
-
For a title with a short supporting line,
|
|
351
|
-
(
|
|
411
|
+
For a title with a short supporting line, pass a `ToolbarText` as the
|
|
412
|
+
`heading` (`heading={<ToolbarText text="Release Thread" size="xlarge" description="Engineering · 5.2 candidate" />}`).
|
|
352
413
|
On the floating title bar an untoned `ToolbarText` keeps AA by itself: its
|
|
353
414
|
title takes the normal text color and its description lifts halfway toward
|
|
354
415
|
it. Any other quiet copy you place there can fall below AA over the content
|
|
@@ -365,7 +426,7 @@ geometry.
|
|
|
365
426
|
|
|
366
427
|
## Non-modal dialogs: `PopoverDialogSurface`
|
|
367
428
|
|
|
368
|
-
`
|
|
429
|
+
`DialogSurface` is modal: it makes the page inert until it closes. When a dialog
|
|
369
430
|
should leave the page interactive and close on Escape or a press outside (a
|
|
370
431
|
status panel, a quick inspector), render `PopoverDialogSurface` instead of a
|
|
371
432
|
hand-built popover with application chrome CSS. It is a native
|
|
@@ -386,8 +447,8 @@ pass `describedBy`, the id of the element that holds the summary. It renders as
|
|
|
386
447
|
</PopoverDialogSurface>;
|
|
387
448
|
```
|
|
388
449
|
|
|
389
|
-
`DialogSurface` has no `describedBy
|
|
390
|
-
|
|
450
|
+
`DialogSurface` has no `describedBy`: name it with `label` or `labelledBy`,
|
|
451
|
+
and keep any description in the body or its `heading`'s description.
|
|
391
452
|
|
|
392
453
|
Open it with a control's `popoverTarget` (or `showPopover()`); the browser
|
|
393
454
|
places it centered in the top layer, light-dismisses it, and restores nothing
|
|
@@ -404,13 +465,19 @@ preview.
|
|
|
404
465
|
</PopoverDialogSurface>;
|
|
405
466
|
```
|
|
406
467
|
|
|
407
|
-
Use `DialogSurface`
|
|
468
|
+
Use `DialogSurface` whenever the task must block the page.
|
|
408
469
|
|
|
409
470
|
Wrap one `PopupMenu` (or another single `wa-dropdown`) with `PopupSurface`. `inset="list-zero"` removes menu
|
|
410
471
|
padding for a child that already owns row insets, `compact` uses 4px, and
|
|
411
|
-
`standard` uses the shared 8px surface inset. Keep the
|
|
412
|
-
|
|
413
|
-
identity across Kerf rerenders
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
472
|
+
`standard` uses the shared 8px surface inset. Keep the menu trigger named. A raw
|
|
473
|
+
`wa-dropdown` should keep `data-morph-skip-children` when its upgraded light-DOM
|
|
474
|
+
items must retain identity across Kerf rerenders; a `PopupMenu` already
|
|
475
|
+
protects its own open state from the morph.
|
|
476
|
+
|
|
477
|
+
`openDialog` installs the document listeners every `DialogSurface` needs
|
|
478
|
+
(close requests, motion, and, while each dialog is open, chrome measurement,
|
|
479
|
+
the floating header's divider, the bottom sheet's keyboard clearance and
|
|
480
|
+
grabber, and restoring that measured state after an application re-render).
|
|
481
|
+
Import `@kerfjs/ui/surface-scaffold/register` once when a dialog may be opened
|
|
482
|
+
without `openDialog` and should still take close requests. Rendering a
|
|
483
|
+
`DialogSurface` has no side effects and registers no custom element.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# TagField
|
|
2
|
+
|
|
3
|
+
`@kerfjs/ui/tag-field` collects short values as removable tags, each
|
|
4
|
+
submitted as its own form value. It is SearchField's token editor in its
|
|
5
|
+
`form-field` presentation, so tags look and edit like SearchField chips, plus
|
|
6
|
+
a hidden input per tag.
|
|
7
|
+
|
|
8
|
+
```tsx
|
|
9
|
+
import { TagField } from "@kerfjs/ui/tag-field";
|
|
10
|
+
import { wireTagFields } from "@kerfjs/ui/wire-tag-fields";
|
|
11
|
+
|
|
12
|
+
const labels = signal(["bug", "docs"]);
|
|
13
|
+
|
|
14
|
+
<TagField
|
|
15
|
+
id="labels"
|
|
16
|
+
label="Labels"
|
|
17
|
+
name="labels"
|
|
18
|
+
tags={labels.value}
|
|
19
|
+
hint="Press Enter or a comma to add a label."
|
|
20
|
+
/>;
|
|
21
|
+
|
|
22
|
+
const stop = wireTagFields(root, {
|
|
23
|
+
onChange: ({ tags }) => (labels.value = tags),
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Props
|
|
28
|
+
|
|
29
|
+
- `id` and `label` (required): the editor's identity and its visible name.
|
|
30
|
+
- `tags` (required): the list, in order. The app owns it.
|
|
31
|
+
- `name` and `form`: each tag submits as a hidden `<input name>` (none while
|
|
32
|
+
`disabled`).
|
|
33
|
+
- `hint`, or `error`, which replaces the hint, marks the field invalid, and
|
|
34
|
+
turns its frame and message the danger color.
|
|
35
|
+
- `max`: the most tags `wireTagFields` accepts.
|
|
36
|
+
- `placeholder` (default `Add tag…`) and `morePlaceholder` after the last tag
|
|
37
|
+
(default `Add another…`), `required`, `disabled`, `icon` (default a tag
|
|
38
|
+
glyph), and `clearLabel` (default `Clear Tags`).
|
|
39
|
+
|
|
40
|
+
## Editing
|
|
41
|
+
|
|
42
|
+
`wireTagFields(root, options)` wires every TagField under `root`, including
|
|
43
|
+
the SearchField editor mechanics it is built on:
|
|
44
|
+
|
|
45
|
+
- **Adding.** Enter or a delimiter (default `,`) adds the typed text; text
|
|
46
|
+
pasted with delimiters becomes several tags; Tab, or focus leaving the
|
|
47
|
+
editor, adds what is typed (`commitOnBlur: false` turns that off).
|
|
48
|
+
- **Refusing.** A duplicate (unless `allowDuplicates`), a value past `max`, or
|
|
49
|
+
a value `normalize` refuses is reported to `onReject({ id, value, reason })`
|
|
50
|
+
with `reason` `duplicate`, `max`, or `invalid`; show it as the `error`.
|
|
51
|
+
`normalize` defaults to trimming and refusing empty text.
|
|
52
|
+
- **Removing and editing.** Backspace at the start removes the last tag; a
|
|
53
|
+
chip's × removes it; its label moves it back into the editor to edit; the
|
|
54
|
+
clear button empties the list.
|
|
55
|
+
- **Moving.** ArrowLeft at the start reaches the chips; ArrowLeft and
|
|
56
|
+
ArrowRight move between them and back to the editor; Backspace or Delete
|
|
57
|
+
removes the focused chip.
|
|
58
|
+
|
|
59
|
+
Every change goes to `onChange({ id, tags })`; apply it and re-render. The
|
|
60
|
+
caret returns to the editor after a change made while typing. A
|
|
61
|
+
`wireSearchFields` on the same root leaves a TagField's keys to
|
|
62
|
+
`wireTagFields`, so both can wire one page.
|
|
63
|
+
|
|
64
|
+
Use `SearchField` instead when the tokens are search filters, and
|
|
65
|
+
`ChoiceChips` to pick several values from a short known set. Use this instead
|
|
66
|
+
of `wa-tag-input`, which is Discouraged.
|
package/docs/type-contracts.md
CHANGED
|
@@ -17,12 +17,12 @@ public-signature artifact.
|
|
|
17
17
|
| `KUI-T002` | `Select` has a visible `label` or an `ariaLabel`. |
|
|
18
18
|
| `KUI-T003` | A literal `Select.value` belongs to its literal `choices`. |
|
|
19
19
|
| `KUI-T004` | A literal `SegmentedControl.value` belongs to its literal `choices`. |
|
|
20
|
-
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `
|
|
21
|
-
| `KUI-T006` | `
|
|
20
|
+
| `KUI-T005` | `expanded`, `expandAction`, and `expandLabel` exist only on `SearchField({ collapsible: true })`. |
|
|
21
|
+
| `KUI-T006` | `SearchFieldEditorAttributes` accepts application `data-*` metadata but rejects component-owned identity, morph, count, and placeholder attributes. |
|
|
22
22
|
| `KUI-T007` | `ToolbarText.maxLines` requires `wrap: true`; it is never silently ignored in typed code. |
|
|
23
23
|
| `KUI-T008` | A literal `TabNavigator.active` id belongs to its literal `tabs`. |
|
|
24
24
|
| `KUI-T009` | Adjacent-token keyboard removal requires `onRemoveToken`; disabling removal rejects the now-meaningless callback. |
|
|
25
|
-
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all
|
|
25
|
+
| `KUI-T010` | Finite public variants have named exported union types, including divider sides, tab activation, banner urgency, and all TabBarItem, TabBar, ToolbarControlGroup, and Select presentation axes; the convenience root barrel re-exports them. |
|
|
26
26
|
| `KUI-T011` | Semantic component zones use the recursive `KerfUiContent` type: `SafeHtml`, runtime-empty booleans/nullish values, and readonly nested arrays are valid; arbitrary strings, numbers, and signals are rejected. Explicit text positions such as `ListInsetText` retain their text exception. |
|
|
27
27
|
| `KUI-T012` | `List.gap` accepts finite `UiSpaceName` shorthands or a complete branded `CssLength`; raw strings and non-standalone `CssLengthExpression` arithmetic are rejected. `calc(plus(...))` promotes a typed expression to a complete value. |
|
|
28
28
|
| `KUI-T013` | CSS-valued props preserve property grammar: `List.flex` uses `CssFlex`, `Skeleton` dimensions use `CssSize`/`CssLength`, and choice icons and `LucideIcon.color` use `CssForegroundColor` (foreground tokens via `uiColor()`, `foregroundColorVar()`, or custom values via `foregroundColor()`; fill tokens such as `uiColor('success-fill-quiet')` are rejected); a row `iconTile` is a finite tone or a `CssColor` fill (custom values via `fillColor()`) with an optional `CssForegroundColor` glyph, and a `ChoiceChips` swatch is a `CssColor` fill (`fillColor()`, `uiColor()`, `colorVar()`) or `'transparent'`; a `fillColor()` value is a plain `CssColor` and is rejected where a `CssForegroundColor` is required; row declaration strings are absent. |
|
|
@@ -62,9 +62,9 @@ dataset. Do not cast a known literal typo merely to bypass the relationship.
|
|
|
62
62
|
The following existing contracts were already exact and remain covered by the
|
|
63
63
|
ordinary source/type gates:
|
|
64
64
|
|
|
65
|
-
- required identity or accessible-name inputs on `
|
|
65
|
+
- required identity or accessible-name inputs on `TabBarItem`, `FloatingToolbar`,
|
|
66
66
|
`NavStack`, `SplitView`, `Workbench`, `TabBar`, `ResizableRegion`,
|
|
67
|
-
`SegmentedControl`, `
|
|
67
|
+
`SegmentedControl`, `SearchField`, and `ValueTable`;
|
|
68
68
|
- finite variants exported or represented as literal props on `DisclosureArrow`,
|
|
69
69
|
`FloatingToolbar`, `Pane`, `ResizableRegion`, `SegmentedControl`, `StateBanner`,
|
|
70
70
|
`SunkenPanel`, `ToolbarText`, `CollapsiblePanel`, `Catalog`, and the wire helpers;
|
|
@@ -73,7 +73,7 @@ ordinary source/type gates:
|
|
|
73
73
|
`wireWorkbench`;
|
|
74
74
|
- a `ListHeader` count requires `countLabel` and excludes badge/status, while
|
|
75
75
|
badge and status can appear together or be explicitly `undefined`; and
|
|
76
|
-
- protected application metadata boundaries on `
|
|
76
|
+
- protected application metadata boundaries on `TabBarItem`, `ListItem`,
|
|
77
77
|
`ListActionRow`, `ListHeader`, `Pane`, `CatalogExample`, and
|
|
78
78
|
`CatalogExampleStack`.
|
|
79
79
|
|
|
@@ -88,7 +88,7 @@ unnamed non-landmark surfaces are intentional variants, not missing contracts.
|
|
|
88
88
|
|
|
89
89
|
Types do not claim to validate:
|
|
90
90
|
|
|
91
|
-
- the contents of `SafeHtml` slots (for example, “only
|
|
91
|
+
- the contents of `SafeHtml` slots (for example, “only TabBarItem children” or “no
|
|
92
92
|
interactive descendants”);
|
|
93
93
|
- nonempty arrays, unique ids, numeric min/max ordering, or a controlled value
|
|
94
94
|
loaded from dynamic data;
|
|
@@ -109,7 +109,7 @@ move errors into casts without making the integration safer.
|
|
|
109
109
|
- Give every `Select` either `label` or `ariaLabel`. Use an explicit `<string>`
|
|
110
110
|
generic only for genuinely dynamic choice data.
|
|
111
111
|
- Put `expanded`/expand-action props behind `collapsible: true`.
|
|
112
|
-
- Replace `
|
|
112
|
+
- Replace `wireSearchFields({ keyboard: true })` with either
|
|
113
113
|
`{ keyboard: { onRemoveToken } }` or
|
|
114
114
|
`{ keyboard: { removeAdjacentToken: false } }` when only caret navigation is
|
|
115
115
|
wanted.
|
package/docs/ui-analyzer.md
CHANGED
|
@@ -138,7 +138,7 @@ rejecting every stylesheet attached to a `kind: composition` catalog entry.
|
|
|
138
138
|
`.kui-list-item__label`, `.acme-meter`), its `[data-component="…"]` root, or
|
|
139
139
|
a Web Awesome tag the package themes (`wa-button`, `wa-select`), and the rule
|
|
140
140
|
sets at least one ordinary property. It also catches a raw descendant of
|
|
141
|
-
cataloged component anatomy, such as `.kui-
|
|
141
|
+
cataloged component anatomy, such as `.kui-tab-bar-item__select > svg`, even when
|
|
142
142
|
the component class is not the final compound. A component root used only as
|
|
143
143
|
context (`.kui-toolbar > .my-widget`) and app-named descendants remain
|
|
144
144
|
available for app-owned content. In component mode, classless element subjects
|