@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,91 @@
|
|
|
1
|
+
# Custom Parts
|
|
2
|
+
|
|
3
|
+
Choose a binding target and expose the state of a custom element.
|
|
4
|
+
|
|
5
|
+
Start with the rating elements from [Rendering Primitives](./rendering.md). Add configuration to `createParts` when you need a different target or a public API.
|
|
6
|
+
|
|
7
|
+
## Choose the Target
|
|
8
|
+
|
|
9
|
+
By default, a part binds to its custom element. `target` chooses a child instead. `wrappedButton` finds a button or link; `wrappedChild("input")` finds an input.
|
|
10
|
+
|
|
11
|
+
Bind to the native element that should own focus and keyboard behavior. Put its label and classes on that element too.
|
|
12
|
+
|
|
13
|
+
## Expose API Methods
|
|
14
|
+
|
|
15
|
+
The rating primitive has a `rate` method. Add it to the root's `api` list to let application code call it:
|
|
16
|
+
|
|
17
|
+
```ts title="rating-web.ts"
|
|
18
|
+
import { createParts, wrappedButton } from "@ui-sdk/web"
|
|
19
|
+
import { rating } from "./rating"
|
|
20
|
+
|
|
21
|
+
createParts(rating, {
|
|
22
|
+
root: { tag: "my-rating", api: ["rate"] },
|
|
23
|
+
star: { tag: "my-rating-star", target: wrappedButton, display: "contents" },
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use this definition instead of the earlier one. Once the root is connected, `element.api.rate(3)` asks the primitive to change its value. Its callback and cancellation still apply. The element exposes only the methods you list.
|
|
28
|
+
|
|
29
|
+
## Expose a Live Property
|
|
30
|
+
|
|
31
|
+
A `state` mapping exposes a live getter and setter. Both call the primitive's API, so the primitive needs methods for reading and writing that value. The rating above only has `rate`; the built-in toggle has both `isPressed` and `setPressed`:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { toggle } from "@ui-sdk/core/toggle"
|
|
35
|
+
import { createParts, wrappedButton } from "@ui-sdk/web"
|
|
36
|
+
|
|
37
|
+
createParts(toggle, {
|
|
38
|
+
root: {
|
|
39
|
+
tag: "my-toggle",
|
|
40
|
+
target: wrappedButton,
|
|
41
|
+
display: "contents",
|
|
42
|
+
state: {
|
|
43
|
+
pressed: {
|
|
44
|
+
get: (api) => api.isPressed(),
|
|
45
|
+
set: (api, value: boolean) => api.setPressed(value),
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
api: ["isPressed", "setPressed", "toggle"],
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<my-toggle><button>Bold</button></my-toggle>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The setter calls the primitive's API, so change callbacks and cancellation still apply. The `api` list exposes those methods on the element's controller.
|
|
58
|
+
|
|
59
|
+
## Attributes and Properties
|
|
60
|
+
|
|
61
|
+
The primitive's schema supplies the default conversion:
|
|
62
|
+
|
|
63
|
+
| Kind | How It Reaches the Primitive |
|
|
64
|
+
| ----------------------------- | -------------------------------------------------------------- |
|
|
65
|
+
| `string`, `number`, `boolean` | Parsed from an attribute. |
|
|
66
|
+
| `list` | A comma-separated attribute. |
|
|
67
|
+
| `value` | A JavaScript property, for objects and other rich values. |
|
|
68
|
+
| `callback` | A DOM event. |
|
|
69
|
+
| `action` | A DOM event with `detail.waitUntil(promise)` for pending work. |
|
|
70
|
+
|
|
71
|
+
A boolean attribute is on when present, unless its value is `"false"`. Defaults determine the value when the attribute is absent. `disabled` and `required` follow native controls, which treat them as on whenever present.
|
|
72
|
+
|
|
73
|
+
Each attribute gets a property that reflects it. Name the booleans that are on by default in `defaults`, so their properties read `true` without the attribute and `false` writes `"false"`:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { tabs } from "@ui-sdk/core/tabs"
|
|
77
|
+
import { createParts, wrappedButton } from "@ui-sdk/web"
|
|
78
|
+
|
|
79
|
+
createParts(tabs, {
|
|
80
|
+
root: { tag: "my-tabs", defaults: { loop: true } },
|
|
81
|
+
list: "my-tabs-list",
|
|
82
|
+
tab: { tag: "my-tabs-tab", target: wrappedButton },
|
|
83
|
+
panel: "my-tabs-panel",
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use `kinds` to override a schema kind for an element and `properties` to add properties absent from the schema. `context(el)` on a child part can supply slot props from surrounding markup; explicit attributes and properties take precedence.
|
|
88
|
+
|
|
89
|
+
## Compose a Popup
|
|
90
|
+
|
|
91
|
+
A custom root can contain `ui-popover` or `ui-dialog`. Keep its `open` property in sync with your primitive and listen for `openchange`. That event doesn't bubble, so a listener on your root hears only the change you forward. [Compose Ours](./core.md#compose-ours) shows the pattern.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# First Component
|
|
2
|
+
|
|
3
|
+
Add a component to your page and style its state.
|
|
4
|
+
|
|
5
|
+
Let's add a Bookmark toggle. Press it once to turn it on, then again to turn it off.
|
|
6
|
+
|
|
7
|
+
If you haven't installed the packages yet, start with [Installation](./installation.md).
|
|
8
|
+
|
|
9
|
+
This example uses a bundler that resolves package imports and compiles TypeScript, such as Vite. Keep `index.html` and `bookmark-button.ts` in the same folder.
|
|
10
|
+
|
|
11
|
+
## Register the Component
|
|
12
|
+
|
|
13
|
+
Create `bookmark-button.ts` and import the toggle entry:
|
|
14
|
+
|
|
15
|
+
```ts title="bookmark-button.ts"
|
|
16
|
+
import "@ui-sdk/web/toggle"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Importing the toggle entry registers `<ui-toggle>`. The custom element manages the wrapped button's pressed state and sets `aria-pressed` for screen readers. The native button handles Enter and Space.
|
|
20
|
+
|
|
21
|
+
## Use It on Your Page
|
|
22
|
+
|
|
23
|
+
Add this markup to `index.html`:
|
|
24
|
+
|
|
25
|
+
```html title="index.html"
|
|
26
|
+
<ui-toggle id="bookmark">
|
|
27
|
+
<button type="button">Bookmark</button>
|
|
28
|
+
</ui-toggle>
|
|
29
|
+
|
|
30
|
+
<script type="module" src="./bookmark-button.ts"></script>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Open your page. You should see a button labeled Bookmark. Next, add styles so you can tell when it is pressed.
|
|
34
|
+
|
|
35
|
+
## Add Styles
|
|
36
|
+
|
|
37
|
+
When the toggle is pressed, its button has a `data-pressed` attribute. Style the button inside `<ui-toggle>`.
|
|
38
|
+
|
|
39
|
+
With Tailwind CSS configured in your app, add utility classes to the button. The `data-pressed:` variant applies while the toggle is pressed:
|
|
40
|
+
|
|
41
|
+
```html title="index.html"
|
|
42
|
+
<ui-toggle id="bookmark">
|
|
43
|
+
<button
|
|
44
|
+
type="button"
|
|
45
|
+
class="inline-flex h-8 items-center rounded-md border border-neutral-300 px-3 text-sm font-medium hover:bg-neutral-100 focus-visible:outline-2 focus-visible:outline-offset-2 data-pressed:bg-neutral-900 data-pressed:text-white"
|
|
46
|
+
>
|
|
47
|
+
Bookmark
|
|
48
|
+
</button>
|
|
49
|
+
</ui-toggle>
|
|
50
|
+
|
|
51
|
+
<script type="module" src="./bookmark-button.ts"></script>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Keep the component import in `bookmark-button.ts`:
|
|
55
|
+
|
|
56
|
+
```ts title="bookmark-button.ts"
|
|
57
|
+
import "@ui-sdk/web/toggle"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Try the styled toggle:
|
|
61
|
+
|
|
62
|
+
```ts title="first-component.ts"
|
|
63
|
+
import "@ui-sdk/web/toggle"
|
|
64
|
+
|
|
65
|
+
function mount(root: HTMLElement) {
|
|
66
|
+
root.innerHTML = `
|
|
67
|
+
<ui-toggle>
|
|
68
|
+
<button type="button" data-variant="outline">
|
|
69
|
+
Bookmark
|
|
70
|
+
</button>
|
|
71
|
+
</ui-toggle>
|
|
72
|
+
`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export { mount }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Click Bookmark to turn it on or off. A filled background means it is on. You can also focus the button with Tab and press Enter or Space.
|
|
79
|
+
|
|
80
|
+
Keep the label the same in both states. `aria-pressed` tells a screen reader whether the toggle is on.
|
|
81
|
+
|
|
82
|
+
## Keep Going
|
|
83
|
+
|
|
84
|
+
- [Toggle](./components/toggle.md) covers disabled states, controlled state, and groups of toggles.
|
|
85
|
+
- [Components](./README.md) lists the other components you can add with the same install.
|
|
86
|
+
- [Parts and Composition](./parts-and-composition.md) shows how to put a component with several parts together.
|
|
87
|
+
- [State and Events](./state-and-events.md) shows how to read changes and control state from your app.
|
|
88
|
+
- [Styling and Animation](./styling-and-animation.md) covers state attributes, CSS variables, and transitions.
|
package/docs/forms.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Forms
|
|
2
|
+
|
|
3
|
+
Submit custom element values, label controls, and show validation errors.
|
|
4
|
+
|
|
5
|
+
Give a control a `name` to include its value in a form. Once their modules load, controls such as Checkbox and Select participate in submission, validation, and reset through the browser’s form-associated custom element APIs.
|
|
6
|
+
|
|
7
|
+
## Submit a Value
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import "@ui-sdk/web/checkbox"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<form action="/preferences" method="post">
|
|
15
|
+
<label
|
|
16
|
+
><ui-checkbox name="updates" value="yes" default-checked></ui-checkbox>
|
|
17
|
+
Email me updates</label
|
|
18
|
+
>
|
|
19
|
+
<button type="submit">Save</button>
|
|
20
|
+
<button type="reset">Reset</button>
|
|
21
|
+
</form>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The checkbox submits `updates=yes` when checked. Reset restores its default value.
|
|
25
|
+
|
|
26
|
+
On controls that support them, `required`, `disabled`, `read-only`, and `form` follow native conventions. The elements expose `validity`, `checkValidity()`, and `setCustomValidity()`.
|
|
27
|
+
|
|
28
|
+
## Respond to a Reset
|
|
29
|
+
|
|
30
|
+
A reset also fires `checkedchange` when it requests a different value. You can use the same listener for clicks and resets:
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<form>
|
|
34
|
+
<label>
|
|
35
|
+
<ui-checkbox name="updates" value="yes" default-checked></ui-checkbox>
|
|
36
|
+
Email me updates
|
|
37
|
+
</label>
|
|
38
|
+
<button type="reset">Reset</button>
|
|
39
|
+
<output id="reason">No change yet</output>
|
|
40
|
+
</form>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import "@ui-sdk/web/checkbox"
|
|
45
|
+
|
|
46
|
+
const checkbox = document.querySelector("ui-checkbox")!
|
|
47
|
+
const reason = document.querySelector("#reason")!
|
|
48
|
+
|
|
49
|
+
checkbox.addEventListener("checkedchange", (event) => {
|
|
50
|
+
reason.textContent = event.detail.reason
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Run the script after the markup exists. Uncheck the box, then press Reset: `default-checked` restores `true`, and the output reads `reset`. If the checkbox is already at its default, no change event is needed.
|
|
55
|
+
|
|
56
|
+
The element owns its live state. If your application mirrors `checked` elsewhere, update that state from `checkedchange` too.
|
|
57
|
+
|
|
58
|
+
## Label and Validate a Field
|
|
59
|
+
|
|
60
|
+
`ui-field` finds the control inside it and connects the label, description, and error:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import "@ui-sdk/web/field"
|
|
64
|
+
import "@ui-sdk/web/input"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<ui-field name="email">
|
|
69
|
+
<ui-field-label>Email</ui-field-label>
|
|
70
|
+
<ui-input>
|
|
71
|
+
<input type="email" required />
|
|
72
|
+
</ui-input>
|
|
73
|
+
<ui-field-description>We'll only use it for receipts.</ui-field-description>
|
|
74
|
+
<ui-field-error></ui-field-error>
|
|
75
|
+
</ui-field>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The control is one of ours, such as `ui-input`, `ui-textarea`, `ui-checkbox` or `ui-select`. [Field](./components/field.md) shows the supported controls.
|
|
79
|
+
|
|
80
|
+
## Handle a Submission
|
|
81
|
+
|
|
82
|
+
On a normal submit, the browser checks constraints such as `required` and `type="email"` before running your listener.
|
|
83
|
+
|
|
84
|
+
Your server may still reject a valid-looking value. Set the field’s `invalid` property to `true` and show the server’s message. When the user edits the field, clear the message and set `invalid` back to `undefined` so the field uses native validation again. This example expects a `/api/preferences` endpoint:
|
|
85
|
+
|
|
86
|
+
```html
|
|
87
|
+
<form>
|
|
88
|
+
<ui-field name="email">
|
|
89
|
+
<ui-field-label>Email</ui-field-label>
|
|
90
|
+
<ui-input>
|
|
91
|
+
<input type="email" required />
|
|
92
|
+
</ui-input>
|
|
93
|
+
<ui-field-error></ui-field-error>
|
|
94
|
+
</ui-field>
|
|
95
|
+
<button type="submit">Save</button>
|
|
96
|
+
</form>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import "@ui-sdk/web/field"
|
|
101
|
+
import "@ui-sdk/web/input"
|
|
102
|
+
|
|
103
|
+
const form = document.querySelector("form")!
|
|
104
|
+
const field = form.querySelector("ui-field")!
|
|
105
|
+
const error = form.querySelector("ui-field-error")!
|
|
106
|
+
|
|
107
|
+
form.addEventListener("submit", async (event) => {
|
|
108
|
+
event.preventDefault()
|
|
109
|
+
const response = await fetch("/api/preferences", {
|
|
110
|
+
method: "POST",
|
|
111
|
+
body: new FormData(form),
|
|
112
|
+
})
|
|
113
|
+
field.invalid = response.ok ? undefined : true
|
|
114
|
+
error.textContent = response.ok ? "" : "That email is already taken."
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
form.addEventListener("input", () => {
|
|
118
|
+
field.invalid = undefined
|
|
119
|
+
error.textContent = ""
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
An empty `<ui-field-error>` shows the browser's own message, so clearing the text brings it back. Without a listener, the native form submits normally.
|
|
124
|
+
|
|
125
|
+
For a form that must work before component scripts load, see [Server Rendering](./server-rendering.md#before-upgrade).
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
Install UI SDK and register its custom elements.
|
|
4
|
+
|
|
5
|
+
Use these components in an app that supports custom elements. The examples use a bundler, such as Vite, to resolve package imports.
|
|
6
|
+
|
|
7
|
+
## Install the Packages
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @ui-sdk/web @ui-sdk/core
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`@ui-sdk/web` provides the custom elements. `@ui-sdk/core` provides their behavior and is a peer dependency. Install both so the components and any helpers you use share one copy of the core.
|
|
14
|
+
|
|
15
|
+
## Register a Component
|
|
16
|
+
|
|
17
|
+
Import each component from its own entry to register its tags:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import "@ui-sdk/web/button"
|
|
21
|
+
import "@ui-sdk/web/toggle"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
A dialog has separate tags for its trigger, content, and title. One import registers them all:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import "@ui-sdk/web/dialog"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Load these imports from your app's browser entry. The root entry, `@ui-sdk/web`, exports helpers and types but registers no elements. Each [component page](./README.md) shows the tags you can use.
|
|
31
|
+
|
|
32
|
+
## Without a Build Step
|
|
33
|
+
|
|
34
|
+
A plain HTML page can load the components from ui-sdk.dev, with nothing to install. Add one script, and each component loads the first time its tags appear on the page:
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<script type="module" src="https://ui-sdk.dev/web@0.js"></script>
|
|
38
|
+
|
|
39
|
+
<ui-toggle><button>Bold</button></ui-toggle>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`@0` follows the newest 0.x release. To keep a page on one release, use its exact version, like `web@0.4.1.js`. For a quick test, `web.js` with no version follows the newest release of all.
|
|
43
|
+
|
|
44
|
+
To have an agent build the page, ask it to read web.md first. It's these docs in one file, written for a page that loads `web.js` and `web.css`.
|
|
45
|
+
|
|
46
|
+
Each component also has its own file, named like its import, if you'd rather list them:
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<script type="module" src="https://ui-sdk.dev/web@0/toggle.js"></script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
To host the files yourself, copy the `browser` folder from the `@ui-sdk/web` package into your site. It holds `web.js` and the `web` folder it loads from, so keep the two side by side. Browsers only run module scripts from a server, so open the page through one, not from a file on disk.
|
|
53
|
+
|
|
54
|
+
### Build Your Own
|
|
55
|
+
|
|
56
|
+
`core.js` has every behavior from `@ui-sdk/core`, along with `definePrimitive` and `createParts`. Import it to build a component we don't ship, on the same page as ours. This one is a small grid of cells you can move through with the arrow keys and select with Shift:
|
|
57
|
+
|
|
58
|
+
```html
|
|
59
|
+
<script type="module">
|
|
60
|
+
import {
|
|
61
|
+
createCellRange,
|
|
62
|
+
createGridFocus,
|
|
63
|
+
createParts,
|
|
64
|
+
definePrimitive,
|
|
65
|
+
} from "https://ui-sdk.dev/web@0/core.js"
|
|
66
|
+
|
|
67
|
+
const sheet = definePrimitive({
|
|
68
|
+
name: "sheet",
|
|
69
|
+
options: { rows: "number", cols: "number" },
|
|
70
|
+
state: () => ({ active: null, range: null }),
|
|
71
|
+
api: (context) => {
|
|
72
|
+
const rows = () => context.options().rows
|
|
73
|
+
const cols = () => context.options().cols
|
|
74
|
+
const grid = createGridFocus(context, { key: "active", rows, cols })
|
|
75
|
+
return {
|
|
76
|
+
grid,
|
|
77
|
+
range: createCellRange(context, { key: "range", grid, rows, cols }),
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
slots: (slot) => ({
|
|
81
|
+
root: slot({ attrs: () => ({ role: "grid" }) }),
|
|
82
|
+
row: slot({ attrs: () => ({ role: "row" }) }),
|
|
83
|
+
cell: slot({
|
|
84
|
+
props: { row: "number", col: "number" },
|
|
85
|
+
attrs: (state, { props, api }) => ({
|
|
86
|
+
role: "gridcell",
|
|
87
|
+
tabindex: api.grid.tabIndex(state, props),
|
|
88
|
+
...api.range.cellAttrs(state, props),
|
|
89
|
+
}),
|
|
90
|
+
on: {
|
|
91
|
+
keydown: (event, { api }) => api.range.keydown(event),
|
|
92
|
+
pointerdown: (event, { api, props }) =>
|
|
93
|
+
api.range.pointerdown(event, props),
|
|
94
|
+
},
|
|
95
|
+
bind: (el, { api, props }) => api.range.bind(el, props),
|
|
96
|
+
}),
|
|
97
|
+
}),
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
createParts(sheet, {
|
|
101
|
+
root: "my-sheet",
|
|
102
|
+
row: "my-sheet-row",
|
|
103
|
+
cell: "my-sheet-cell",
|
|
104
|
+
})
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<my-sheet rows="2" cols="2" aria-label="Numbers">
|
|
108
|
+
<my-sheet-row>
|
|
109
|
+
<my-sheet-cell row="0" col="0">4</my-sheet-cell>
|
|
110
|
+
<my-sheet-cell row="0" col="1">8</my-sheet-cell>
|
|
111
|
+
</my-sheet-row>
|
|
112
|
+
<my-sheet-row>
|
|
113
|
+
<my-sheet-cell row="1" col="0">15</my-sheet-cell>
|
|
114
|
+
<my-sheet-cell row="1" col="1">16</my-sheet-cell>
|
|
115
|
+
</my-sheet-row>
|
|
116
|
+
</my-sheet>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Selected cells get `aria-selected` and `data-selected` to style. [Compose Behaviors](./core.md#compose-behaviors) walks through building a primitive, and [Rendering Primitives](./rendering.md) covers `createParts`. `core.js` shares its files with the components, so a page that uses both loads that code once.
|
|
120
|
+
|
|
121
|
+
## Add Your Styles
|
|
122
|
+
|
|
123
|
+
Components use light DOM and are unstyled, so you style them with your app's CSS or with Tailwind CSS. [Styling and Animation](./styling-and-animation.md) covers both.
|
|
124
|
+
|
|
125
|
+
You can render your first component without setting up a provider, a portal root, or a UI SDK stylesheet. CSS Modules need a bundler that imports a class-name map.
|
|
126
|
+
|
|
127
|
+
For right-to-left layouts, set `dir="rtl"` on the page or a container. Use logical CSS properties, such as `padding-inline-start`, in your styles. [Server Rendering](./server-rendering.md) covers markup before the elements upgrade.
|
|
128
|
+
|
|
129
|
+
## Editor Support
|
|
130
|
+
|
|
131
|
+
The package includes `custom-elements.json`, which describes its tags, attributes, properties, and events. Tools that support custom element manifests can read it.
|
|
132
|
+
|
|
133
|
+
For HTML completion in VS Code, add this to your workspace settings:
|
|
134
|
+
|
|
135
|
+
```json title=".vscode/settings.json"
|
|
136
|
+
{ "html.customData": ["./node_modules/@ui-sdk/web/html-custom-data.json"] }
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Component imports also register element types with TypeScript. For example, importing `@ui-sdk/web/toggle` gives `document.querySelector("ui-toggle")` its element type.
|
|
140
|
+
|
|
141
|
+
Continue with [First Component](./first-component.md) to add a working toggle to your page.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Introduction
|
|
2
|
+
|
|
3
|
+
Use unstyled custom elements with keyboard, focus, and screen reader support built in.
|
|
4
|
+
|
|
5
|
+
These docs cover ui-sdk in Web Components. Using another framework? See React, Vue, Svelte or Solid. To build your own components from behaviors, see [Core](./core.md).
|
|
6
|
+
|
|
7
|
+
`@ui-sdk/web` gives you components such as Select, Dialog, and Tabs as custom elements, built on ui-sdk's behaviors. They handle interactions, focus, and ARIA attributes. You write the HTML and styles.
|
|
8
|
+
|
|
9
|
+
Import the components you need to register their tags, add them to your page, and style them with your own CSS.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Copy this prompt into your agent:
|
|
14
|
+
|
|
15
|
+
```text prompt
|
|
16
|
+
Set up ui-sdk in this Web Components project. Each component registers its tags when you import its entry, like @ui-sdk/web/dialog.
|
|
17
|
+
|
|
18
|
+
1. Install @ui-sdk/web and @ui-sdk/core with the project's package manager.
|
|
19
|
+
2. Add a note to AGENTS.md, creating it if needed: before using ui-sdk, follow the ui-sdk skill if it's installed, and read node_modules/@ui-sdk/web/docs/llms.txt. To build a new component, also search node_modules/@ui-sdk/web/docs/core.md by heading, and read rendering.md next to it.
|
|
20
|
+
3. If you support skills, run: npx skills add vercel-labs/ui --skill ui-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
It installs ui-sdk and points your `AGENTS.md` at the docs that ship with the packages.
|
|
24
|
+
|
|
25
|
+
## Set It Up Yourself
|
|
26
|
+
|
|
27
|
+
- [Installation](./installation.md): Install the packages and register their custom elements.
|
|
28
|
+
- [First Component](./first-component.md): Add and style your first component.
|
|
29
|
+
|
|
30
|
+
## Explore the Components
|
|
31
|
+
|
|
32
|
+
The [Using Components guides](./parts-and-composition.md) cover patterns the components share, such as composing parts, handling state, and styling.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Lists and Menus
|
|
2
|
+
|
|
3
|
+
Supply options as data, load them from a server, and define menu actions.
|
|
4
|
+
|
|
5
|
+
Select, Combobox, Autocomplete, and Listbox accept items as a property. Use this when your choices already come from an array. You can also write their item parts in HTML.
|
|
6
|
+
|
|
7
|
+
## Start with Strings
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<ui-select>
|
|
11
|
+
<ui-select-trigger
|
|
12
|
+
><button aria-label="Fruit">
|
|
13
|
+
<ui-select-value placeholder="Choose a fruit"></ui-select-value></button
|
|
14
|
+
></ui-select-trigger>
|
|
15
|
+
<ui-select-content>
|
|
16
|
+
<ui-select-list></ui-select-list>
|
|
17
|
+
</ui-select-content>
|
|
18
|
+
</ui-select>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import "@ui-sdk/web/select"
|
|
23
|
+
|
|
24
|
+
const select = document.querySelector("ui-select")!
|
|
25
|
+
select.items = ["Apple", "Banana", "Pear"]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Each string is both its value and its label. For different values and labels, use `{ value: "apple", label: "Apple" }`. Items can also have `disabled` and `keywords`.
|
|
29
|
+
|
|
30
|
+
Group choices with `{ type: "group", label, items }`, or separate them with `{ type: "separator" }`. Annotate the array with `ListData` and your editor checks every entry where you write it:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import type { ListData } from "@ui-sdk/core/select"
|
|
34
|
+
|
|
35
|
+
const plans: ListData = [
|
|
36
|
+
{ value: "free", label: "Free" },
|
|
37
|
+
{ value: "pro", label: "Pro" },
|
|
38
|
+
{ type: "separator" },
|
|
39
|
+
{
|
|
40
|
+
type: "group",
|
|
41
|
+
label: "Contact sales",
|
|
42
|
+
items: [{ value: "enterprise", label: "Enterprise" }],
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For object values, set the `itemToValue` and `itemToLabel` properties, and write the type as `ListData<Plan>`. [Select](./components/select.md) has complete examples.
|
|
48
|
+
|
|
49
|
+
Trigger Menu uses a `triggers` property for its trigger definitions; see [Trigger Menu](./components/trigger-menu.md).
|
|
50
|
+
|
|
51
|
+
## Search and Load Items
|
|
52
|
+
|
|
53
|
+
The `filter` attribute chooses a matching mode, such as `filter="startsWith"`. Assign a function to the `filter` property for your own matching. [Async Options](./utilities/async-options.md) covers loading from a server.
|
|
54
|
+
|
|
55
|
+
Data lists can virtualize large collections.
|
|
56
|
+
|
|
57
|
+
## Define a Menu
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<ui-menu>
|
|
61
|
+
<ui-menu-trigger><button>File</button></ui-menu-trigger>
|
|
62
|
+
</ui-menu>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
import "@ui-sdk/web/menu"
|
|
67
|
+
import type { MenuData } from "@ui-sdk/web"
|
|
68
|
+
|
|
69
|
+
const fileMenu: MenuData = [
|
|
70
|
+
{ value: "open", label: "Open", shortcut: "mod+o" },
|
|
71
|
+
{ type: "separator" },
|
|
72
|
+
{
|
|
73
|
+
type: "submenu",
|
|
74
|
+
label: "Share",
|
|
75
|
+
items: [{ value: "email", label: "Email" }],
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
const menu = document.querySelector("ui-menu")!
|
|
80
|
+
menu.items = fileMenu
|
|
81
|
+
menu.addEventListener("action", (event) => console.log(event.detail.value))
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A plain string is an action whose value and label are the string. [Menu](./components/menu.md) covers checkbox items and radio groups. Commands use `CommandData` and trigger menus `TriggerMenuData`, the same entries with fields of their own, and trees `TreeItemData[]`.
|
|
85
|
+
|
|
86
|
+
## Style Parts from Data
|
|
87
|
+
|
|
88
|
+
Parts rendered from data start out bare, with no classes. To style them, put a `<template>` inside the element and write each part there once, the way you want it to look. Every part the element renders is a copy of the part with the same tag in its template, classes and content included.
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<ui-select default-value="pro">
|
|
92
|
+
<ui-select-trigger>
|
|
93
|
+
<button><ui-select-value></ui-select-value></button>
|
|
94
|
+
</ui-select-trigger>
|
|
95
|
+
<template>
|
|
96
|
+
<ui-select-content class="rounded-2xl bg-white p-1 shadow-lg">
|
|
97
|
+
<ui-select-group>
|
|
98
|
+
<ui-select-group-label
|
|
99
|
+
class="px-2 py-1 text-xs text-neutral-500"
|
|
100
|
+
></ui-select-group-label>
|
|
101
|
+
<ui-select-item
|
|
102
|
+
class="relative flex items-center rounded-xl py-1.5 ps-2 pe-8 data-highlighted:bg-neutral-100"
|
|
103
|
+
>
|
|
104
|
+
<ui-select-item-indicator class="absolute end-2"
|
|
105
|
+
>✓</ui-select-item-indicator
|
|
106
|
+
>
|
|
107
|
+
</ui-select-item>
|
|
108
|
+
</ui-select-group>
|
|
109
|
+
<ui-select-separator
|
|
110
|
+
class="-mx-1 my-1 h-px bg-neutral-200"
|
|
111
|
+
></ui-select-separator>
|
|
112
|
+
</ui-select-content>
|
|
113
|
+
</template>
|
|
114
|
+
</ui-select>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const select = document.querySelector("ui-select")!
|
|
119
|
+
select.items = plans
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The element looks up each part by its tag, so the template only needs one of each, nested however reads best. Parts you leave out of it render bare.
|
|
123
|
+
|
|
124
|
+
- **Containers copy only themselves.** The content, the list, a group or a submenu's content takes the template's classes, and the data fills it.
|
|
125
|
+
- **Items copy everything inside them.** An indicator, an icon or a shortcut you put in the template's item shows in every item.
|
|
126
|
+
- **The label goes in the text part.** When the template's item has one, like `<ui-select-item-text>`, the label goes there, so you can style what a search matched with classes like `[&_mark]:font-semibold`. Without one, the label comes first in the item.
|
|
127
|
+
|
|
128
|
+
Select, Combobox, Autocomplete, Command, Listbox and Trigger Menu copy their content, list, groups, group labels, items and separators. A combobox with chips copies its chip too, with the remove button you write inside it:
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<template>
|
|
132
|
+
<ui-combobox-chip
|
|
133
|
+
class="flex items-center gap-1 rounded-2xl bg-neutral-200 ps-1.5 pe-0.5 text-xs"
|
|
134
|
+
>
|
|
135
|
+
<ui-combobox-chip-remove>
|
|
136
|
+
<button type="button" class="opacity-50 hover:opacity-100">×</button>
|
|
137
|
+
</ui-combobox-chip-remove>
|
|
138
|
+
</ui-combobox-chip>
|
|
139
|
+
</template>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
A menu copies its content, items, checkbox items, radio items, groups, group labels, separators, submenu triggers and submenu content. Put the check in the template's checkbox item and the chevron in its submenu trigger.
|
|
143
|
+
|
|
144
|
+
A tree copies its items, indicators, checkboxes, labels and groups. A branch gets the indicator, and every item gets the checkbox when the tree is `checkable`. A link item's label becomes an `<a>` that takes the label's classes.
|
|
145
|
+
|
|
146
|
+
```html
|
|
147
|
+
<ui-tree aria-label="Groceries">
|
|
148
|
+
<template>
|
|
149
|
+
<ui-tree-item class="flex flex-wrap items-center">
|
|
150
|
+
<ui-tree-item-indicator
|
|
151
|
+
class="size-4 before:content-['›'] data-expanded:rotate-90"
|
|
152
|
+
></ui-tree-item-indicator>
|
|
153
|
+
<ui-tree-item-label
|
|
154
|
+
class="flex-1 rounded-xl px-2 data-selected:bg-neutral-100"
|
|
155
|
+
></ui-tree-item-label>
|
|
156
|
+
<ui-tree-group class="basis-full ps-4"></ui-tree-group>
|
|
157
|
+
</ui-tree-item>
|
|
158
|
+
</template>
|
|
159
|
+
</ui-tree>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Keys and Shortcuts
|
|
163
|
+
|
|
164
|
+
`loop` controls whether arrow keys wrap around a list. Components that support `orientation` use it to choose the navigation axis.
|
|
165
|
+
|
|
166
|
+
A trigger's `shortcut="mod+k"` opens it from elsewhere on the page. Data menus run item shortcuts while closed; a menu item written in HTML only displays its shortcut. [Shortcuts](./utilities/shortcuts.md) covers registering your own.
|