@ui-sdk/web 0.0.0-stage → 0.1.0-beta.1
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/LICENSE +202 -0
- package/README.md +10 -2
- package/browser/web/accordion.js +1 -0
- package/browser/web/alert-dialog.js +1 -0
- package/browser/web/autocomplete.js +1 -0
- package/browser/web/avatar.js +1 -0
- package/browser/web/button.js +1 -0
- package/browser/web/calendar.js +1 -0
- package/browser/web/carousel.js +1 -0
- package/browser/web/checkbox.js +1 -0
- package/browser/web/chunks/0eRGibL6.js +1 -0
- package/browser/web/chunks/2bIEUO6_.js +1 -0
- package/browser/web/chunks/5A9w2ULz.js +1 -0
- package/browser/web/chunks/5RSyydjV.js +1 -0
- package/browser/web/chunks/9pWTy2wl.js +1 -0
- package/browser/web/chunks/B0f2j6zz.js +1 -0
- package/browser/web/chunks/B1rux6br.js +1 -0
- package/browser/web/chunks/B3-APaNf.js +1 -0
- package/browser/web/chunks/B7EgSgjQ.js +1 -0
- package/browser/web/chunks/B8QcOzJU.js +1 -0
- package/browser/web/chunks/BFueEkwm.js +3 -0
- package/browser/web/chunks/BJj3oS29.js +1 -0
- package/browser/web/chunks/BNSvTCpr.js +1 -0
- package/browser/web/chunks/BPD0kAZB.js +1 -0
- package/browser/web/chunks/BQeduZqT.js +1 -0
- package/browser/web/chunks/B_CVFyiz.js +1 -0
- package/browser/web/chunks/B_ns1YHO.js +1 -0
- package/browser/web/chunks/BcwkVTsR.js +1 -0
- package/browser/web/chunks/BeaQ6TYM.js +1 -0
- package/browser/web/chunks/BgBB013u.js +1 -0
- package/browser/web/chunks/BgsKhHDm.js +1 -0
- package/browser/web/chunks/BjMcbuhi.js +9 -0
- package/browser/web/chunks/Bjiy_F2N.js +1 -0
- package/browser/web/chunks/BqScCLwv.js +1 -0
- package/browser/web/chunks/BqX3Utqx.js +1 -0
- package/browser/web/chunks/BtVkQf3z.js +1 -0
- package/browser/web/chunks/By30h-7B.js +1 -0
- package/browser/web/chunks/C1zqYpy2.js +1 -0
- package/browser/web/chunks/C436juFf.js +1 -0
- package/browser/web/chunks/C4_bULs1.js +1 -0
- package/browser/web/chunks/C4omqJEz.js +1 -0
- package/browser/web/chunks/C7tt0T3n.js +1 -0
- package/browser/web/chunks/C8w7s5dg.js +1 -0
- package/browser/web/chunks/CElY4erO.js +1 -0
- package/browser/web/chunks/CFODo-m2.js +1 -0
- package/browser/web/chunks/CL4wjam9.js +1 -0
- package/browser/web/chunks/CMg-8UVf.js +1 -0
- package/browser/web/chunks/COWKfakj.js +1 -0
- package/browser/web/chunks/CQBU0qZ4.js +1 -0
- package/browser/web/chunks/CV6uABgc.js +1 -0
- package/browser/web/chunks/C_SWFpWQ.js +1 -0
- package/browser/web/chunks/C_Uanbrl.js +1 -0
- package/browser/web/chunks/Ce_CSanC.js +1 -0
- package/browser/web/chunks/Cg-ZmRhS.js +1 -0
- package/browser/web/chunks/Cgf2wPI_.js +1 -0
- package/browser/web/chunks/Cuep_3Vf.js +1 -0
- package/browser/web/chunks/D02PaHn6.js +1 -0
- package/browser/web/chunks/D5LiaI5R.js +1 -0
- package/browser/web/chunks/D9UgVYvF.js +1 -0
- package/browser/web/chunks/DC08tnkE.js +2 -0
- package/browser/web/chunks/DG8YGSvu.js +1 -0
- package/browser/web/chunks/DIQd0FYD.js +1 -0
- package/browser/web/chunks/DMLqacE8.js +1 -0
- package/browser/web/chunks/DSUI3yI-.js +1 -0
- package/browser/web/chunks/DT3Hb76X.js +1 -0
- package/browser/web/chunks/DY75g3-W.js +1 -0
- package/browser/web/chunks/DZpNQKZ9.js +1 -0
- package/browser/web/chunks/Db-W1wrC.js +1 -0
- package/browser/web/chunks/Dc1xK3Ii.js +1 -0
- package/browser/web/chunks/DdF6awFs.js +1 -0
- package/browser/web/chunks/DdaCLml8.js +1 -0
- package/browser/web/chunks/Dh8MLjQO.js +1 -0
- package/browser/web/chunks/DiuslJRy.js +1 -0
- package/browser/web/chunks/DjRcw3Y0.js +1 -0
- package/browser/web/chunks/Djdv-16J.js +1 -0
- package/browser/web/chunks/DnFXe_lF.js +1 -0
- package/browser/web/chunks/DneGv1oC.js +1 -0
- package/browser/web/chunks/DsVxP-p-.js +1 -0
- package/browser/web/chunks/DwDilCo2.js +1 -0
- package/browser/web/chunks/DwV48AXv.js +1 -0
- package/browser/web/chunks/F37aF4-L.js +1 -0
- package/browser/web/chunks/LyB6XIbN.js +1 -0
- package/browser/web/chunks/NKnbYGjC.js +1 -0
- package/browser/web/chunks/Vk-rVi16.js +1 -0
- package/browser/web/chunks/XsM0J1Ex.js +1 -0
- package/browser/web/chunks/asSN9iEp.js +1 -0
- package/browser/web/chunks/c-AjHfdF.js +1 -0
- package/browser/web/chunks/dR-12TPY.js +1 -0
- package/browser/web/chunks/hR4xM0EC.js +1 -0
- package/browser/web/chunks/hqOaBxAg.js +1 -0
- package/browser/web/chunks/kMKqqeG4.js +1 -0
- package/browser/web/chunks/kXboBcfi.js +1 -0
- package/browser/web/chunks/l4aQIg22.js +1 -0
- package/browser/web/chunks/tJC0JSU4.js +1 -0
- package/browser/web/chunks/wHdS_QYM.js +1 -0
- package/browser/web/chunks/yv8dTvNI.js +1 -0
- package/browser/web/chunks/yw9M3nfi.js +1 -0
- package/browser/web/collapsible.js +1 -0
- package/browser/web/color-picker.js +1 -0
- package/browser/web/combobox.js +2 -0
- package/browser/web/command.js +1 -0
- package/browser/web/core.js +5 -0
- package/browser/web/date-input.js +1 -0
- package/browser/web/date-picker.js +1 -0
- package/browser/web/dialog.js +1 -0
- package/browser/web/drawer.js +1 -0
- package/browser/web/field.js +1 -0
- package/browser/web/file-input.js +1 -0
- package/browser/web/hover-card.js +1 -0
- package/browser/web/image-cropper.js +1 -0
- package/browser/web/input.js +1 -0
- package/browser/web/label.js +1 -0
- package/browser/web/listbox.js +1 -0
- package/browser/web/menu.js +1 -0
- package/browser/web/menubar.js +1 -0
- package/browser/web/meter.js +1 -0
- package/browser/web/navigation-menu.js +1 -0
- package/browser/web/number-input.js +1 -0
- package/browser/web/otp-input.js +2 -0
- package/browser/web/overlays.js +1 -0
- package/browser/web/pagination.js +1 -0
- package/browser/web/password-input.js +1 -0
- package/browser/web/popover.js +1 -0
- package/browser/web/preferences.js +1 -0
- package/browser/web/progress.js +1 -0
- package/browser/web/radio.js +1 -0
- package/browser/web/rating.js +1 -0
- package/browser/web/resizable.js +1 -0
- package/browser/web/scroll-area.js +1 -0
- package/browser/web/segmented-control.js +1 -0
- package/browser/web/select.js +1 -0
- package/browser/web/separator.js +1 -0
- package/browser/web/slider.js +1 -0
- package/browser/web/switch.js +1 -0
- package/browser/web/tabs.js +1 -0
- package/browser/web/textarea.js +1 -0
- package/browser/web/time-input.js +1 -0
- package/browser/web/timeline.js +1 -0
- package/browser/web/toast.js +1 -0
- package/browser/web/toggle.js +1 -0
- package/browser/web/token-input.js +8 -0
- package/browser/web/toolbar.js +1 -0
- package/browser/web/tooltip.js +1 -0
- package/browser/web/tree.js +1 -0
- package/browser/web/trigger-menu.js +4 -0
- package/browser/web/waterfall.js +1 -0
- package/browser/web.css +3378 -0
- package/browser/web.js +3 -0
- package/custom-elements.json +32315 -0
- package/dist/accordion.d.ts +2 -0
- package/dist/accordion.js +57 -0
- package/dist/action.d.ts +16 -0
- package/dist/action.js +39 -0
- package/dist/agent.d.ts +2 -0
- package/dist/agent.js +7 -0
- package/dist/autocomplete.d.ts +2 -0
- package/dist/autocomplete.js +120 -0
- package/dist/autoload.d.ts +18 -0
- package/dist/autoload.js +63 -0
- package/dist/avatar.d.ts +2 -0
- package/dist/avatar.js +27 -0
- package/dist/browser-core.d.ts +2 -0
- package/dist/browser-core.js +8 -0
- package/dist/button.d.ts +2 -0
- package/dist/button.js +35 -0
- package/dist/calendar.d.ts +23 -0
- package/dist/calendar.js +429 -0
- package/dist/carousel.d.ts +2 -0
- package/dist/carousel.js +54 -0
- package/dist/checkbox.d.ts +4 -0
- package/dist/checkbox.js +75 -0
- package/dist/collapsible.d.ts +2 -0
- package/dist/collapsible.js +28 -0
- package/dist/color-picker.d.ts +2 -0
- package/dist/color-picker.js +64 -0
- package/dist/combobox.d.ts +2 -0
- package/dist/combobox.js +334 -0
- package/dist/command.d.ts +2 -0
- package/dist/command.js +122 -0
- package/dist/date-input.d.ts +3 -0
- package/dist/date-input.js +87 -0
- package/dist/date-picker.d.ts +2 -0
- package/dist/date-picker.js +174 -0
- package/dist/default-text.d.ts +3 -0
- package/dist/default-text.js +24 -0
- package/dist/define-element.d.ts +404 -0
- package/dist/define-element.js +1489 -0
- package/dist/dialog.d.ts +3 -0
- package/dist/dialog.js +94 -0
- package/dist/drawer.d.ts +2 -0
- package/dist/drawer.js +96 -0
- package/dist/entries/accordion.d.ts +3 -0
- package/dist/entries/accordion.js +7 -0
- package/dist/entries/alert-dialog.d.ts +3 -0
- package/dist/entries/alert-dialog.js +13 -0
- package/dist/entries/autocomplete.d.ts +3 -0
- package/dist/entries/autocomplete.js +7 -0
- package/dist/entries/avatar.d.ts +2 -0
- package/dist/entries/avatar.js +3 -0
- package/dist/entries/button.d.ts +2 -0
- package/dist/entries/button.js +3 -0
- package/dist/entries/calendar.d.ts +3 -0
- package/dist/entries/calendar.js +7 -0
- package/dist/entries/carousel.d.ts +3 -0
- package/dist/entries/carousel.js +7 -0
- package/dist/entries/checkbox.d.ts +3 -0
- package/dist/entries/checkbox.js +15 -0
- package/dist/entries/collapsible.d.ts +3 -0
- package/dist/entries/collapsible.js +7 -0
- package/dist/entries/color-picker.d.ts +3 -0
- package/dist/entries/color-picker.js +7 -0
- package/dist/entries/combobox.d.ts +3 -0
- package/dist/entries/combobox.js +7 -0
- package/dist/entries/command.d.ts +3 -0
- package/dist/entries/command.js +7 -0
- package/dist/entries/date-input.d.ts +3 -0
- package/dist/entries/date-input.js +7 -0
- package/dist/entries/date-picker.d.ts +3 -0
- package/dist/entries/date-picker.js +7 -0
- package/dist/entries/dialog.d.ts +3 -0
- package/dist/entries/dialog.js +7 -0
- package/dist/entries/drawer.d.ts +3 -0
- package/dist/entries/drawer.js +8 -0
- package/dist/entries/field.d.ts +2 -0
- package/dist/entries/field.js +3 -0
- package/dist/entries/file-input.d.ts +3 -0
- package/dist/entries/file-input.js +13 -0
- package/dist/entries/hover-card.d.ts +3 -0
- package/dist/entries/hover-card.js +7 -0
- package/dist/entries/image-cropper.d.ts +3 -0
- package/dist/entries/image-cropper.js +7 -0
- package/dist/entries/input.d.ts +3 -0
- package/dist/entries/input.js +8 -0
- package/dist/entries/label.d.ts +2 -0
- package/dist/entries/label.js +3 -0
- package/dist/entries/listbox.d.ts +3 -0
- package/dist/entries/listbox.js +7 -0
- package/dist/entries/menu.d.ts +3 -0
- package/dist/entries/menu.js +7 -0
- package/dist/entries/menubar.d.ts +3 -0
- package/dist/entries/menubar.js +7 -0
- package/dist/entries/meter.d.ts +2 -0
- package/dist/entries/meter.js +3 -0
- package/dist/entries/navigation-menu.d.ts +3 -0
- package/dist/entries/navigation-menu.js +7 -0
- package/dist/entries/number-input.d.ts +3 -0
- package/dist/entries/number-input.js +7 -0
- package/dist/entries/otp-input.d.ts +3 -0
- package/dist/entries/otp-input.js +7 -0
- package/dist/entries/overlays.d.ts +2 -0
- package/dist/entries/overlays.js +3 -0
- package/dist/entries/pagination.d.ts +3 -0
- package/dist/entries/pagination.js +11 -0
- package/dist/entries/password-input.d.ts +3 -0
- package/dist/entries/password-input.js +7 -0
- package/dist/entries/popover.d.ts +3 -0
- package/dist/entries/popover.js +7 -0
- package/dist/entries/preferences.d.ts +3 -0
- package/dist/entries/preferences.js +13 -0
- package/dist/entries/progress.d.ts +2 -0
- package/dist/entries/progress.js +3 -0
- package/dist/entries/radio.d.ts +3 -0
- package/dist/entries/radio.js +7 -0
- package/dist/entries/rating.d.ts +3 -0
- package/dist/entries/rating.js +8 -0
- package/dist/entries/resizable.d.ts +3 -0
- package/dist/entries/resizable.js +11 -0
- package/dist/entries/scroll-area.d.ts +3 -0
- package/dist/entries/scroll-area.js +7 -0
- package/dist/entries/segmented-control.d.ts +3 -0
- package/dist/entries/segmented-control.js +7 -0
- package/dist/entries/select.d.ts +3 -0
- package/dist/entries/select.js +7 -0
- package/dist/entries/separator.d.ts +2 -0
- package/dist/entries/separator.js +3 -0
- package/dist/entries/slider.d.ts +3 -0
- package/dist/entries/slider.js +7 -0
- package/dist/entries/switch.d.ts +3 -0
- package/dist/entries/switch.js +7 -0
- package/dist/entries/tabs.d.ts +3 -0
- package/dist/entries/tabs.js +7 -0
- package/dist/entries/textarea.d.ts +3 -0
- package/dist/entries/textarea.js +7 -0
- package/dist/entries/time-input.d.ts +3 -0
- package/dist/entries/time-input.js +7 -0
- package/dist/entries/timeline.d.ts +3 -0
- package/dist/entries/timeline.js +7 -0
- package/dist/entries/toast.d.ts +2 -0
- package/dist/entries/toast.js +3 -0
- package/dist/entries/toggle.d.ts +3 -0
- package/dist/entries/toggle.js +12 -0
- package/dist/entries/token-input.d.ts +3 -0
- package/dist/entries/token-input.js +17 -0
- package/dist/entries/toolbar.d.ts +3 -0
- package/dist/entries/toolbar.js +7 -0
- package/dist/entries/tooltip.d.ts +3 -0
- package/dist/entries/tooltip.js +7 -0
- package/dist/entries/tree.d.ts +3 -0
- package/dist/entries/tree.js +17 -0
- package/dist/entries/trigger-menu.d.ts +3 -0
- package/dist/entries/trigger-menu.js +11 -0
- package/dist/entries/waterfall.d.ts +3 -0
- package/dist/entries/waterfall.js +11 -0
- package/dist/events.d.ts +1658 -0
- package/dist/events.js +0 -0
- package/dist/field.d.ts +2 -0
- package/dist/field.js +101 -0
- package/dist/file-input.d.ts +2 -0
- package/dist/file-input.js +140 -0
- package/dist/forward-attributes.d.ts +2 -0
- package/dist/forward-attributes.js +22 -0
- package/dist/history.d.ts +2 -0
- package/dist/history.js +11 -0
- package/dist/hover-card.d.ts +2 -0
- package/dist/hover-card.js +31 -0
- package/dist/image-cropper.d.ts +2 -0
- package/dist/image-cropper.js +66 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +269 -0
- package/dist/input.d.ts +3 -0
- package/dist/input.js +69 -0
- package/dist/label.d.ts +2 -0
- package/dist/label.js +11 -0
- package/dist/list.d.ts +40 -0
- package/dist/list.js +192 -0
- package/dist/listbox.d.ts +2 -0
- package/dist/listbox.js +84 -0
- package/dist/menu.d.ts +4 -0
- package/dist/menu.js +295 -0
- package/dist/menubar.d.ts +4 -0
- package/dist/menubar.js +30 -0
- package/dist/meter.d.ts +2 -0
- package/dist/meter.js +22 -0
- package/dist/navigation-menu.d.ts +2 -0
- package/dist/navigation-menu.js +114 -0
- package/dist/number-input.d.ts +2 -0
- package/dist/number-input.js +73 -0
- package/dist/observe.d.ts +2 -0
- package/dist/observe.js +7 -0
- package/dist/otp-input.d.ts +2 -0
- package/dist/otp-input.js +72 -0
- package/dist/overlays.d.ts +13 -0
- package/dist/overlays.js +156 -0
- package/dist/pagination.d.ts +2 -0
- package/dist/pagination.js +127 -0
- package/dist/password-input.d.ts +2 -0
- package/dist/password-input.js +57 -0
- package/dist/popover.d.ts +2 -0
- package/dist/popover.js +64 -0
- package/dist/popup.d.ts +40 -0
- package/dist/popup.js +112 -0
- package/dist/preferences.d.ts +2 -0
- package/dist/preferences.js +56 -0
- package/dist/progress.d.ts +2 -0
- package/dist/progress.js +22 -0
- package/dist/radio.d.ts +2 -0
- package/dist/radio.js +33 -0
- package/dist/rating.d.ts +2 -0
- package/dist/rating.js +64 -0
- package/dist/resizable.d.ts +2 -0
- package/dist/resizable.js +42 -0
- package/dist/scroll-area.d.ts +2 -0
- package/dist/scroll-area.js +45 -0
- package/dist/segmented-control.d.ts +2 -0
- package/dist/segmented-control.js +28 -0
- package/dist/select.d.ts +2 -0
- package/dist/select.js +239 -0
- package/dist/separator.d.ts +2 -0
- package/dist/separator.js +11 -0
- package/dist/slider.d.ts +2 -0
- package/dist/slider.js +77 -0
- package/dist/tabs.d.ts +2 -0
- package/dist/tabs.js +37 -0
- package/dist/timeline.d.ts +2 -0
- package/dist/timeline.js +27 -0
- package/dist/toast.d.ts +20 -0
- package/dist/toast.js +177 -0
- package/dist/toggle.d.ts +3 -0
- package/dist/toggle.js +64 -0
- package/dist/token-input.d.ts +2 -0
- package/dist/token-input.js +103 -0
- package/dist/toolbar.d.ts +2 -0
- package/dist/toolbar.js +36 -0
- package/dist/tooltip.d.ts +2 -0
- package/dist/tooltip.js +35 -0
- package/dist/tree.d.ts +2 -0
- package/dist/tree.js +147 -0
- package/dist/trigger-menu.d.ts +2 -0
- package/dist/trigger-menu.js +133 -0
- package/dist/waterfall.d.ts +2 -0
- package/dist/waterfall.js +140 -0
- package/docs/README.md +89 -0
- package/docs/agents.md +1523 -0
- package/docs/components/accordion.md +1401 -0
- package/docs/components/alert-dialog.md +788 -0
- package/docs/components/autocomplete.md +1692 -0
- package/docs/components/avatar.md +261 -0
- package/docs/components/button.md +441 -0
- package/docs/components/calendar.md +1536 -0
- package/docs/components/carousel.md +1055 -0
- package/docs/components/checkbox.md +1045 -0
- package/docs/components/collapsible.md +535 -0
- package/docs/components/color-picker.md +651 -0
- package/docs/components/combobox.md +3274 -0
- package/docs/components/command.md +1431 -0
- package/docs/components/date-input.md +563 -0
- package/docs/components/date-picker.md +1136 -0
- package/docs/components/dialog.md +1360 -0
- package/docs/components/drawer.md +1201 -0
- package/docs/components/field.md +519 -0
- package/docs/components/file-input.md +617 -0
- package/docs/components/hover-card.md +486 -0
- package/docs/components/image-cropper.md +489 -0
- package/docs/components/input.md +327 -0
- package/docs/components/label.md +208 -0
- package/docs/components/listbox.md +1015 -0
- package/docs/components/menu.md +1212 -0
- package/docs/components/menubar.md +460 -0
- package/docs/components/meter.md +298 -0
- package/docs/components/navigation-menu.md +1573 -0
- package/docs/components/number-input.md +1087 -0
- package/docs/components/otp-input.md +558 -0
- package/docs/components/pagination.md +639 -0
- package/docs/components/password-input.md +649 -0
- package/docs/components/popover.md +1433 -0
- package/docs/components/preferences.md +243 -0
- package/docs/components/progress.md +406 -0
- package/docs/components/radio.md +855 -0
- package/docs/components/rating.md +431 -0
- package/docs/components/resizable.md +866 -0
- package/docs/components/scroll-area.md +898 -0
- package/docs/components/segmented-control.md +421 -0
- package/docs/components/select.md +1957 -0
- package/docs/components/separator.md +238 -0
- package/docs/components/slider.md +1018 -0
- package/docs/components/switch.md +583 -0
- package/docs/components/tabs.md +948 -0
- package/docs/components/textarea.md +331 -0
- package/docs/components/time-input.md +235 -0
- package/docs/components/timeline.md +622 -0
- package/docs/components/toast.md +1223 -0
- package/docs/components/toggle.md +522 -0
- package/docs/components/token-input.md +854 -0
- package/docs/components/toolbar.md +815 -0
- package/docs/components/tooltip.md +860 -0
- package/docs/components/tree.md +1243 -0
- package/docs/components/trigger-menu.md +1110 -0
- package/docs/components/waterfall.md +709 -0
- package/docs/controllers.md +66 -0
- package/docs/core.md +8027 -0
- package/docs/custom-parts.md +91 -0
- package/docs/first-component.md +88 -0
- package/docs/forms.md +125 -0
- package/docs/installation.md +141 -0
- package/docs/introduction.md +32 -0
- package/docs/lists-and-menus.md +166 -0
- package/docs/llms.txt +1566 -0
- package/docs/parts-and-composition.md +57 -0
- package/docs/popups.md +92 -0
- package/docs/rendering.md +71 -0
- package/docs/server-rendering.md +118 -0
- package/docs/state-and-events.md +134 -0
- package/docs/styling-and-animation.md +104 -0
- package/docs/utilities/async-options.md +332 -0
- package/docs/utilities/shortcuts.md +184 -0
- package/html-custom-data.json +14792 -0
- package/package.json +302 -3
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Preferences
|
|
2
|
+
|
|
3
|
+
Apply user preferences to data attributes so your styles can follow them.
|
|
4
|
+
|
|
5
|
+
`<ui-preferences>` puts your preferences on `data-*` attributes and keeps them up to date. Use it around a part of your app, or apply a preference to the whole page.
|
|
6
|
+
|
|
7
|
+
```ts title="basic.ts"
|
|
8
|
+
import { createLocalStorage, createPreference } from "@ui-sdk/core"
|
|
9
|
+
import "@ui-sdk/web/button"
|
|
10
|
+
import "@ui-sdk/web/preferences"
|
|
11
|
+
import { log } from "./log"
|
|
12
|
+
|
|
13
|
+
const view = createPreference({
|
|
14
|
+
values: ["list", "grid"],
|
|
15
|
+
defaultValue: "list",
|
|
16
|
+
attribute: "data-view",
|
|
17
|
+
storage: createLocalStorage("ui-sdk-preferences-view"),
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const files = [
|
|
21
|
+
{ name: "Q3 roadmap.pdf", detail: "2.4 MB" },
|
|
22
|
+
{ name: "Launch checklist.md", detail: "12 KB" },
|
|
23
|
+
{ name: "Offsite photos", detail: "24 items" },
|
|
24
|
+
{ name: "Brand assets.zip", detail: "18 MB" },
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
function mount(root: HTMLElement) {
|
|
28
|
+
root.innerHTML = `
|
|
29
|
+
<ui-preferences>
|
|
30
|
+
<div data-slot="stack">
|
|
31
|
+
<div data-slot="controls" role="group" aria-label="View">
|
|
32
|
+
<ui-button><button type="button" data-value="list">List</button></ui-button>
|
|
33
|
+
<ui-button><button type="button" data-value="grid">Grid</button></ui-button>
|
|
34
|
+
</div>
|
|
35
|
+
<ul data-slot="files" aria-label="Files">
|
|
36
|
+
${files.map((file) => `<li><span>${file.name}</span><span data-slot="hint">${file.detail}</span></li>`).join("")}
|
|
37
|
+
</ul>
|
|
38
|
+
</div>
|
|
39
|
+
</ui-preferences>
|
|
40
|
+
`
|
|
41
|
+
|
|
42
|
+
const preferences = root.querySelector("ui-preferences")!
|
|
43
|
+
const buttons = [...root.querySelectorAll<HTMLButtonElement>("[data-value]")]
|
|
44
|
+
preferences.preferences = [view]
|
|
45
|
+
|
|
46
|
+
const update = () => {
|
|
47
|
+
const { value } = view.get()
|
|
48
|
+
for (const button of buttons) {
|
|
49
|
+
button.setAttribute(
|
|
50
|
+
"aria-pressed",
|
|
51
|
+
String(button.dataset.value === value)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const choose = (event: MouseEvent) => {
|
|
56
|
+
const next = (event.currentTarget as HTMLButtonElement).dataset.value as
|
|
57
|
+
"list" | "grid"
|
|
58
|
+
view.set(next, { reason: "press", event })
|
|
59
|
+
log(root, `Saved the ${next} view`)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stop = view.subscribe(update)
|
|
63
|
+
update()
|
|
64
|
+
for (const button of buttons) {
|
|
65
|
+
button.addEventListener("click", choose)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return () => {
|
|
69
|
+
stop()
|
|
70
|
+
for (const button of buttons) {
|
|
71
|
+
button.removeEventListener("click", choose)
|
|
72
|
+
}
|
|
73
|
+
preferences.preferences = []
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { mount }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Choose Grid, then reload the page. The files come back in the view you chose, and the console logs each change.
|
|
81
|
+
|
|
82
|
+
## Installation
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm install @ui-sdk/web @ui-sdk/core
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Import the component once to register its element:
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import "@ui-sdk/web/preferences"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
Define the preference you want to apply. Here, `view` chooses how a file list is laid out:
|
|
97
|
+
|
|
98
|
+
```ts title="preferences.ts"
|
|
99
|
+
import { createPreference } from "@ui-sdk/core"
|
|
100
|
+
|
|
101
|
+
const view = createPreference({
|
|
102
|
+
values: ["list", "grid"],
|
|
103
|
+
defaultValue: "list",
|
|
104
|
+
attribute: "data-view",
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
export { view }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Wrap the content in `<ui-preferences>`, then style it by the preference's attribute:
|
|
111
|
+
|
|
112
|
+
```html title="file-list.html"
|
|
113
|
+
<ui-preferences>
|
|
114
|
+
<ul data-slot="files">
|
|
115
|
+
<li>Q3 roadmap.pdf</li>
|
|
116
|
+
<li>Launch checklist.md</li>
|
|
117
|
+
</ul>
|
|
118
|
+
</ui-preferences>
|
|
119
|
+
<script type="module" src="./file-list.ts"></script>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Set the element's `preferences` property to your list:
|
|
123
|
+
|
|
124
|
+
```ts title="file-list.ts"
|
|
125
|
+
import "@ui-sdk/web/preferences"
|
|
126
|
+
import { view } from "./preferences"
|
|
127
|
+
|
|
128
|
+
const preferences = document.querySelector("ui-preferences")!
|
|
129
|
+
preferences.preferences = [view]
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
```css
|
|
133
|
+
[data-view="grid"] [data-slot="files"] {
|
|
134
|
+
display: grid;
|
|
135
|
+
grid-template-columns: repeat(2, 1fr);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The element starts with `data-view="list"`. Calling `view.set("grid")` updates it, and the list becomes a grid. `<ui-preferences>` renders with `display: contents`, so it adds no box of its own.
|
|
140
|
+
|
|
141
|
+
## Save the Value
|
|
142
|
+
|
|
143
|
+
Add `storage` to save the choice between visits:
|
|
144
|
+
|
|
145
|
+
```ts title="preferences.ts"
|
|
146
|
+
import { createLocalStorage, createPreference } from "@ui-sdk/core"
|
|
147
|
+
|
|
148
|
+
const view = createPreference({
|
|
149
|
+
values: ["list", "grid"],
|
|
150
|
+
defaultValue: "list",
|
|
151
|
+
attribute: "data-view",
|
|
152
|
+
storage: createLocalStorage("ui-sdk-preferences-view"),
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
export { view }
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The preference now saves changes in local storage and restores the saved value when the page reloads. You can also [use session storage or cookies with `createPreference`](../core.md#remember-the-choice).
|
|
159
|
+
|
|
160
|
+
## Read the Value
|
|
161
|
+
|
|
162
|
+
Use `get()` and `subscribe()` when the value affects your content. This function keeps a Grid button pressed while the grid view is on, toggles the view when it's pressed and returns its cleanup:
|
|
163
|
+
|
|
164
|
+
```ts title="view-switch.ts"
|
|
165
|
+
import { view } from "./preferences"
|
|
166
|
+
|
|
167
|
+
function bindViewSwitch(button: HTMLButtonElement) {
|
|
168
|
+
const update = () => {
|
|
169
|
+
button.setAttribute("aria-pressed", String(view.get().value === "grid"))
|
|
170
|
+
}
|
|
171
|
+
const toggle = () => view.set(view.get().value === "grid" ? "list" : "grid")
|
|
172
|
+
|
|
173
|
+
const stop = view.subscribe(update)
|
|
174
|
+
update()
|
|
175
|
+
button.addEventListener("click", toggle)
|
|
176
|
+
return () => {
|
|
177
|
+
stop()
|
|
178
|
+
button.removeEventListener("click", toggle)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export { bindViewSwitch }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Call `bindViewSwitch(button)` when the button mounts, and call the returned function when it is removed. Pass the same preference instance wherever you need its value. Subscriptions also work outside `<ui-preferences>`.
|
|
186
|
+
|
|
187
|
+
## Apply to the Whole Page
|
|
188
|
+
|
|
189
|
+
Set `global: true` when defining the preference:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const view = createPreference({
|
|
193
|
+
values: ["list", "grid"],
|
|
194
|
+
defaultValue: "list",
|
|
195
|
+
attribute: "data-view",
|
|
196
|
+
global: true,
|
|
197
|
+
storage: createLocalStorage("ui-sdk-preferences-view"),
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Keep assigning it to `<ui-preferences>`. Its attribute now goes on `<html>`, so styles throughout the page can use it. A global preference needs only one connected `<ui-preferences>` element to apply it.
|
|
202
|
+
|
|
203
|
+
## Multiple Preferences
|
|
204
|
+
|
|
205
|
+
Assign more than one preference in the list. For example, you can apply `view` alongside a [color scheme](../core.md#choose-a-color-scheme):
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { createColorScheme } from "@ui-sdk/core"
|
|
209
|
+
|
|
210
|
+
const colorScheme = createColorScheme()
|
|
211
|
+
|
|
212
|
+
preferences.preferences = [view, colorScheme]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Each preference uses its own attribute and `global` option. Wrappers that share a preference instance follow the same value. For independent choices, use separate preference instances and different storage keys.
|
|
216
|
+
|
|
217
|
+
## Server Rendering
|
|
218
|
+
|
|
219
|
+
To apply saved values before the page paints, write `preferencesScript([...])` into your server-rendered HTML as the element's first child:
|
|
220
|
+
|
|
221
|
+
```ts title="server.ts"
|
|
222
|
+
import { preferencesScript } from "@ui-sdk/core"
|
|
223
|
+
import { view } from "./preferences"
|
|
224
|
+
|
|
225
|
+
const page = `<ui-preferences>
|
|
226
|
+
<script>${preferencesScript([view])}</script>
|
|
227
|
+
<main>…</main>
|
|
228
|
+
</ui-preferences>`
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The script applies the saved attributes as the browser parses the page. Your client module then assigns the same preferences to the element, as in [Usage](#usage), to keep them current.
|
|
232
|
+
|
|
233
|
+
Follow the [server rendering setup](../server-rendering.md#show-them-before-the-scripts-load) for the complete page and client module, including how to keep cookie-backed preferences separate for each request.
|
|
234
|
+
|
|
235
|
+
If your Content Security Policy requires a nonce, put the nonce from your response on the `<script>` you write into the HTML.
|
|
236
|
+
|
|
237
|
+
## API Reference
|
|
238
|
+
|
|
239
|
+
### ui-preferences
|
|
240
|
+
|
|
241
|
+
Set `preferences` as a JavaScript property. It accepts preferences created with `createPreference` or `createColorScheme`.
|
|
242
|
+
|
|
243
|
+
- `preferences` (`readonly PreferenceLike[]`): The preferences to show, from `createPreference` or `createColorScheme`. Example: [Usage](#usage).
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
# Progress
|
|
2
|
+
|
|
3
|
+
Show a task’s progress, or an indeterminate state while its progress is unknown.
|
|
4
|
+
|
|
5
|
+
```ts title="basic.ts"
|
|
6
|
+
import "@ui-sdk/web/progress"
|
|
7
|
+
|
|
8
|
+
function mount(root: HTMLElement) {
|
|
9
|
+
root.innerHTML = `
|
|
10
|
+
<ui-progress value="60">
|
|
11
|
+
<ui-progress-label>Exporting video</ui-progress-label>
|
|
12
|
+
<ui-progress-value></ui-progress-value>
|
|
13
|
+
<ui-progress-track>
|
|
14
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
15
|
+
</ui-progress-track>
|
|
16
|
+
</ui-progress>
|
|
17
|
+
`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { mount }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Read the export bar. Its label and 60% value are available both visually and to a screen reader.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install @ui-sdk/web @ui-sdk/core
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Importing the component defines its elements. On the server the import does nothing.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import "@ui-sdk/web/progress"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Composition
|
|
38
|
+
|
|
39
|
+
Use the following composition to build a `ui-progress`:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
ui-progress
|
|
43
|
+
├── ui-progress-label
|
|
44
|
+
├── ui-progress-value
|
|
45
|
+
└── ui-progress-track
|
|
46
|
+
└── ui-progress-indicator
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- `ui-progress` holds the value and range.
|
|
50
|
+
- `ui-progress-label` gives it a visible name. You can use `aria-label` on the root instead.
|
|
51
|
+
- `ui-progress-value` displays the formatted value.
|
|
52
|
+
- `ui-progress-track` gives the bar its size, and `ui-progress-indicator` fills it.
|
|
53
|
+
|
|
54
|
+
The value is already part of the root's accessible description. The visible value is hidden from screen readers to avoid reading it twice.
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
Import the parts and put them together:
|
|
59
|
+
|
|
60
|
+
```html
|
|
61
|
+
<ui-progress value="40">
|
|
62
|
+
<ui-progress-label></ui-progress-label>
|
|
63
|
+
<ui-progress-value></ui-progress-value>
|
|
64
|
+
<ui-progress-track>
|
|
65
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
66
|
+
</ui-progress-track>
|
|
67
|
+
</ui-progress>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Build Your Own
|
|
71
|
+
|
|
72
|
+
`@ui-sdk/web/progress` comes with ready-made `ui-progress` elements. If you'd like to build your own, with your own element names, start from the `progress` primitive in `@ui-sdk/core`:
|
|
73
|
+
|
|
74
|
+
```ts title="upload-elements.ts"
|
|
75
|
+
import { progress } from "@ui-sdk/core/progress"
|
|
76
|
+
import { createParts } from "@ui-sdk/web"
|
|
77
|
+
|
|
78
|
+
createParts(progress, {
|
|
79
|
+
root: { tag: "upload-progress", display: "block" },
|
|
80
|
+
label: "upload-label",
|
|
81
|
+
value: "upload-value",
|
|
82
|
+
track: { tag: "upload-track", display: "block" },
|
|
83
|
+
indicator: { tag: "upload-bar", display: "block" },
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<upload-progress value="40">
|
|
89
|
+
<upload-label>Uploading photos</upload-label>
|
|
90
|
+
<upload-value>40%</upload-value>
|
|
91
|
+
<upload-track>
|
|
92
|
+
<upload-bar></upload-bar>
|
|
93
|
+
</upload-track>
|
|
94
|
+
</upload-progress>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`ui-progress-value` fills in the formatted value for you. An element from `createParts` shows only what you put in it, so write the text yourself when you set the value, like `40%` here.
|
|
98
|
+
|
|
99
|
+
Each element keeps the behavior, state and data attributes of its ready-made counterpart: the root is the `progressbar`, and the indicator sets its width from the value. See [Rendering](../rendering.md) and [Custom Parts](../custom-parts.md) for more.
|
|
100
|
+
|
|
101
|
+
## Indeterminate
|
|
102
|
+
|
|
103
|
+
Leave out `value` when you do not know how much work is complete. Every part gets `data-indeterminate`, and the root has no `aria-valuenow`.
|
|
104
|
+
|
|
105
|
+
The indicator has no inline width in this state. This example sweeps a short highlight across the track, and shows a still, full-width fill when reduced motion is on.
|
|
106
|
+
|
|
107
|
+
```ts title="indeterminate.ts"
|
|
108
|
+
import "@ui-sdk/web/progress"
|
|
109
|
+
|
|
110
|
+
function mount(root: HTMLElement) {
|
|
111
|
+
root.innerHTML = `
|
|
112
|
+
<ui-progress>
|
|
113
|
+
<ui-progress-label>Connecting to server</ui-progress-label>
|
|
114
|
+
<ui-progress-track>
|
|
115
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
116
|
+
</ui-progress-track>
|
|
117
|
+
</ui-progress>
|
|
118
|
+
`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export { mount }
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Read the Connecting to server bar. It shows an ongoing task without announcing a percentage.
|
|
125
|
+
|
|
126
|
+
## Changing the Value
|
|
127
|
+
|
|
128
|
+
Pass the latest `value` as your task progresses. The parts get `data-progressing` while the value is below `max`, and `data-complete` when it reaches the end.
|
|
129
|
+
|
|
130
|
+
```ts title="controlled.ts"
|
|
131
|
+
import "@ui-sdk/web/progress"
|
|
132
|
+
import { log } from "./log"
|
|
133
|
+
|
|
134
|
+
const total = 5
|
|
135
|
+
|
|
136
|
+
function mount(root: HTMLElement) {
|
|
137
|
+
root.innerHTML = `
|
|
138
|
+
<div data-slot="stack">
|
|
139
|
+
<div data-slot="controls">
|
|
140
|
+
<button type="button">Upload Next</button>
|
|
141
|
+
<button type="button">Reset</button>
|
|
142
|
+
</div>
|
|
143
|
+
<ui-progress>
|
|
144
|
+
<ui-progress-label>Uploading photos</ui-progress-label>
|
|
145
|
+
<ui-progress-value></ui-progress-value>
|
|
146
|
+
<ui-progress-track>
|
|
147
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
148
|
+
</ui-progress-track>
|
|
149
|
+
</ui-progress>
|
|
150
|
+
</div>
|
|
151
|
+
`
|
|
152
|
+
const progress = root.querySelector("ui-progress")!
|
|
153
|
+
const [next, reset] = root.querySelectorAll("button")
|
|
154
|
+
let uploaded = 1
|
|
155
|
+
const show = () => {
|
|
156
|
+
progress.setAttribute("value", String((uploaded / total) * 100))
|
|
157
|
+
next.setAttribute("aria-disabled", String(uploaded >= total))
|
|
158
|
+
}
|
|
159
|
+
next.addEventListener("click", () => {
|
|
160
|
+
if (uploaded >= total) {
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
uploaded++
|
|
164
|
+
show()
|
|
165
|
+
log(root, `Uploaded ${uploaded} of ${total} photos`)
|
|
166
|
+
})
|
|
167
|
+
reset.addEventListener("click", () => {
|
|
168
|
+
uploaded = 0
|
|
169
|
+
show()
|
|
170
|
+
log(root, "Reset to 0 photos")
|
|
171
|
+
})
|
|
172
|
+
show()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export { mount }
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Click Upload Next to add one photo, or 20%, and watch the console count them. At 100%, the button stops advancing the bar. Click Reset to start at 0%.
|
|
179
|
+
|
|
180
|
+
Progress displays your state; it fires no `valuechange` event.
|
|
181
|
+
|
|
182
|
+
## Bounds
|
|
183
|
+
|
|
184
|
+
`min` and `max` default to 0 and 100. A value outside that range is clamped for the fill, the percentage and `aria-valuenow`, but the state's `value` and a format other than percent keep it as you passed it. A value of 3 between 1 and 5 fills half the track.
|
|
185
|
+
|
|
186
|
+
```ts title="min-max.ts"
|
|
187
|
+
import "@ui-sdk/web/progress"
|
|
188
|
+
|
|
189
|
+
function mount(root: HTMLElement) {
|
|
190
|
+
root.innerHTML = `
|
|
191
|
+
<ui-progress value="3" min="1" max="5">
|
|
192
|
+
<ui-progress-label>Account setup, step 3 of 5</ui-progress-label>
|
|
193
|
+
<ui-progress-value></ui-progress-value>
|
|
194
|
+
<ui-progress-track>
|
|
195
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
196
|
+
</ui-progress-track>
|
|
197
|
+
</ui-progress>
|
|
198
|
+
`
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export { mount }
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Compare step 3 of 5 with the fill. Because the range starts at 1, the value is halfway through the range.
|
|
205
|
+
|
|
206
|
+
## Format and Locale
|
|
207
|
+
|
|
208
|
+
Pass `Intl.NumberFormat` options to `format` for units or decimal places. A function can return custom text, such as the time remaining.
|
|
209
|
+
|
|
210
|
+
```ts title="format.ts"
|
|
211
|
+
import "@ui-sdk/web/progress"
|
|
212
|
+
|
|
213
|
+
const bars = [
|
|
214
|
+
{
|
|
215
|
+
label: "Download",
|
|
216
|
+
value: 120,
|
|
217
|
+
max: 250,
|
|
218
|
+
format: { style: "unit", unit: "gigabyte" },
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
label: "Video render",
|
|
222
|
+
value: 87.25,
|
|
223
|
+
format: { style: "percent", maximumFractionDigits: 1 },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
label: "Backup",
|
|
227
|
+
value: 45,
|
|
228
|
+
max: 60,
|
|
229
|
+
format: (minutes: number) => `${60 - minutes} min left`,
|
|
230
|
+
},
|
|
231
|
+
{ label: "Synchronisierung", value: 40, locale: "de-DE" },
|
|
232
|
+
] satisfies {
|
|
233
|
+
label: string
|
|
234
|
+
value: number
|
|
235
|
+
max?: number
|
|
236
|
+
format?: Intl.NumberFormatOptions | ((value: number) => string)
|
|
237
|
+
locale?: string
|
|
238
|
+
}[]
|
|
239
|
+
|
|
240
|
+
function mount(root: HTMLElement) {
|
|
241
|
+
const items = bars.map(
|
|
242
|
+
(bar) => `
|
|
243
|
+
<ui-progress value="${bar.value}" ${"max" in bar ? `max="${bar.max}"` : ""} ${"locale" in bar ? `locale="${bar.locale}"` : ""}>
|
|
244
|
+
<ui-progress-label>${bar.label}</ui-progress-label>
|
|
245
|
+
<ui-progress-value></ui-progress-value>
|
|
246
|
+
<ui-progress-track>
|
|
247
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
248
|
+
</ui-progress-track>
|
|
249
|
+
</ui-progress>`
|
|
250
|
+
)
|
|
251
|
+
root.innerHTML = `<div data-slot="stack">${items.join("")}</div>`
|
|
252
|
+
root
|
|
253
|
+
.querySelectorAll<HTMLElement & { format?: unknown }>("ui-progress")
|
|
254
|
+
.forEach((progress, index) => {
|
|
255
|
+
const bar = bars[index]
|
|
256
|
+
if ("format" in bar) {
|
|
257
|
+
progress.format = bar.format
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export { mount }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Compare the progress readings. They show downloaded data, a precise percentage, time remaining, and a localized percentage.
|
|
266
|
+
|
|
267
|
+
A percent format reports the value's position between `min` and `max`. Other formats use the value itself.
|
|
268
|
+
|
|
269
|
+
`locale` controls digits and separators. If you omit it, the component reads the page's language after it mounts, with the browser's language as a fallback. The initial server and client render use English.
|
|
270
|
+
|
|
271
|
+
Set `dir="rtl"` on the surrounding content to fill the track from the right.
|
|
272
|
+
|
|
273
|
+
Set `format` and `getValueLabel` as element properties because they accept objects or functions. `locale` is an attribute.
|
|
274
|
+
|
|
275
|
+
## Value Label
|
|
276
|
+
|
|
277
|
+
Use `getValueLabel` to give screen readers more context than the visible number. Its details include `formatted`, `percent`, `min`, and `max`. Handle a `null` value when the task can be indeterminate; `percent` is also `null` and `formatted` is empty then.
|
|
278
|
+
|
|
279
|
+
```ts title="value-label.ts"
|
|
280
|
+
import type { GaugeLabelDetails } from "@ui-sdk/core/progress"
|
|
281
|
+
import "@ui-sdk/web/progress"
|
|
282
|
+
|
|
283
|
+
function mount(root: HTMLElement) {
|
|
284
|
+
root.innerHTML = `
|
|
285
|
+
<ui-progress value="3" max="12">
|
|
286
|
+
<ui-progress-label>Copying files</ui-progress-label>
|
|
287
|
+
<ui-progress-value>3 of 12</ui-progress-value>
|
|
288
|
+
<ui-progress-track>
|
|
289
|
+
<ui-progress-indicator></ui-progress-indicator>
|
|
290
|
+
</ui-progress-track>
|
|
291
|
+
</ui-progress>
|
|
292
|
+
`
|
|
293
|
+
const progress = root.querySelector("ui-progress") as HTMLElement & {
|
|
294
|
+
getValueLabel: (value: number | null, details: GaugeLabelDetails) => string
|
|
295
|
+
}
|
|
296
|
+
progress.getValueLabel = (value, details) =>
|
|
297
|
+
`${value} of ${details.max} files, ${details.formatted}`
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { mount }
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Read Copying files with a screen reader. It announces 3 of 12 files and 25%, while the visible value stays compact.
|
|
304
|
+
|
|
305
|
+
Use [Meter](./meter.md) for a reading such as storage used, rather than a task that will finish.
|
|
306
|
+
|
|
307
|
+
## Custom Rendering
|
|
308
|
+
|
|
309
|
+
See [Parts and Composition](../parts-and-composition.md) for choosing the elements parts bind. Use `format` for text that should be shared by the visible value and screen readers.
|
|
310
|
+
|
|
311
|
+
## Styling
|
|
312
|
+
|
|
313
|
+
Give the track a height, background, and width. The indicator sets its width as an inline percentage of the track. Style `data-indeterminate` for a task whose progress is unknown, since the indicator has no width then, and `data-complete` once the task finishes. Both styling options are shown in each example's Code tab.
|
|
314
|
+
|
|
315
|
+
Each part has a `data-slot`, such as `progress-indicator`, and its state attributes are listed under [Data Attributes](#data-attributes).
|
|
316
|
+
|
|
317
|
+
### `<ui-progress>`
|
|
318
|
+
The root exposes a CSS variable for positioning other content alongside the reading.
|
|
319
|
+
|
|
320
|
+
- `--progress-value`: Where the value sits between `min` and `max`, as a percentage, like 40%. Unset while indeterminate.
|
|
321
|
+
|
|
322
|
+
## Data Attributes
|
|
323
|
+
|
|
324
|
+
### `<ui-progress>`
|
|
325
|
+
`[data-slot="progress"]`
|
|
326
|
+
|
|
327
|
+
- `data-indeterminate`: Present while the value is null: the task is under way, but how far is unknown.
|
|
328
|
+
- `data-progressing`: Present while the value is below `max`.
|
|
329
|
+
- `data-complete`: Present once the value reaches `max`.
|
|
330
|
+
|
|
331
|
+
### `<ui-progress-label>`
|
|
332
|
+
`[data-slot="progress-label"]`
|
|
333
|
+
|
|
334
|
+
- `data-indeterminate`: Present while the value is null: the task is under way, but how far is unknown.
|
|
335
|
+
- `data-progressing`: Present while the value is below `max`.
|
|
336
|
+
- `data-complete`: Present once the value reaches `max`.
|
|
337
|
+
|
|
338
|
+
### `<ui-progress-value>`
|
|
339
|
+
`[data-slot="progress-value"]`
|
|
340
|
+
|
|
341
|
+
- `data-indeterminate`: Present while the value is null: the task is under way, but how far is unknown.
|
|
342
|
+
- `data-progressing`: Present while the value is below `max`.
|
|
343
|
+
- `data-complete`: Present once the value reaches `max`.
|
|
344
|
+
|
|
345
|
+
### `<ui-progress-track>`
|
|
346
|
+
`[data-slot="progress-track"]`
|
|
347
|
+
|
|
348
|
+
- `data-indeterminate`: Present while the value is null: the task is under way, but how far is unknown.
|
|
349
|
+
- `data-progressing`: Present while the value is below `max`.
|
|
350
|
+
- `data-complete`: Present once the value reaches `max`.
|
|
351
|
+
|
|
352
|
+
### `<ui-progress-indicator>`
|
|
353
|
+
`[data-slot="progress-indicator"]`
|
|
354
|
+
|
|
355
|
+
- `data-indeterminate`: Present while the value is null: the task is under way, but how far is unknown.
|
|
356
|
+
- `data-progressing`: Present while the value is below `max`.
|
|
357
|
+
- `data-complete`: Present once the value reaches `max`.
|
|
358
|
+
|
|
359
|
+
## API Reference
|
|
360
|
+
|
|
361
|
+
Props are attributes, like `value`, `min`, `max` and `locale`. `format` and `getValueLabel` are properties.
|
|
362
|
+
|
|
363
|
+
### Progress
|
|
364
|
+
|
|
365
|
+
- `min?` (`number`): The lowest value.
|
|
366
|
+
- `max?` (`number`): The highest value.
|
|
367
|
+
- `format?` (`NumberFormat`): How the value reads, for screen readers and the Value part: `Intl.NumberFormat` options, or a function of the value. A percent style shows where the value sits between `min` and `max`; any other style shows the value itself, like `{ style: "unit", unit: "gigabyte" }`.
|
|
368
|
+
- `locale?` (`string`): The locale the value is formatted in. Defaults to the page's `lang`, or the browser's language without one, once the page is interactive. Server markup uses English until then, so it never disagrees with the client.
|
|
369
|
+
- `getValueLabel?` (`((value: number | null, details: GaugeLabelDetails<number | null>) => string)`): The text screen readers announce for the value, when the formatted value says too little, like "3 of 12 files". It receives the value, null while a progress bar is indeterminate, and details: the `formatted` value, its `percent`, `min` and `max`.
|
|
370
|
+
- `value?` (`number | null`): How far the task has come, between `min` and `max`. Null means it's under way but how far is unknown, and the bar is indeterminate.
|
|
371
|
+
- `debug?` (`boolean`): Logs every state change with its reason to the console, in development builds.
|
|
372
|
+
|
|
373
|
+
### State
|
|
374
|
+
|
|
375
|
+
The same state shows as data attributes on each element.
|
|
376
|
+
|
|
377
|
+
- `value` (`number | null`): The value, or null while indeterminate.
|
|
378
|
+
- `percent` (`number | null`): Where the value sits between `min` and `max`, from 0 to 100, or null while indeterminate.
|
|
379
|
+
- `status` (`ProgressStatus`): Whether the progress is unknown, under way, or done.
|
|
380
|
+
|
|
381
|
+
`ui-progress-value` adds the formatted text:
|
|
382
|
+
|
|
383
|
+
- `value` (`number | null`): The value, or null while indeterminate.
|
|
384
|
+
- `percent` (`number | null`): Where the value sits between `min` and `max`, from 0 to 100, or null while indeterminate.
|
|
385
|
+
- `status` (`ProgressStatus`): Whether the progress is unknown, under way, or done.
|
|
386
|
+
- `text` (`string`): The formatted value, like "40%". Empty while indeterminate.
|
|
387
|
+
|
|
388
|
+
## Accessibility
|
|
389
|
+
|
|
390
|
+
Name the component with `ui-progress-label` or `aria-label`. It exposes the range and formatted value through the `progressbar` role. Use `getValueLabel` when that value needs more explanation.
|
|
391
|
+
|
|
392
|
+
### Tested Behavior
|
|
393
|
+
|
|
394
|
+
Every line below is an automated test.
|
|
395
|
+
|
|
396
|
+
- A progress bar is named by its label and reads its value.
|
|
397
|
+
- The value part shows the formatted value.
|
|
398
|
+
- The indicator is as wide as the value.
|
|
399
|
+
- A new value updates the bar.
|
|
400
|
+
- Every part says whether the task is under way, done, or unknown.
|
|
401
|
+
- An indeterminate bar has no value.
|
|
402
|
+
- A unit format reads the value itself.
|
|
403
|
+
- A value label replaces the formatted value for screen readers.
|
|
404
|
+
- A value above the maximum reads as the maximum.
|
|
405
|
+
|
|
406
|
+
Runs in React, Vue and web components.
|