@universal-material/web 3.7.2 → 3.9.0
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/.claude-plugin/plugin.json +12 -0
- package/README.md +12 -0
- package/app-bar/top-app-bar.d.ts +20 -4
- package/app-bar/top-app-bar.d.ts.map +1 -1
- package/app-bar/top-app-bar.js +84 -33
- package/app-bar/top-app-bar.js.map +1 -1
- package/app-bar/top-app-bar.styles.d.ts.map +1 -1
- package/app-bar/top-app-bar.styles.js +18 -1
- package/app-bar/top-app-bar.styles.js.map +1 -1
- package/badge/badge.d.ts +5 -2
- package/badge/badge.d.ts.map +1 -1
- package/badge/badge.js +9 -6
- package/badge/badge.js.map +1 -1
- package/badge/badge.styles.d.ts.map +1 -1
- package/badge/badge.styles.js +1 -0
- package/badge/badge.styles.js.map +1 -1
- package/bundle.min.js +5480 -2170
- package/button/button-base.d.ts +9 -2
- package/button/button-base.d.ts.map +1 -1
- package/button/button-base.js +12 -5
- package/button/button-base.js.map +1 -1
- package/button/button-set.d.ts +3 -3
- package/button/button-set.d.ts.map +1 -1
- package/button/button-set.js +7 -7
- package/button/button-set.js.map +1 -1
- package/button/button.d.ts +10 -7
- package/button/button.d.ts.map +1 -1
- package/button/button.js +17 -14
- package/button/button.js.map +1 -1
- package/button/fab-menu-color-context.d.ts +2 -2
- package/button/fab-menu-color-context.d.ts.map +1 -1
- package/button/fab-menu-color-context.js.map +1 -1
- package/button/fab-menu-item.d.ts +3 -3
- package/button/fab-menu-item.d.ts.map +1 -1
- package/button/fab-menu-item.js +11 -11
- package/button/fab-menu-item.js.map +1 -1
- package/button/fab-menu.d.ts +20 -5
- package/button/fab-menu.d.ts.map +1 -1
- package/button/fab-menu.js +48 -11
- package/button/fab-menu.js.map +1 -1
- package/button/fab.d.ts +22 -7
- package/button/fab.d.ts.map +1 -1
- package/button/fab.js +49 -11
- package/button/fab.js.map +1 -1
- package/button/icon-button.d.ts +13 -7
- package/button/icon-button.d.ts.map +1 -1
- package/button/icon-button.js +14 -8
- package/button/icon-button.js.map +1 -1
- package/button/toggle-button.d.ts +6 -6
- package/button/toggle-button.d.ts.map +1 -1
- package/button/toggle-button.js +10 -10
- package/button/toggle-button.js.map +1 -1
- package/button-field/button-field.d.ts +6 -3
- package/button-field/button-field.d.ts.map +1 -1
- package/button-field/button-field.js +12 -9
- package/button-field/button-field.js.map +1 -1
- package/calendar/calendar-adapter.d.ts +3 -0
- package/calendar/calendar-adapter.d.ts.map +1 -1
- package/calendar/calendar-adapter.js.map +1 -1
- package/calendar/calendar-base.d.ts +18 -1
- package/calendar/calendar-base.d.ts.map +1 -1
- package/calendar/calendar-base.js +188 -25
- package/calendar/calendar-base.js.map +1 -1
- package/calendar/calendar.d.ts +6 -2
- package/calendar/calendar.d.ts.map +1 -1
- package/calendar/calendar.js +12 -8
- package/calendar/calendar.js.map +1 -1
- package/calendar/default-calendar-adapter.d.ts +3 -0
- package/calendar/default-calendar-adapter.d.ts.map +1 -1
- package/calendar/default-calendar-adapter.js +17 -5
- package/calendar/default-calendar-adapter.js.map +1 -1
- package/calendar/range-calendar.d.ts +2 -2
- package/calendar/range-calendar.d.ts.map +1 -1
- package/calendar/range-calendar.js +9 -9
- package/calendar/range-calendar.js.map +1 -1
- package/card/card-content.d.ts +7 -2
- package/card/card-content.d.ts.map +1 -1
- package/card/card-content.js +10 -5
- package/card/card-content.js.map +1 -1
- package/card/card-media.d.ts +5 -2
- package/card/card-media.d.ts.map +1 -1
- package/card/card-media.js +8 -5
- package/card/card-media.js.map +1 -1
- package/card/card.d.ts +4 -4
- package/card/card.d.ts.map +1 -1
- package/card/card.js +5 -5
- package/card/card.js.map +1 -1
- package/checkbox/checkbox-list-item.d.ts +4 -4
- package/checkbox/checkbox-list-item.d.ts.map +1 -1
- package/checkbox/checkbox-list-item.js +5 -5
- package/checkbox/checkbox-list-item.js.map +1 -1
- package/checkbox/checkbox.d.ts +10 -3
- package/checkbox/checkbox.d.ts.map +1 -1
- package/checkbox/checkbox.js +14 -7
- package/checkbox/checkbox.js.map +1 -1
- package/chip/chip-set.d.ts +3 -3
- package/chip/chip-set.d.ts.map +1 -1
- package/chip/chip-set.js +6 -6
- package/chip/chip-set.js.map +1 -1
- package/chip/chip.d.ts +8 -5
- package/chip/chip.d.ts.map +1 -1
- package/chip/chip.js +23 -20
- package/chip/chip.js.map +1 -1
- package/chip-field/chip-field.d.ts +6 -3
- package/chip-field/chip-field.d.ts.map +1 -1
- package/chip-field/chip-field.js +9 -9
- package/chip-field/chip-field.js.map +1 -1
- package/collapse/collapse.d.ts +26 -0
- package/collapse/collapse.d.ts.map +1 -0
- package/collapse/collapse.js +62 -0
- package/collapse/collapse.js.map +1 -0
- package/collapse/collapse.styles.d.ts +2 -0
- package/collapse/collapse.styles.d.ts.map +1 -0
- package/collapse/collapse.styles.js +8 -0
- package/collapse/collapse.styles.js.map +1 -0
- package/config.js.map +1 -1
- package/css/universal-material.css +2 -1
- package/css/universal-material.min.css +2 -1
- package/custom-elements.json +17175 -9684
- package/datepicker/datepicker.d.ts +54 -3
- package/datepicker/datepicker.d.ts.map +1 -1
- package/datepicker/datepicker.js +202 -6
- package/datepicker/datepicker.js.map +1 -1
- package/datepicker/datepicker.styles.d.ts.map +1 -1
- package/datepicker/datepicker.styles.js +25 -0
- package/datepicker/datepicker.styles.js.map +1 -1
- package/datepicker/format.d.ts +19 -0
- package/datepicker/format.d.ts.map +1 -0
- package/datepicker/format.js +47 -0
- package/datepicker/format.js.map +1 -0
- package/datepicker/range-datepicker.d.ts +58 -0
- package/datepicker/range-datepicker.d.ts.map +1 -0
- package/datepicker/range-datepicker.js +212 -0
- package/datepicker/range-datepicker.js.map +1 -0
- package/dialog/confirm-dialog-builder.d.ts +3 -3
- package/dialog/confirm-dialog-builder.d.ts.map +1 -1
- package/dialog/confirm-dialog-builder.js.map +1 -1
- package/dialog/dialog-builder.d.ts +5 -4
- package/dialog/dialog-builder.d.ts.map +1 -1
- package/dialog/dialog-builder.js +10 -3
- package/dialog/dialog-builder.js.map +1 -1
- package/dialog/dialog-button-def.d.ts +3 -3
- package/dialog/dialog-button-def.d.ts.map +1 -1
- package/dialog/dialog-button-def.js.map +1 -1
- package/dialog/dialog.d.ts +10 -2
- package/dialog/dialog.d.ts.map +1 -1
- package/dialog/dialog.js +22 -14
- package/dialog/dialog.js.map +1 -1
- package/dialog/message-dialog-builder.d.ts +2 -2
- package/dialog/message-dialog-builder.d.ts.map +1 -1
- package/dialog/message-dialog-builder.js.map +1 -1
- package/elevation/elevation.d.ts +2 -2
- package/elevation/elevation.d.ts.map +1 -1
- package/elevation/elevation.js +4 -4
- package/elevation/elevation.js.map +1 -1
- package/expansion-panel/expansion-panel-container.d.ts +24 -0
- package/expansion-panel/expansion-panel-container.d.ts.map +1 -0
- package/expansion-panel/expansion-panel-container.js +54 -0
- package/expansion-panel/expansion-panel-container.js.map +1 -0
- package/expansion-panel/expansion-panel-container.styles.d.ts +2 -0
- package/expansion-panel/expansion-panel-container.styles.d.ts.map +1 -0
- package/expansion-panel/expansion-panel-container.styles.js +9 -0
- package/expansion-panel/expansion-panel-container.styles.js.map +1 -0
- package/expansion-panel/expansion-panel.d.ts +37 -0
- package/expansion-panel/expansion-panel.d.ts.map +1 -0
- package/expansion-panel/expansion-panel.js +89 -0
- package/expansion-panel/expansion-panel.js.map +1 -0
- package/expansion-panel/expansion-panel.styles.d.ts +2 -0
- package/expansion-panel/expansion-panel.styles.d.ts.map +1 -0
- package/expansion-panel/expansion-panel.styles.js +66 -0
- package/expansion-panel/expansion-panel.styles.js.map +1 -0
- package/field/field-base.d.ts +17 -3
- package/field/field-base.d.ts.map +1 -1
- package/field/field-base.js +30 -20
- package/field/field-base.js.map +1 -1
- package/field/field-defaults-context.d.ts +2 -2
- package/field/field-defaults-context.d.ts.map +1 -1
- package/field/field-defaults-context.js.map +1 -1
- package/field/field-defaults.d.ts +3 -3
- package/field/field-defaults.d.ts.map +1 -1
- package/field/field-defaults.js.map +1 -1
- package/field/field-variant.d.ts +1 -1
- package/field/field-variant.d.ts.map +1 -1
- package/field/field-variant.js.map +1 -1
- package/field/field.d.ts +7 -3
- package/field/field.d.ts.map +1 -1
- package/field/field.js +10 -6
- package/field/field.js.map +1 -1
- package/icon/icon.d.ts +2 -2
- package/icon/icon.d.ts.map +1 -1
- package/icon/icon.js +4 -4
- package/icon/icon.js.map +1 -1
- package/index.d.ts +29 -1
- package/index.d.ts.map +1 -1
- package/index.js +29 -1
- package/index.js.map +1 -1
- package/list/list-item.d.ts +19 -2
- package/list/list-item.d.ts.map +1 -1
- package/list/list-item.js +29 -6
- package/list/list-item.js.map +1 -1
- package/list/list-item.styles.d.ts.map +1 -1
- package/list/list-item.styles.js +13 -0
- package/list/list-item.styles.js.map +1 -1
- package/list/list.d.ts +2 -2
- package/list/list.d.ts.map +1 -1
- package/list/list.js +4 -4
- package/list/list.js.map +1 -1
- package/menu/menu-item.d.ts +9 -3
- package/menu/menu-item.d.ts.map +1 -1
- package/menu/menu-item.js +16 -10
- package/menu/menu-item.js.map +1 -1
- package/menu/menu.d.ts +18 -2
- package/menu/menu.d.ts.map +1 -1
- package/menu/menu.js +37 -18
- package/menu/menu.js.map +1 -1
- package/menu/menu.styles.d.ts.map +1 -1
- package/menu/menu.styles.js +5 -0
- package/menu/menu.styles.js.map +1 -1
- package/navigation/drawer-headline.d.ts +2 -2
- package/navigation/drawer-headline.d.ts.map +1 -1
- package/navigation/drawer-headline.js +6 -6
- package/navigation/drawer-headline.js.map +1 -1
- package/navigation/drawer-headline.styles.js +1 -1
- package/navigation/drawer-headline.styles.js.map +1 -1
- package/navigation/drawer-item.d.ts +3 -3
- package/navigation/drawer-item.d.ts.map +1 -1
- package/navigation/drawer-item.js +17 -12
- package/navigation/drawer-item.js.map +1 -1
- package/navigation/drawer.d.ts +2 -2
- package/navigation/drawer.d.ts.map +1 -1
- package/navigation/drawer.js +4 -4
- package/navigation/drawer.js.map +1 -1
- package/navigation/side-navigation.d.ts +9 -2
- package/navigation/side-navigation.d.ts.map +1 -1
- package/navigation/side-navigation.js +15 -8
- package/navigation/side-navigation.js.map +1 -1
- package/navigation-bar/navigation-bar-item.d.ts +40 -0
- package/navigation-bar/navigation-bar-item.d.ts.map +1 -0
- package/navigation-bar/navigation-bar-item.js +113 -0
- package/navigation-bar/navigation-bar-item.js.map +1 -0
- package/navigation-bar/navigation-bar-item.styles.d.ts +2 -0
- package/navigation-bar/navigation-bar-item.styles.d.ts.map +1 -0
- package/navigation-bar/navigation-bar-item.styles.js +101 -0
- package/navigation-bar/navigation-bar-item.styles.js.map +1 -0
- package/navigation-bar/navigation-bar.d.ts +40 -0
- package/navigation-bar/navigation-bar.d.ts.map +1 -0
- package/navigation-bar/navigation-bar.js +85 -0
- package/navigation-bar/navigation-bar.js.map +1 -0
- package/navigation-bar/navigation-bar.styles.d.ts +2 -0
- package/navigation-bar/navigation-bar.styles.d.ts.map +1 -0
- package/navigation-bar/navigation-bar.styles.js +44 -0
- package/navigation-bar/navigation-bar.styles.js.map +1 -0
- package/navigation-rail/navigation-rail-headline.d.ts +23 -0
- package/navigation-rail/navigation-rail-headline.d.ts.map +1 -0
- package/navigation-rail/navigation-rail-headline.js +28 -0
- package/navigation-rail/navigation-rail-headline.js.map +1 -0
- package/navigation-rail/navigation-rail-headline.styles.d.ts +2 -0
- package/navigation-rail/navigation-rail-headline.styles.d.ts.map +1 -0
- package/navigation-rail/navigation-rail-headline.styles.js +19 -0
- package/navigation-rail/navigation-rail-headline.styles.js.map +1 -0
- package/navigation-rail/navigation-rail-item.d.ts +58 -0
- package/navigation-rail/navigation-rail-item.d.ts.map +1 -0
- package/navigation-rail/navigation-rail-item.js +160 -0
- package/navigation-rail/navigation-rail-item.js.map +1 -0
- package/navigation-rail/navigation-rail-item.styles.d.ts +2 -0
- package/navigation-rail/navigation-rail-item.styles.d.ts.map +1 -0
- package/navigation-rail/navigation-rail-item.styles.js +182 -0
- package/navigation-rail/navigation-rail-item.styles.js.map +1 -0
- package/navigation-rail/navigation-rail.d.ts +66 -0
- package/navigation-rail/navigation-rail.d.ts.map +1 -0
- package/navigation-rail/navigation-rail.js +223 -0
- package/navigation-rail/navigation-rail.js.map +1 -0
- package/navigation-rail/navigation-rail.styles.d.ts +2 -0
- package/navigation-rail/navigation-rail.styles.d.ts.map +1 -0
- package/navigation-rail/navigation-rail.styles.js +220 -0
- package/navigation-rail/navigation-rail.styles.js.map +1 -0
- package/overflow-menu/overflow-menu-item.d.ts +8 -0
- package/overflow-menu/overflow-menu-item.d.ts.map +1 -1
- package/overflow-menu/overflow-menu-item.js +8 -0
- package/overflow-menu/overflow-menu-item.js.map +1 -1
- package/overflow-menu/overflow-menu.d.ts +8 -2
- package/overflow-menu/overflow-menu.d.ts.map +1 -1
- package/overflow-menu/overflow-menu.js +10 -1
- package/overflow-menu/overflow-menu.js.map +1 -1
- package/package.json +21 -5
- package/progress/circular-progress.d.ts +9 -2
- package/progress/circular-progress.d.ts.map +1 -1
- package/progress/circular-progress.js +9 -6
- package/progress/circular-progress.js.map +1 -1
- package/progress/progress-bar.d.ts +9 -2
- package/progress/progress-bar.d.ts.map +1 -1
- package/progress/progress-bar.js +9 -6
- package/progress/progress-bar.js.map +1 -1
- package/radio/radio-list-item.d.ts +4 -4
- package/radio/radio-list-item.d.ts.map +1 -1
- package/radio/radio-list-item.js +5 -5
- package/radio/radio-list-item.js.map +1 -1
- package/radio/radio.d.ts +6 -3
- package/radio/radio.d.ts.map +1 -1
- package/radio/radio.js +9 -6
- package/radio/radio.js.map +1 -1
- package/ripple/ripple.d.ts +2 -2
- package/ripple/ripple.d.ts.map +1 -1
- package/ripple/ripple.js +9 -9
- package/ripple/ripple.js.map +1 -1
- package/scaffold/pane.d.ts +127 -0
- package/scaffold/pane.d.ts.map +1 -0
- package/scaffold/pane.js +220 -0
- package/scaffold/pane.js.map +1 -0
- package/scaffold/pane.styles.d.ts +2 -0
- package/scaffold/pane.styles.d.ts.map +1 -0
- package/scaffold/pane.styles.js +1909 -0
- package/scaffold/pane.styles.js.map +1 -0
- package/scaffold/scaffold.d.ts +45 -0
- package/scaffold/scaffold.d.ts.map +1 -0
- package/scaffold/scaffold.js +170 -0
- package/scaffold/scaffold.js.map +1 -0
- package/scaffold/scaffold.styles.d.ts +2 -0
- package/scaffold/scaffold.styles.d.ts.map +1 -0
- package/scaffold/scaffold.styles.js +69 -0
- package/scaffold/scaffold.styles.js.map +1 -0
- package/scaffold/scroll-container-context.d.ts +4 -0
- package/scaffold/scroll-container-context.d.ts.map +1 -0
- package/scaffold/scroll-container-context.js +3 -0
- package/scaffold/scroll-container-context.js.map +1 -0
- package/scss/utilities/_divider.scss +4 -0
- package/search/search.d.ts +6 -3
- package/search/search.d.ts.map +1 -1
- package/search/search.js +10 -7
- package/search/search.js.map +1 -1
- package/search/search.styles.d.ts.map +1 -1
- package/search/search.styles.js +7 -2
- package/search/search.styles.js.map +1 -1
- package/select/option.d.ts +9 -3
- package/select/option.d.ts.map +1 -1
- package/select/option.js +14 -8
- package/select/option.js.map +1 -1
- package/select/select-navigation-controller.d.ts +4 -4
- package/select/select-navigation-controller.d.ts.map +1 -1
- package/select/select-navigation-controller.js.map +1 -1
- package/select/select.d.ts +22 -12
- package/select/select.d.ts.map +1 -1
- package/select/select.js +81 -31
- package/select/select.js.map +1 -1
- package/shared/button-wrapper.d.ts +4 -1
- package/shared/button-wrapper.d.ts.map +1 -1
- package/shared/button-wrapper.js +8 -8
- package/shared/button-wrapper.js.map +1 -1
- package/shared/char-count-text-field/native-text-field-wrapper.d.ts +15 -2
- package/shared/char-count-text-field/native-text-field-wrapper.d.ts.map +1 -1
- package/shared/char-count-text-field/native-text-field-wrapper.js +16 -6
- package/shared/char-count-text-field/native-text-field-wrapper.js.map +1 -1
- package/shared/menu-field/menu-field-navigation-controller.d.ts +3 -3
- package/shared/menu-field/menu-field-navigation-controller.d.ts.map +1 -1
- package/shared/menu-field/menu-field-navigation-controller.js.map +1 -1
- package/shared/menu-field/menu-field.d.ts +5 -5
- package/shared/menu-field/menu-field.d.ts.map +1 -1
- package/shared/menu-field/menu-field.js.map +1 -1
- package/shared/selection-control/selection-control-list-item.d.ts +2 -2
- package/shared/selection-control/selection-control-list-item.d.ts.map +1 -1
- package/shared/selection-control/selection-control-list-item.js +14 -1
- package/shared/selection-control/selection-control-list-item.js.map +1 -1
- package/shared/selection-control/selection-control.d.ts +10 -1
- package/shared/selection-control/selection-control.d.ts.map +1 -1
- package/shared/selection-control/selection-control.js +24 -7
- package/shared/selection-control/selection-control.js.map +1 -1
- package/shared/sets/set-base.d.ts +1 -1
- package/shared/sets/set-base.d.ts.map +1 -1
- package/shared/sets/set-base.js +2 -2
- package/shared/sets/set-base.js.map +1 -1
- package/shared/text-field-base/text-field-base.d.ts +37 -2
- package/shared/text-field-base/text-field-base.d.ts.map +1 -1
- package/shared/text-field-base/text-field-base.js +66 -4
- package/shared/text-field-base/text-field-base.js.map +1 -1
- package/skills/badge/SKILL.md +43 -0
- package/skills/buttons/SKILL.md +115 -0
- package/skills/card/SKILL.md +162 -0
- package/skills/chips/SKILL.md +95 -0
- package/skills/collapse/SKILL.md +37 -0
- package/skills/datepicker/SKILL.md +110 -0
- package/skills/dialog/SKILL.md +92 -0
- package/skills/drawer/SKILL.md +94 -0
- package/skills/expansion-panel/SKILL.md +65 -0
- package/skills/fab/SKILL.md +79 -0
- package/skills/list/SKILL.md +105 -0
- package/skills/menu/SKILL.md +120 -0
- package/skills/navigation-bar/SKILL.md +87 -0
- package/skills/navigation-rail/SKILL.md +127 -0
- package/skills/overview/SKILL.md +44 -0
- package/skills/progress/SKILL.md +63 -0
- package/skills/scaffold/SKILL.md +392 -0
- package/skills/search/SKILL.md +65 -0
- package/skills/select/SKILL.md +120 -0
- package/skills/selection-controls/SKILL.md +88 -0
- package/skills/setup/SKILL.md +58 -0
- package/skills/slider/SKILL.md +119 -0
- package/skills/snackbar/SKILL.md +70 -0
- package/skills/tab-bar/SKILL.md +55 -0
- package/skills/text-field/SKILL.md +114 -0
- package/skills/theming/SKILL.md +80 -0
- package/skills/top-app-bar/SKILL.md +64 -0
- package/skills/typeahead/SKILL.md +113 -0
- package/slider/slider.d.ts +73 -0
- package/slider/slider.d.ts.map +1 -0
- package/slider/slider.js +506 -0
- package/slider/slider.js.map +1 -0
- package/slider/slider.styles.d.ts +2 -0
- package/slider/slider.styles.d.ts.map +1 -0
- package/slider/slider.styles.js +292 -0
- package/slider/slider.styles.js.map +1 -0
- package/snackbar/snackbar.d.ts +13 -4
- package/snackbar/snackbar.d.ts.map +1 -1
- package/snackbar/snackbar.js +37 -28
- package/snackbar/snackbar.js.map +1 -1
- package/snackbar/snackbar.styles.js +1 -1
- package/snackbar/snackbar.styles.js.map +1 -1
- package/switch/switch-list-item.d.ts +4 -4
- package/switch/switch-list-item.d.ts.map +1 -1
- package/switch/switch-list-item.js +5 -5
- package/switch/switch-list-item.js.map +1 -1
- package/switch/switch.d.ts +3 -3
- package/switch/switch.d.ts.map +1 -1
- package/switch/switch.js +5 -5
- package/switch/switch.js.map +1 -1
- package/tab-bar/tab-bar.d.ts +9 -6
- package/tab-bar/tab-bar.d.ts.map +1 -1
- package/tab-bar/tab-bar.js +43 -23
- package/tab-bar/tab-bar.js.map +1 -1
- package/tab-bar/tab.d.ts +10 -5
- package/tab-bar/tab.d.ts.map +1 -1
- package/tab-bar/tab.js +14 -9
- package/tab-bar/tab.js.map +1 -1
- package/text-area/text-area.d.ts +6 -3
- package/text-area/text-area.d.ts.map +1 -1
- package/text-area/text-area.js +12 -9
- package/text-area/text-area.js.map +1 -1
- package/text-field/text-field.d.ts +31 -3
- package/text-field/text-field.d.ts.map +1 -1
- package/text-field/text-field.js +53 -13
- package/text-field/text-field.js.map +1 -1
- package/typeahead/highlight.d.ts +2 -2
- package/typeahead/highlight.d.ts.map +1 -1
- package/typeahead/highlight.js +7 -7
- package/typeahead/highlight.js.map +1 -1
- package/typeahead/typeahead-template-render.d.ts +4 -0
- package/typeahead/typeahead-template-render.d.ts.map +1 -1
- package/typeahead/typeahead-template-render.js +4 -0
- package/typeahead/typeahead-template-render.js.map +1 -1
- package/typeahead/typeahead.d.ts +14 -7
- package/typeahead/typeahead.d.ts.map +1 -1
- package/typeahead/typeahead.js +29 -18
- package/typeahead/typeahead.js.map +1 -1
- package/vscode.html-custom-data.json +1146 -326
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Lay out an app screen with u-scaffold — top app bar, flex-row body that accepts plain content and any number of u-pane children, an optional navigation bar at the bottom, and a FAB anchored above the bar. Panes behave per a mode attribute (fixed / collapsible / sidebar / fullscreen) that can vary by Material 3 breakpoint.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Scaffold (page layout)
|
|
6
|
+
|
|
7
|
+
`<u-scaffold>` is a layout container that hosts a top app bar, a flex-row body, an optional navigation bar and a floating FAB. The body accepts plain content and any number of `<u-pane>` children as siblings — panes are flex items in DOM order; non-pane children flex to fill the remaining space.
|
|
8
|
+
|
|
9
|
+
## Basic usage
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<u-scaffold style="height: 100vh">
|
|
13
|
+
<u-top-app-bar slot="top-bar" size="large" headline="Inbox">
|
|
14
|
+
<u-icon-button slot="leading-icon">
|
|
15
|
+
<span class="material-symbols-outlined">menu</span>
|
|
16
|
+
</u-icon-button>
|
|
17
|
+
</u-top-app-bar>
|
|
18
|
+
|
|
19
|
+
<main style="padding: 16px 24px; overflow: auto">
|
|
20
|
+
<!-- scrollable page content -->
|
|
21
|
+
</main>
|
|
22
|
+
|
|
23
|
+
<u-navigation-bar slot="bottom-bar">
|
|
24
|
+
<u-navigation-bar-item active>
|
|
25
|
+
<span class="material-symbols-outlined" slot="icon">inbox</span>
|
|
26
|
+
Inbox
|
|
27
|
+
</u-navigation-bar-item>
|
|
28
|
+
</u-navigation-bar>
|
|
29
|
+
|
|
30
|
+
<u-fab slot="fab" color="primary">
|
|
31
|
+
<span class="material-symbols-outlined">edit</span>
|
|
32
|
+
</u-fab>
|
|
33
|
+
</u-scaffold>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The scaffold:
|
|
37
|
+
- arranges panes and non-pane content in a flex row with a 16dp gap,
|
|
38
|
+
- auto-sets `position="absolute"` on slotted `<u-top-app-bar>` / `<u-navigation-bar>` so they anchor against the scaffold (not the viewport),
|
|
39
|
+
- measures the navigation bar's height and offsets the FAB above it (16dp gap per M3),
|
|
40
|
+
- writes `data-align="start|end"` on each `<u-pane>` child based on whether it appears before or after the first non-pane child — used by sidebar/fullscreen modes to pick the slide direction,
|
|
41
|
+
- exposes itself as a named CSS container (`container-type: inline-size; container-name: u-scaffold`) so panes can opt into `query-context="container"`.
|
|
42
|
+
|
|
43
|
+
## Multi-pane layout via flex
|
|
44
|
+
|
|
45
|
+
Drop panes around the body content; DOM order is visual order. Panes default to `mode="fixed"` (always visible flex item) — they keep their content's intrinsic width unless you style them.
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<u-scaffold style="height: 100vh">
|
|
49
|
+
<u-pane variant="filled" style="width: 240px">
|
|
50
|
+
<!-- navigation pane -->
|
|
51
|
+
</u-pane>
|
|
52
|
+
|
|
53
|
+
<u-pane variant="transparent" style="flex: 1 1 0">
|
|
54
|
+
<!-- main body content; transparent = no background, scrolls inside .content -->
|
|
55
|
+
</u-pane>
|
|
56
|
+
|
|
57
|
+
<u-pane variant="filled" style="width: 320px">
|
|
58
|
+
<!-- supporting pane -->
|
|
59
|
+
</u-pane>
|
|
60
|
+
</u-scaffold>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The scaffold applies `flex: 1 1 0` to every non-pane child via `::slotted(:not(u-pane))`, so a plain `<main>` would also flex correctly — but see the recommendation below for why panes are preferred when other panes are present.
|
|
64
|
+
|
|
65
|
+
### Recommendation: be consistent — if you use panes, use them for every body sibling
|
|
66
|
+
|
|
67
|
+
When any body child of a scaffold is a `<u-pane>`, prefer making **all** body children panes (even the central content). Mixing `<u-pane>` with raw `<main>` / `<aside>` creates three forms of inconsistency:
|
|
68
|
+
|
|
69
|
+
1. **Surface**: panes pick up Material 3 surface tokens (filled = `surface-container-low` + 12dp corner; transparent = no bg). Raw `<main>` sits on `surface` without that shape. Side-by-side, the pane looks like a "real panel" and the main looks like loose content.
|
|
70
|
+
2. **Scrolling**: panes scroll inside their internal `.content` part — set the pane's height and overflow is handled automatically. Raw `<main>` needs `overflow: auto` set explicitly and `min-height: 0` to work right inside the flex row.
|
|
71
|
+
3. **Responsive modes**: panes accept `mode` / `mode-sm` / `mode-md` / `mode-lg` / `mode-xl` for breakpoint-driven layout changes. Raw `<main>` doesn't — you'd have to write `@media` rules to mirror the same behavior.
|
|
72
|
+
|
|
73
|
+
Use the `transparent` variant for the central content area when you want it to read as the page surface rather than a raised panel:
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<u-scaffold style="height: 100vh">
|
|
77
|
+
<u-pane mode="sidebar" mode-md="fixed" variant="filled" style="width: 240px">…sub-nav…</u-pane>
|
|
78
|
+
<u-pane variant="transparent" style="flex: 1 1 0">…page content…</u-pane>
|
|
79
|
+
</u-scaffold>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The rule is "be deliberate about the mix": use raw `<main>` when no panes exist in the layout at all (simpler), and use panes everywhere when any pane is present (consistent).
|
|
83
|
+
|
|
84
|
+
## Canonical patterns
|
|
85
|
+
|
|
86
|
+
Two layouts come up over and over in real apps. Use these as the starting point and tune from there.
|
|
87
|
+
|
|
88
|
+
### Pattern A — "Settings / section nav" (settings, profile, admin)
|
|
89
|
+
|
|
90
|
+
A settings screen **is a list-detail**: the section nav is the *list* and the section's content is the *detail*. Don't model it as "a modal sidebar + always-on content" — that hides the nav on mobile and forces a redundant mobile picker. Instead:
|
|
91
|
+
|
|
92
|
+
- **Section nav = the list**: `mode="fixed"` (always visible). On mobile it fills the viewport (it's the only thing shown until you pick a section); on md+ it's a fixed-width column. Drive the width with a class, not inline style, so a media query can switch it.
|
|
93
|
+
- **Section content = the detail**: `mode="fullscreen" mode-md="fixed"`. On mobile, picking a section opens the content as a fullscreen overlay with a back button; on md+ both sit side by side.
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<u-scaffold style="height: 100vh">
|
|
97
|
+
<u-top-app-bar slot="top-bar" headline="Settings">…</u-top-app-bar>
|
|
98
|
+
|
|
99
|
+
<!-- Nav (the list): fills the screen on mobile, fixed column on md+ -->
|
|
100
|
+
<u-pane id="nav" mode="fixed" variant="filled" class="settings-nav">
|
|
101
|
+
<u-drawer>
|
|
102
|
+
<u-drawer-item active data-section="general" keep-drawer-open>General</u-drawer-item>
|
|
103
|
+
<u-drawer-item data-section="security" keep-drawer-open>Security</u-drawer-item>
|
|
104
|
+
</u-drawer>
|
|
105
|
+
</u-pane>
|
|
106
|
+
|
|
107
|
+
<!-- Content (the detail): fullscreen overlay on mobile, fixed on md+ -->
|
|
108
|
+
<u-pane id="content" mode="fullscreen" mode-md="fixed" variant="transparent" style="flex: 1 1 0; min-width: 0;">
|
|
109
|
+
<div slot="header" class="settings-back"><!-- shown only on mobile -->
|
|
110
|
+
<u-icon-button onclick="document.getElementById('content').close()">
|
|
111
|
+
<span class="material-symbols-outlined">arrow_back</span>
|
|
112
|
+
</u-icon-button>
|
|
113
|
+
<span class="u-title-s">Settings</span>
|
|
114
|
+
</div>
|
|
115
|
+
<!-- sections, forms, etc. -->
|
|
116
|
+
</u-pane>
|
|
117
|
+
</u-scaffold>
|
|
118
|
+
|
|
119
|
+
<style>
|
|
120
|
+
.settings-nav { flex: 1 1 0; } /* mobile: nav fills viewport */
|
|
121
|
+
@media (min-width: 840px) { .settings-nav { flex: 0 0 320px; } } /* md+: fixed column */
|
|
122
|
+
.settings-back { display: none; align-items: center; gap: 8px; padding: 8px 12px; }
|
|
123
|
+
@media (max-width: 839.98px) { .settings-back { display: flex; } } /* back only on mobile */
|
|
124
|
+
</style>
|
|
125
|
+
|
|
126
|
+
<script>
|
|
127
|
+
// Picking a section reveals it AND opens the detail (no-op at md+ where it's fixed).
|
|
128
|
+
document.querySelectorAll('u-drawer-item[data-section]').forEach(it =>
|
|
129
|
+
it.addEventListener('click', () => {
|
|
130
|
+
showSection(it.dataset.section);
|
|
131
|
+
document.getElementById('content').show();
|
|
132
|
+
}));
|
|
133
|
+
</script>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Two cascade traps this pattern walks into (both bit real builds):
|
|
137
|
+
- **`display` on the mobile-only back header**: put it in a class with the media query, never `style="display:flex"` inline — inline beats the class's `display:none` and the header leaks onto desktop.
|
|
138
|
+
- **Pane width**: `mode="fixed"` panes set their own `flex` internally; override it from a document-scope **class** (not the component's `:host`) so a media query can flip `flex: 1 1 0` ↔ `flex: 0 0 320px`.
|
|
139
|
+
|
|
140
|
+
### Pattern B — "List-detail" (mail, messaging, file managers, CRM contacts)
|
|
141
|
+
|
|
142
|
+
Three panes: a small top-level nav, a list of items, and a detail view. The detail collapses to a fullscreen overlay on mobile so it can take over the viewport when the user picks an item, then slides back out when they hit back.
|
|
143
|
+
|
|
144
|
+
```html
|
|
145
|
+
<u-scaffold style="height: 100vh">
|
|
146
|
+
<u-top-app-bar slot="top-bar" headline="Mail">
|
|
147
|
+
<u-icon-button slot="leading-icon" onclick="document.getElementById('mailnav').toggle()">
|
|
148
|
+
<span class="material-symbols-outlined">menu</span>
|
|
149
|
+
</u-icon-button>
|
|
150
|
+
</u-top-app-bar>
|
|
151
|
+
|
|
152
|
+
<!-- Nav: modal on mobile/medium, fixed at lg -->
|
|
153
|
+
<u-pane id="mailnav" mode="sidebar" mode-lg="fixed" variant="filled" style="width: 240px;">
|
|
154
|
+
<u-drawer>
|
|
155
|
+
<u-drawer-item active>
|
|
156
|
+
<span slot="icon" class="material-symbols-outlined">inbox</span>
|
|
157
|
+
Inbox
|
|
158
|
+
<span slot="badge">12</span>
|
|
159
|
+
</u-drawer-item>
|
|
160
|
+
<u-drawer-item>
|
|
161
|
+
<span slot="icon" class="material-symbols-outlined">send</span>
|
|
162
|
+
Sent
|
|
163
|
+
</u-drawer-item>
|
|
164
|
+
</u-drawer>
|
|
165
|
+
</u-pane>
|
|
166
|
+
|
|
167
|
+
<!-- List: always in-flow. Filled gives it a distinct surface. -->
|
|
168
|
+
<u-pane variant="filled" mode="fixed" style="width: 360px;">
|
|
169
|
+
<div slot="header" style="padding: 8px 12px; display: flex; align-items: center; gap: 8px;">
|
|
170
|
+
<strong>Primary · 5 messages</strong>
|
|
171
|
+
</div>
|
|
172
|
+
<u-list>
|
|
173
|
+
<u-list-item selectable onclick="openMessage(...)">…</u-list-item>
|
|
174
|
+
<!-- ... -->
|
|
175
|
+
</u-list>
|
|
176
|
+
</u-pane>
|
|
177
|
+
|
|
178
|
+
<!-- Detail: fullscreen overlay on mobile, fixed in-flow on md+. THIS is the key. -->
|
|
179
|
+
<u-pane id="detail" mode="fullscreen" mode-md="fixed" variant="filled" style="flex: 1 1 0; min-width: 0;">
|
|
180
|
+
<div slot="header" style="display: flex; align-items: center; gap: 4px; padding: 8px 12px;">
|
|
181
|
+
<u-icon-button onclick="document.getElementById('detail').close()" aria-label="Back">
|
|
182
|
+
<span class="material-symbols-outlined">arrow_back</span>
|
|
183
|
+
</u-icon-button>
|
|
184
|
+
<span style="flex: 1"></span>
|
|
185
|
+
<u-icon-button aria-label="Archive"><span class="material-symbols-outlined">archive</span></u-icon-button>
|
|
186
|
+
</div>
|
|
187
|
+
<div style="padding: 0 24px 24px;">
|
|
188
|
+
<!-- subject, sender, body -->
|
|
189
|
+
</div>
|
|
190
|
+
</u-pane>
|
|
191
|
+
</u-scaffold>
|
|
192
|
+
|
|
193
|
+
<script>
|
|
194
|
+
function openMessage(id) {
|
|
195
|
+
// populate detail content...
|
|
196
|
+
document.getElementById('detail').show(); // opens fullscreen overlay on mobile, no-op at md+ where it's already fixed
|
|
197
|
+
}
|
|
198
|
+
</script>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
What makes this work:
|
|
202
|
+
|
|
203
|
+
- **Nav pane**: `mode="sidebar" mode-lg="fixed"` — closed-by-default modal until lg, where it docks in-flow. (`mode-md="collapsible"` is another option if you want it visible at md but collapsible.)
|
|
204
|
+
- **List pane**: `mode="fixed"` — always visible. `filled` so it has its own surface, distinct from the detail.
|
|
205
|
+
- **Detail pane**: `mode="fullscreen" mode-md="fixed"` — **this is the linchpin of the list-detail pattern**. At mobile sizes the detail slides in OVER the list when opened; the back button calls `pane.close()` to dismiss. At md+ it's a fixed flex item beside the list. The mode change is pure CSS; the `open` property persists across breakpoints (once you set it, it sticks).
|
|
206
|
+
- **Header slot**: each pane uses `slot="header"` for its toolbar so it stays pinned while the list/detail content scrolls.
|
|
207
|
+
|
|
208
|
+
There's a working version of this in the docs site under `docs/src/app/screens/scaffold-list-detail/` (a Mail clone) — read it whenever you need the full responsive choreography.
|
|
209
|
+
|
|
210
|
+
## Modes and breakpoints
|
|
211
|
+
|
|
212
|
+
Each pane picks a `mode` (default `fixed`). Optional `mode-sm` / `mode-md` / `mode-lg` / `mode-xl` attributes override the mode from that Material 3 breakpoint upward. The largest matching breakpoint wins — all resolution is CSS, no `matchMedia`.
|
|
213
|
+
|
|
214
|
+
| Mode | Behaviour |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `fixed` (default) | In-flow flex item, always visible. `open` is ignored. |
|
|
217
|
+
| `collapsible` | In-flow when `open=true`, removed from the row when `open=false` (animated). |
|
|
218
|
+
| `sidebar` | Modal drawer overlay against the scaffold when `open=true`. Slides from the leading or trailing edge per DOM order. Closed by default. |
|
|
219
|
+
| `fullscreen` | Like `sidebar` but full-width and sits above the top app bar (no scrim). Closed by default. |
|
|
220
|
+
|
|
221
|
+
```html
|
|
222
|
+
<u-scaffold style="height: 100vh">
|
|
223
|
+
<!-- Navigation: sidebar on mobile, collapsible at md+, permanent at lg+ -->
|
|
224
|
+
<u-pane
|
|
225
|
+
id="nav"
|
|
226
|
+
mode="sidebar"
|
|
227
|
+
mode-md="collapsible"
|
|
228
|
+
mode-lg="fixed"
|
|
229
|
+
variant="filled"
|
|
230
|
+
style="width: 240px">
|
|
231
|
+
<!-- navigation -->
|
|
232
|
+
</u-pane>
|
|
233
|
+
|
|
234
|
+
<main style="overflow: auto">…</main>
|
|
235
|
+
|
|
236
|
+
<!-- Inspector: fullscreen on mobile, permanent at md+ -->
|
|
237
|
+
<u-pane
|
|
238
|
+
id="inspector"
|
|
239
|
+
mode="fullscreen"
|
|
240
|
+
mode-md="fixed"
|
|
241
|
+
variant="filled"
|
|
242
|
+
style="width: 320px">
|
|
243
|
+
<!-- details -->
|
|
244
|
+
</u-pane>
|
|
245
|
+
</u-scaffold>
|
|
246
|
+
|
|
247
|
+
<script>
|
|
248
|
+
document.getElementById('nav').show(); // open
|
|
249
|
+
document.getElementById('nav').toggle(); // flip
|
|
250
|
+
document.getElementById('inspector').close();
|
|
251
|
+
</script>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
The default value of `open` follows the base `mode`: `true` for `fixed` / `collapsible`, `false` for `sidebar` / `fullscreen`. Once you write to `open` (attribute or property), your value sticks regardless of mode changes.
|
|
255
|
+
|
|
256
|
+
## Container queries
|
|
257
|
+
|
|
258
|
+
Switch a pane to react to the scaffold's own width rather than the viewport with `query-context="container"`. Useful when a scaffold is embedded in a narrower outer layout.
|
|
259
|
+
|
|
260
|
+
```html
|
|
261
|
+
<u-pane mode="sidebar" mode-md="fixed" query-context="container">
|
|
262
|
+
<!-- mode-md kicks in at md *of the scaffold's box*, not the viewport -->
|
|
263
|
+
</u-pane>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Hosting a drawer or rail
|
|
267
|
+
|
|
268
|
+
`<u-drawer>` and `<u-navigation-rail>` are first-class body siblings or pane contents — there's no special slot.
|
|
269
|
+
|
|
270
|
+
```html
|
|
271
|
+
<u-scaffold>
|
|
272
|
+
<u-top-app-bar slot="top-bar" headline="Mail">
|
|
273
|
+
<u-icon-button slot="leading-icon">
|
|
274
|
+
<span class="material-symbols-outlined">menu</span>
|
|
275
|
+
</u-icon-button>
|
|
276
|
+
</u-top-app-bar>
|
|
277
|
+
|
|
278
|
+
<!-- Permanent drawer below lg, modal sidebar above -->
|
|
279
|
+
<u-pane id="nav" mode="sidebar" mode-lg="fixed" style="width: 360px">
|
|
280
|
+
<u-drawer>
|
|
281
|
+
<u-drawer-headline>Mail</u-drawer-headline>
|
|
282
|
+
<u-drawer-item>Inbox</u-drawer-item>
|
|
283
|
+
<u-drawer-item>Sent</u-drawer-item>
|
|
284
|
+
</u-drawer>
|
|
285
|
+
</u-pane>
|
|
286
|
+
|
|
287
|
+
<main>…</main>
|
|
288
|
+
</u-scaffold>
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
For a rail at all sizes, drop it directly in the body row:
|
|
292
|
+
|
|
293
|
+
```html
|
|
294
|
+
<u-scaffold>
|
|
295
|
+
<u-navigation-rail>…</u-navigation-rail>
|
|
296
|
+
<main>…</main>
|
|
297
|
+
</u-scaffold>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Scroll behaviour
|
|
301
|
+
|
|
302
|
+
The scaffold doesn't own the scroll. Non-pane body content needs its own `overflow: auto` (the scaffold applies `min-height: 0` so the rule works). Pane content scrolls inside the pane's own `.content` part.
|
|
303
|
+
|
|
304
|
+
The top app bar, FAB and FAB menu listen to `window` by default. Use the bar's `scrollContainer` attribute to point it at a specific element:
|
|
305
|
+
|
|
306
|
+
```html
|
|
307
|
+
<u-top-app-bar slot="top-bar" scrollContainer="body-scroll" headline="…"></u-top-app-bar>
|
|
308
|
+
|
|
309
|
+
<div id="body-scroll" style="overflow: auto">…</div>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## `<u-pane>` attribute reference
|
|
313
|
+
|
|
314
|
+
| Attribute | Values | Default | What it does |
|
|
315
|
+
| --- | --- | --- | --- |
|
|
316
|
+
| `variant` | `transparent` \| `filled` | `transparent` | `filled` gives a `surface-container-low` background + 12dp corner. Modal-mode overlays use `surface-container-low` (sidebar) or `surface-container-lowest` (fullscreen) automatically. |
|
|
317
|
+
| `mode` | `fixed` \| `collapsible` \| `sidebar` \| `fullscreen` | `fixed` | Base behaviour. |
|
|
318
|
+
| `mode-sm` / `mode-md` / `mode-lg` / `mode-xl` | same values | unset | Per-breakpoint override (≥ 600 / 840 / 1200 / 1600 px). Larger breakpoints win. |
|
|
319
|
+
| `query-context` | `media` \| `container` | `media` | Whether breakpoint overrides query the viewport or the scaffold's container. |
|
|
320
|
+
| `open` | boolean | `true` for `fixed`/`collapsible`, `false` for `sidebar`/`fullscreen` | Programmatic open state. Ignored in `fixed`. |
|
|
321
|
+
| `animation` | `none` \| `exit` \| `exit-start` \| `exit-end` \| `fade` | `exit` | How the pane transitions in/out. `exit` (default) slides off-screen and infers the edge from `data-align` (start → leading, end → trailing). `exit-start`/`exit-end` force a side. `fade` swaps the slide for an opacity transition. `none` disables the transition. |
|
|
322
|
+
| `animation-sm` / `animation-md` / `animation-lg` / `animation-xl` | same values | unset | Per-breakpoint override for `animation`. Larger breakpoints win. |
|
|
323
|
+
|
|
324
|
+
### `--u-pane-width` (collapsible slide distance)
|
|
325
|
+
|
|
326
|
+
In `collapsible` mode the pane slides off via a negative `margin-inline-start` (or `margin-inline-end` when `data-align=end`). The slide distance defaults to `100%` of the body row — for the math to match the pane's actual open width, set `--u-pane-width` to that width.
|
|
327
|
+
|
|
328
|
+
```html
|
|
329
|
+
<!-- Sets both the visible width and the slide distance -->
|
|
330
|
+
<u-pane mode-md="collapsible" style="width: 280px; --u-pane-width: 280px;">…</u-pane>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Programmatic control
|
|
334
|
+
|
|
335
|
+
Each pane exposes `show()`, `close()`, `toggle()`, plus the `open` boolean property. The pane fires `open` and `close` events when the consumer writes to `open`; `expand` / `collapse` events no longer exist (mode resolution is CSS-only).
|
|
336
|
+
|
|
337
|
+
```ts
|
|
338
|
+
const pane = document.getElementById('nav');
|
|
339
|
+
pane.show();
|
|
340
|
+
pane.close();
|
|
341
|
+
pane.toggle();
|
|
342
|
+
pane.open = true;
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Slots
|
|
346
|
+
|
|
347
|
+
`<u-scaffold>`:
|
|
348
|
+
|
|
349
|
+
| Slot | Goes into |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| `top-bar` | A `<u-top-app-bar>` (auto-positioned absolute). |
|
|
352
|
+
| default | Panes (`<u-pane>`) and the page content as siblings. Non-pane children flex to fill the remaining space. |
|
|
353
|
+
| `bottom-bar` | A `<u-navigation-bar>` (auto-positioned absolute). |
|
|
354
|
+
| `fab` | A `<u-fab>` or `<u-fab-menu>` — anchored above the bottom bar. |
|
|
355
|
+
|
|
356
|
+
`<u-pane>`:
|
|
357
|
+
|
|
358
|
+
| Slot | Goes into |
|
|
359
|
+
| --- | --- |
|
|
360
|
+
| `header` | Sticks to the top of the pane. |
|
|
361
|
+
| default | The pane content (scrolls inside the pane's `.content` part). |
|
|
362
|
+
|
|
363
|
+
## Parts
|
|
364
|
+
|
|
365
|
+
Scaffold: `top-bar`, `bottom-bar`, `fab`, `body-row`.
|
|
366
|
+
|
|
367
|
+
Pane: `container`, `header`, `content`, `scrim`.
|
|
368
|
+
|
|
369
|
+
## CSS custom properties
|
|
370
|
+
|
|
371
|
+
Scaffold:
|
|
372
|
+
- `--u-pane-gap` (default `16px`), `--u-pane-padding` (default `0` below md, `16px` at md+) — spacing in the body row.
|
|
373
|
+
- `--u-scaffold-fab-inline-offset`, `--u-scaffold-fab-block-offset` (defaults `16px`).
|
|
374
|
+
- `--u-scaffold-container-color` — scaffold background.
|
|
375
|
+
|
|
376
|
+
Pane (set on the pane host):
|
|
377
|
+
- `--u-pane-filled-bg-color`, `--u-pane-filled-shape-corner` — in-flow filled variant.
|
|
378
|
+
- `--u-pane-overlay-bg-color`, `--u-pane-overlay-corner-shape` — sidebar/fullscreen overlay.
|
|
379
|
+
- `--u-pane-mobile-width` (default `360px`) — sidebar drawer width.
|
|
380
|
+
- `--u-pane-scrim-color`, `--u-pane-scrim-opacity` (default `.4`).
|
|
381
|
+
- `--u-pane-z-index` (default `1030`, sidebar), `--u-pane-fullscreen-z-index` (default `1040`).
|
|
382
|
+
- `--u-pane-transition` (default `300ms` ease).
|
|
383
|
+
|
|
384
|
+
## Caveats
|
|
385
|
+
|
|
386
|
+
- The scaffold must have an explicit height (`100vh`, fixed px, or flex parent). Without it the body row collapses to 0.
|
|
387
|
+
- Non-pane body content does not get an automatic scroll container — apply `overflow: auto` yourself if you want the column to scroll independently of the page.
|
|
388
|
+
- The top app bar / FAB default to `window` scroll. To make them react to in-scaffold scroll, set `scrollContainer="..."` to the id of a scrolling element or pass an `HTMLElement` directly to the property.
|
|
389
|
+
- `<u-pane mode="sidebar">` slides from the leading edge by default. Place the pane *after* your body content in DOM order to slide from the trailing edge — the scaffold writes `data-align="end"` on it automatically.
|
|
390
|
+
- `query-context="container"` requires the scaffold ancestor (which sets `container-type`). If you use a pane outside a `<u-scaffold>`, container queries won't resolve.
|
|
391
|
+
- The standalone `u-side-navigation` is `@deprecated` — use a `<u-pane>` with a slotted `<u-drawer>` / `<u-navigation-rail>` instead.
|
|
392
|
+
- **A `<u-drawer>` slotted into a `filled` pane paints over the pane's own background.** The drawer renders its own surface, and at `lg`+ that surface becomes `surface`/body (the "standard drawer" treatment for a permanent side-nav) — identical to the scaffold background. So a filled nav pane shows its background at small/medium widths and then *loses it on desktop*, exactly where the drawer flips to body color. The pane background is there; the drawer is painting on top. Fix at the drawer, not the pane: neutralize the drawer's surface so the pane shows through — `--u-modal-drawer-bg-color: transparent; --u-standard-drawer-bg-color: transparent;` (set on the pane; they inherit to the drawer). See the drawer skill for detail.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use u-search — the Material 3 search bar (rounded input with leading/trailing icon slots), optionally driven by u-typeahead for suggestions.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Search
|
|
6
|
+
|
|
7
|
+
`<u-search>` is the Material 3 **search bar**: a rounded, single-line input with leading/trailing icon slots. It is form-associated (`value`, submits its `<form>` on Enter) and is the idiomatic input to pair with `<u-typeahead>` for autocomplete.
|
|
8
|
+
|
|
9
|
+
Use it for a search box; use `<u-text-field>` for a labeled form field.
|
|
10
|
+
|
|
11
|
+
## Basic
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<u-search placeholder="Search">
|
|
15
|
+
<span class="material-symbols-outlined" slot="leading-icon">search</span>
|
|
16
|
+
</u-search>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Slots: `leading-icon`, `trailing-icon` (e.g. a clear/voice button). Parts: `input`, `icon` / `leading` / `trailing`.
|
|
20
|
+
|
|
21
|
+
## Position
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<u-search position="static"></u-search> <!-- in-flow, inline (toolbar / pane header) -->
|
|
25
|
+
<u-search position="fixed"></u-search> <!-- floating bar (default) -->
|
|
26
|
+
<u-search position="absolute"></u-search>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`position` defaults to **`fixed`** (the floating M3 search bar). For a search input that sits inline in a header/toolbar, use `position="static"`.
|
|
30
|
+
|
|
31
|
+
## Reading the value
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const search = document.querySelector('u-search')!;
|
|
35
|
+
search.value; // current text (form-associated)
|
|
36
|
+
search.addEventListener('input', () => …); // fires as the user types
|
|
37
|
+
// Enter submits the associated <form> (form.requestSubmit()).
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Other props: `placeholder`, `autocomplete`, `maxlength`, `role`.
|
|
41
|
+
|
|
42
|
+
## With suggestions (`u-typeahead`)
|
|
43
|
+
|
|
44
|
+
`<u-search>` is the idiomatic target for `<u-typeahead>` — the suggestions popover anchors to the search input:
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<u-search id="q" position="static" placeholder="Search clients">
|
|
48
|
+
<span class="material-symbols-outlined" slot="leading-icon">search</span>
|
|
49
|
+
</u-search>
|
|
50
|
+
<u-typeahead target-id="q" positioning="fixed"></u-typeahead>
|
|
51
|
+
|
|
52
|
+
<script>
|
|
53
|
+
const ta = document.querySelector('u-typeahead');
|
|
54
|
+
ta.source = (term) => clients.filter((c) => c.name.toLowerCase().includes(term.toLowerCase()));
|
|
55
|
+
ta.formatter = (c) => c.name;
|
|
56
|
+
ta.addEventListener('selected', (e) => openClient(e.detail));
|
|
57
|
+
</script>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
See the **typeahead** skill for the full suggestions API.
|
|
61
|
+
|
|
62
|
+
## Caveats
|
|
63
|
+
|
|
64
|
+
- It's a search **bar**, not a labeled field — use `placeholder`; there is no floating label. For a labeled form input use `<u-text-field>`.
|
|
65
|
+
- Default `position` is `fixed` (floating). Set `position="static"` to keep it inline in a header/toolbar.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use u-select — a Material 3 dropdown built on the field chrome, with u-option children, supporting text and validation.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Select
|
|
6
|
+
|
|
7
|
+
`<u-select>` is a form-associated dropdown that opens a `<u-menu>` of `<u-option>` children. It shares the field chrome with `<u-text-field>` (label, supporting/error text, leading/trailing icons).
|
|
8
|
+
|
|
9
|
+
## Basic usage
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<u-select label="Country">
|
|
13
|
+
<u-option value="br">Brazil</u-option>
|
|
14
|
+
<u-option value="us">United States</u-option>
|
|
15
|
+
<u-option value="es">Spain</u-option>
|
|
16
|
+
<u-option value="jp">Japan</u-option>
|
|
17
|
+
</u-select>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Variants and helpers
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<u-select label="Country" variant="outlined" supporting-text="Pick where you live">
|
|
24
|
+
…
|
|
25
|
+
</u-select>
|
|
26
|
+
|
|
27
|
+
<u-select label="Country" error-text="Required" invalid>
|
|
28
|
+
…
|
|
29
|
+
</u-select>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Programmatic value
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const select = document.querySelector('u-select')!;
|
|
36
|
+
select.value = 'br'; // set
|
|
37
|
+
console.log(select.value); // get
|
|
38
|
+
|
|
39
|
+
select.addEventListener('change', () => console.log(select.value));
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Initial selection (in markup)
|
|
43
|
+
|
|
44
|
+
Like the native `<select>`, there is **no `value` attribute** — set the initial selection with `selected` on the option (or assign `.value` in JS after upgrade). With neither, the first enabled option is selected.
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<u-select label="Country">
|
|
48
|
+
<u-option value="br">Brazil</u-option>
|
|
49
|
+
<u-option value="us" selected>United States</u-option>
|
|
50
|
+
</u-select>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Icons in options
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<u-select label="Theme">
|
|
57
|
+
<u-option value="auto">
|
|
58
|
+
<span class="material-symbols-outlined" slot="icon">brightness_4</span>
|
|
59
|
+
System
|
|
60
|
+
</u-option>
|
|
61
|
+
<u-option value="light">
|
|
62
|
+
<span class="material-symbols-outlined" slot="icon">light_mode</span>
|
|
63
|
+
Light
|
|
64
|
+
</u-option>
|
|
65
|
+
<u-option value="dark">
|
|
66
|
+
<span class="material-symbols-outlined" slot="icon">dark_mode</span>
|
|
67
|
+
Dark
|
|
68
|
+
</u-option>
|
|
69
|
+
</u-select>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Positioning inside clipped containers
|
|
73
|
+
|
|
74
|
+
When the select sits inside a scrollable/clipped wrapper, set `menu-positioning="fixed"` so the dropdown escapes its bounds:
|
|
75
|
+
|
|
76
|
+
```html
|
|
77
|
+
<u-select label="Country" menu-positioning="fixed">…</u-select>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Disabled / read-only
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<u-select label="Country" disabled>…</u-select>
|
|
84
|
+
<u-select label="Country" readOnly>…</u-select>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Required / validation
|
|
88
|
+
|
|
89
|
+
`required` participates in constraint validation and blocks native form submit. Because a select with options always has a selection, add an **empty-valued placeholder option** so "nothing chosen" is representable:
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<u-select label="Country" required error-text="Please choose a country">
|
|
93
|
+
<u-option value="">Choose…</u-option>
|
|
94
|
+
<u-option value="br">Brazil</u-option>
|
|
95
|
+
<u-option value="us">United States</u-option>
|
|
96
|
+
</u-select>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
select.checkValidity(); // boolean (fires `invalid` if not)
|
|
101
|
+
select.reportValidity(); // also shows the bubble + sets the visual `invalid` state
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## When NOT to use `<u-select>`
|
|
105
|
+
|
|
106
|
+
- Free-text input with suggestions → use `<u-typeahead>`.
|
|
107
|
+
- Multi-select chip input → use `<u-chip-field>`.
|
|
108
|
+
- A non-form action menu (Edit/Delete/Share) → use `<u-button>` + `<u-menu>` directly.
|
|
109
|
+
|
|
110
|
+
## SPA / framework binding
|
|
111
|
+
|
|
112
|
+
The select keeps its selection when the framework **re-renders the `<u-option>` list** (e.g. an `*ngFor`/`v-for`). It remembers the last value you set (via `.value`/`.selectedIndex`, a click, or `<u-option selected>`) and re-applies it once the matching option is present — so you don't need to re-assign `.value` after the options change. Setting `.value` **before** the options exist (async load) also works: it applies when that option appears. The first-option default is *not* sticky, matching the native `<select>`.
|
|
113
|
+
|
|
114
|
+
## Caveats
|
|
115
|
+
|
|
116
|
+
- The displayed value is the matching `<u-option>`'s text content. Keep option text concise. **An icon inside an option** (`<span slot="icon">`) shows in the dropdown but its ligature text leaks into the *closed* select's displayed value (e.g. "groups Todos") — omit option icons when the value is shown as text.
|
|
117
|
+
- **Single-select only** — there is no `multiple` attribute. For multiple values use `<u-chip-field>`.
|
|
118
|
+
- `required` only triggers when the current value is empty; without an empty-valued option the select always has a non-empty value and so is always valid.
|
|
119
|
+
- For long lists, the menu virtualizes after a threshold but very large lists (1000+) feel sluggish — consider a typeahead instead.
|
|
120
|
+
- Don't put non-`u-option` children inside `<u-select>` — they're ignored.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use u-checkbox, u-radio, u-switch — and their u-*-list-item variants for selection lists.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Selection controls — checkbox, radio, switch
|
|
6
|
+
|
|
7
|
+
All three are form-associated and share API conventions: `checked`, `disabled`, `value`, `name`, plus a `change` event.
|
|
8
|
+
|
|
9
|
+
## Checkbox
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<u-checkbox></u-checkbox>
|
|
13
|
+
<u-checkbox checked></u-checkbox>
|
|
14
|
+
<u-checkbox indeterminate></u-checkbox>
|
|
15
|
+
<u-checkbox disabled></u-checkbox>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
With a label, either inline or via `<u-checkbox-list-item>`:
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<label class="flex items-center gap-2">
|
|
22
|
+
<u-checkbox></u-checkbox>
|
|
23
|
+
Subscribe to newsletter
|
|
24
|
+
</label>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Radio
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<u-radio name="color" value="red"></u-radio>
|
|
31
|
+
<u-radio name="color" value="green" checked></u-radio>
|
|
32
|
+
<u-radio name="color" value="blue"></u-radio>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`name` groups them — only one in a group can be checked. Listen on each, or use a wrapping `<form>` and read `FormData`.
|
|
36
|
+
|
|
37
|
+
## Switch
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<u-switch></u-switch>
|
|
41
|
+
<u-switch checked></u-switch>
|
|
42
|
+
<u-switch disabled></u-switch>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Same API as the checkbox.
|
|
46
|
+
|
|
47
|
+
## List-item variants
|
|
48
|
+
|
|
49
|
+
For settings screens with rows of controls, use the `u-*-list-item` components — they render a `<u-list-item>` with the control on the trailing side and a label/supporting-text on the leading side. Drop them inside a `<u-list>`:
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<u-list>
|
|
53
|
+
<u-switch-list-item checked>
|
|
54
|
+
Wi-Fi
|
|
55
|
+
<span slot="supporting-text">Connected to "Office"</span>
|
|
56
|
+
</u-switch-list-item>
|
|
57
|
+
|
|
58
|
+
<u-switch-list-item>
|
|
59
|
+
Bluetooth
|
|
60
|
+
<span slot="supporting-text">Off</span>
|
|
61
|
+
</u-switch-list-item>
|
|
62
|
+
|
|
63
|
+
<u-checkbox-list-item>
|
|
64
|
+
Show passwords
|
|
65
|
+
</u-checkbox-list-item>
|
|
66
|
+
|
|
67
|
+
<u-radio-list-item name="theme" value="light">Light</u-radio-list-item>
|
|
68
|
+
<u-radio-list-item name="theme" value="dark" checked>Dark</u-radio-list-item>
|
|
69
|
+
</u-list>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The list items handle the click on the whole row (toggling the control), the ripple, and the spacing.
|
|
73
|
+
|
|
74
|
+
## Programmatic
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
const cb = document.querySelector('u-checkbox')!;
|
|
78
|
+
cb.checked = true;
|
|
79
|
+
cb.addEventListener('change', () => console.log(cb.checked));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Caveats
|
|
83
|
+
|
|
84
|
+
- `<u-checkbox>` and `<u-switch>` emit `change` on every toggle; `<u-radio>` emits `change` only on the newly-selected radio in a group (not on deselected siblings).
|
|
85
|
+
- `indeterminate` is visual only — `checked` still reads the underlying boolean. For **dynamically-built DOM** (innerHTML / generated rows) set it via the **property** after upgrade (`cb.indeterminate = true`), not the markup attribute. Setting `checked = true` clears `indeterminate`.
|
|
86
|
+
- `change` **bubbles**, so you can delegate it on an ancestor (e.g. a `<tbody>`) for bulk-selection — `wrapper.addEventListener('change', e => e.target.closest('u-checkbox') && …)` works.
|
|
87
|
+
- For groups of switches/checkboxes in settings, prefer the `*-list-item` variants — they're keyboard-accessible across the whole row and follow the M3 list spec.
|
|
88
|
+
- The `*-list-item` variants accept **`no-inset`** — pulls the row flush with surrounding content (a negative inline margin equal to the inline padding) so it lines up with the section heading/labels. See the **list** skill.
|