zabi-components 8.0.0 → 9.0.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/CHANGELOG.md +2935 -0
- package/README.md +243 -10
- package/THEME.md +162 -332
- package/THEMING.md +1419 -259
- package/dist/atoms/ActionPanel.svelte +15 -5
- package/dist/atoms/Avatar.svelte +120 -0
- package/dist/atoms/Avatar.svelte.d.ts +46 -0
- package/dist/atoms/Badge.svelte +71 -13
- package/dist/atoms/Badge.svelte.d.ts +8 -2
- package/dist/atoms/Block.svelte +74 -0
- package/dist/atoms/Block.svelte.d.ts +29 -0
- package/dist/atoms/Button.svelte +217 -30
- package/dist/atoms/Button.svelte.d.ts +33 -4
- package/dist/atoms/Card.svelte +182 -26
- package/dist/atoms/Card.svelte.d.ts +55 -3
- package/dist/atoms/CardHeader.svelte +16 -4
- package/dist/atoms/Checkbox.svelte +81 -21
- package/dist/atoms/Checkbox.svelte.d.ts +31 -2
- package/dist/atoms/Chip.svelte +351 -0
- package/dist/atoms/Chip.svelte.d.ts +57 -0
- package/dist/atoms/CodeBlock.svelte +20 -2
- package/dist/atoms/CodeBlock.svelte.d.ts +4 -0
- package/dist/atoms/CodeField.svelte +385 -0
- package/dist/atoms/CodeField.svelte.d.ts +61 -0
- package/dist/atoms/ColorPicker.svelte +260 -49
- package/dist/atoms/ColorPicker.svelte.d.ts +3 -0
- package/dist/atoms/Container.svelte +16 -8
- package/dist/atoms/DateField.svelte +145 -0
- package/dist/atoms/DateField.svelte.d.ts +81 -0
- package/dist/atoms/FieldMessages.svelte +69 -0
- package/dist/atoms/FieldMessages.svelte.d.ts +23 -0
- package/dist/atoms/FloatingActionButton.svelte +176 -0
- package/dist/atoms/FloatingActionButton.svelte.d.ts +51 -0
- package/dist/atoms/Heading.svelte +63 -5
- package/dist/atoms/Heading.svelte.d.ts +14 -0
- package/dist/atoms/IconButton.svelte +294 -26
- package/dist/atoms/IconButton.svelte.d.ts +62 -4
- package/dist/atoms/Input.svelte +259 -53
- package/dist/atoms/Input.svelte.d.ts +33 -2
- package/dist/atoms/List.svelte +5 -1
- package/dist/atoms/ListItem.svelte +70 -13
- package/dist/atoms/ListItem.svelte.d.ts +11 -0
- package/dist/atoms/PickerField.svelte +239 -0
- package/dist/atoms/PickerField.svelte.d.ts +67 -0
- package/dist/atoms/Progress.svelte +99 -19
- package/dist/atoms/Progress.svelte.d.ts +15 -1
- package/dist/atoms/Radio.svelte +51 -3
- package/dist/atoms/Radio.svelte.d.ts +30 -2
- package/dist/atoms/Rating.svelte +620 -0
- package/dist/atoms/Rating.svelte.d.ts +77 -0
- package/dist/atoms/Select.svelte +438 -98
- package/dist/atoms/Select.svelte.d.ts +61 -3
- package/dist/atoms/SelectionControl.svelte +193 -23
- package/dist/atoms/SelectionControl.svelte.d.ts +29 -3
- package/dist/atoms/Skeleton.svelte +114 -18
- package/dist/atoms/Skeleton.svelte.d.ts +30 -3
- package/dist/atoms/SkeletonGroup.svelte +43 -0
- package/dist/atoms/SkeletonGroup.svelte.d.ts +20 -0
- package/dist/atoms/Slider.svelte +344 -0
- package/dist/atoms/Slider.svelte.d.ts +40 -0
- package/dist/atoms/Sparkline.svelte +109 -0
- package/dist/atoms/Sparkline.svelte.d.ts +27 -0
- package/dist/atoms/SpeechBubble.svelte +187 -0
- package/dist/atoms/SpeechBubble.svelte.d.ts +33 -0
- package/dist/atoms/Spinner.svelte +57 -0
- package/dist/atoms/Spinner.svelte.d.ts +19 -0
- package/dist/atoms/Stat.svelte +72 -0
- package/dist/atoms/Stat.svelte.d.ts +19 -0
- package/dist/atoms/Table.svelte +151 -6
- package/dist/atoms/Table.svelte.d.ts +15 -3
- package/dist/atoms/TemporalField.svelte +472 -0
- package/dist/atoms/TemporalField.svelte.d.ts +48 -0
- package/dist/atoms/Text.svelte +23 -11
- package/dist/atoms/Text.svelte.d.ts +6 -3
- package/dist/atoms/Textarea.svelte +150 -44
- package/dist/atoms/Textarea.svelte.d.ts +35 -2
- package/dist/atoms/ThemeToggle.svelte +223 -44
- package/dist/atoms/ThemeToggle.svelte.d.ts +26 -3
- package/dist/atoms/TimeColumn.svelte +150 -0
- package/dist/atoms/TimeColumn.svelte.d.ts +25 -0
- package/dist/atoms/TimeField.svelte +151 -0
- package/dist/atoms/TimeField.svelte.d.ts +85 -0
- package/dist/atoms/Toast.svelte +22 -8
- package/dist/atoms/Toast.svelte.d.ts +2 -0
- package/dist/atoms/Toggle.svelte +98 -14
- package/dist/atoms/Toggle.svelte.d.ts +26 -2
- package/dist/atoms/Tooltip.svelte +528 -24
- package/dist/atoms/Tooltip.svelte.d.ts +18 -0
- package/dist/atoms/ZabiStringsProvider.svelte +45 -0
- package/dist/atoms/ZabiStringsProvider.svelte.d.ts +27 -0
- package/dist/atoms/index.d.ts +38 -0
- package/dist/atoms/index.js +29 -0
- package/dist/atoms/selection-control.styles.d.ts +47 -5
- package/dist/atoms/selection-control.styles.js +52 -10
- package/dist/components/atoms/index.d.ts +38 -0
- package/dist/components/atoms/index.d.ts.map +1 -1
- package/dist/components/atoms/selection-control.styles.d.ts +47 -5
- package/dist/components/atoms/selection-control.styles.d.ts.map +1 -1
- package/dist/components/index.d.ts +104 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/map.d.ts +11 -0
- package/dist/components/map.d.ts.map +1 -0
- package/dist/components/molecules/index.d.ts +51 -0
- package/dist/components/molecules/index.d.ts.map +1 -1
- package/dist/components/molecules/toast-store.d.ts +83 -7
- package/dist/components/molecules/toast-store.d.ts.map +1 -1
- package/dist/components/organisms/index.d.ts +10 -0
- package/dist/components/organisms/index.d.ts.map +1 -1
- package/dist/components/types/variants.d.ts +24 -1
- package/dist/components/types/variants.d.ts.map +1 -1
- package/dist/components/util/app-shell.d.ts +79 -0
- package/dist/components/util/app-shell.d.ts.map +1 -0
- package/dist/components/util/avatar.d.ts +39 -0
- package/dist/components/util/avatar.d.ts.map +1 -0
- package/dist/components/util/bottom-sheet.d.ts +30 -0
- package/dist/components/util/bottom-sheet.d.ts.map +1 -0
- package/dist/components/util/bottom-tab-bar.d.ts +41 -0
- package/dist/components/util/bottom-tab-bar.d.ts.map +1 -0
- package/dist/components/util/calendar.d.ts +56 -0
- package/dist/components/util/calendar.d.ts.map +1 -0
- package/dist/components/util/chart.d.ts +140 -0
- package/dist/components/util/chart.d.ts.map +1 -0
- package/dist/components/util/chip.d.ts +66 -0
- package/dist/components/util/chip.d.ts.map +1 -0
- package/dist/components/util/cn.d.ts.map +1 -1
- package/dist/components/util/code-field.d.ts +63 -0
- package/dist/components/util/code-field.d.ts.map +1 -0
- package/dist/components/util/collapsible.d.ts +64 -0
- package/dist/components/util/collapsible.d.ts.map +1 -0
- package/dist/components/util/confirm-dialog.d.ts +12 -0
- package/dist/components/util/confirm-dialog.d.ts.map +1 -0
- package/dist/components/util/date.d.ts +96 -0
- package/dist/components/util/date.d.ts.map +1 -0
- package/dist/components/util/display-voice.d.ts +10 -0
- package/dist/components/util/display-voice.d.ts.map +1 -0
- package/dist/components/util/drawer.d.ts +13 -0
- package/dist/components/util/drawer.d.ts.map +1 -0
- package/dist/components/util/dropdown.d.ts +47 -0
- package/dist/components/util/dropdown.d.ts.map +1 -0
- package/dist/components/util/field-control.d.ts +30 -0
- package/dist/components/util/field-control.d.ts.map +1 -0
- package/dist/components/util/field.d.ts +45 -0
- package/dist/components/util/field.d.ts.map +1 -0
- package/dist/components/util/fit-in-viewport.d.ts +201 -0
- package/dist/components/util/fit-in-viewport.d.ts.map +1 -0
- package/dist/components/util/focus-utils.d.ts +77 -2
- package/dist/components/util/focus-utils.d.ts.map +1 -1
- package/dist/components/util/hydration.d.ts +45 -0
- package/dist/components/util/hydration.d.ts.map +1 -0
- package/dist/components/util/keyboard-inset.d.ts +18 -0
- package/dist/components/util/keyboard-inset.d.ts.map +1 -0
- package/dist/components/util/map-view.d.ts +144 -0
- package/dist/components/util/map-view.d.ts.map +1 -0
- package/dist/components/util/media-grid.d.ts +51 -0
- package/dist/components/util/media-grid.d.ts.map +1 -0
- package/dist/components/util/media.d.ts +6 -0
- package/dist/components/util/media.d.ts.map +1 -0
- package/dist/components/util/overlay-chrome.d.ts +53 -0
- package/dist/components/util/overlay-chrome.d.ts.map +1 -0
- package/dist/components/util/overlay.d.ts +72 -0
- package/dist/components/util/overlay.d.ts.map +1 -0
- package/dist/components/util/photo.d.ts +234 -0
- package/dist/components/util/photo.d.ts.map +1 -0
- package/dist/components/util/portal.d.ts +23 -0
- package/dist/components/util/portal.d.ts.map +1 -0
- package/dist/components/util/progress.d.ts +19 -0
- package/dist/components/util/progress.d.ts.map +1 -0
- package/dist/components/util/pull-to-refresh.d.ts +27 -0
- package/dist/components/util/pull-to-refresh.d.ts.map +1 -0
- package/dist/components/util/radio-keys.d.ts +25 -0
- package/dist/components/util/radio-keys.d.ts.map +1 -0
- package/dist/components/util/rating.d.ts +23 -0
- package/dist/components/util/rating.d.ts.map +1 -0
- package/dist/components/util/ready-made-strings.d.ts +77 -0
- package/dist/components/util/ready-made-strings.d.ts.map +1 -0
- package/dist/components/util/scroll-edge.d.ts +33 -0
- package/dist/components/util/scroll-edge.d.ts.map +1 -0
- package/dist/components/util/scroll-padding.d.ts +20 -0
- package/dist/components/util/scroll-padding.d.ts.map +1 -0
- package/dist/components/util/segmented-control.d.ts +16 -0
- package/dist/components/util/segmented-control.d.ts.map +1 -0
- package/dist/components/util/select.d.ts +41 -0
- package/dist/components/util/select.d.ts.map +1 -0
- package/dist/components/util/sheet-drag.d.ts +84 -0
- package/dist/components/util/sheet-drag.d.ts.map +1 -0
- package/dist/components/util/sidebar.d.ts +63 -0
- package/dist/components/util/sidebar.d.ts.map +1 -0
- package/dist/components/util/skeleton.d.ts +15 -0
- package/dist/components/util/skeleton.d.ts.map +1 -0
- package/dist/components/util/sliding-indicator.d.ts +25 -0
- package/dist/components/util/sliding-indicator.d.ts.map +1 -0
- package/dist/components/util/sortable-list.d.ts +65 -0
- package/dist/components/util/sortable-list.d.ts.map +1 -0
- package/dist/components/util/stepper.d.ts +40 -0
- package/dist/components/util/stepper.d.ts.map +1 -0
- package/dist/components/util/swipeable-list-item.d.ts +36 -0
- package/dist/components/util/swipeable-list-item.d.ts.map +1 -0
- package/dist/components/util/temporal-field.d.ts +89 -0
- package/dist/components/util/temporal-field.d.ts.map +1 -0
- package/dist/components/util/theme-mode.d.ts +80 -0
- package/dist/components/util/theme-mode.d.ts.map +1 -0
- package/dist/components/util/toaster.d.ts +133 -0
- package/dist/components/util/toaster.d.ts.map +1 -0
- package/dist/components/util/tone-surface.d.ts +34 -0
- package/dist/components/util/tone-surface.d.ts.map +1 -0
- package/dist/components/util/tooltip.d.ts +10 -0
- package/dist/components/util/tooltip.d.ts.map +1 -0
- package/dist/components/util/top-navbar.d.ts +35 -0
- package/dist/components/util/top-navbar.d.ts.map +1 -0
- package/dist/components/util/touch-target.d.ts +31 -0
- package/dist/components/util/touch-target.d.ts.map +1 -0
- package/dist/components/util/zabi-strings.d.ts +142 -0
- package/dist/components/util/zabi-strings.d.ts.map +1 -0
- package/dist/create-theme/cli.js +173 -0
- package/dist/create-theme/index.d.ts +190 -0
- package/dist/create-theme/index.js +1034 -0
- package/dist/create-theme/lib/ramp-math.js +128 -0
- package/dist/create-theme/lib/resolve.js +238 -0
- package/dist/create-theme/theme-data.js +2644 -0
- package/dist/index.d.ts +104 -2
- package/dist/index.js +75 -2
- package/dist/map.d.ts +10 -0
- package/dist/map.js +9 -0
- package/dist/molecules/Alert.svelte +63 -16
- package/dist/molecules/Alert.svelte.d.ts +14 -1
- package/dist/molecules/AppBar.svelte +674 -0
- package/dist/molecules/AppBar.svelte.d.ts +131 -0
- package/dist/molecules/AvatarGroup.svelte +116 -0
- package/dist/molecules/AvatarGroup.svelte.d.ts +40 -0
- package/dist/molecules/BarChart.svelte +381 -0
- package/dist/molecules/BarChart.svelte.d.ts +45 -0
- package/dist/molecules/BottomSheet.svelte +608 -0
- package/dist/molecules/BottomSheet.svelte.d.ts +109 -0
- package/dist/molecules/BottomTabBar.svelte +403 -0
- package/dist/molecules/BottomTabBar.svelte.d.ts +98 -0
- package/dist/molecules/Calendar.svelte +597 -0
- package/dist/molecules/Calendar.svelte.d.ts +72 -0
- package/dist/molecules/ChipGroup.svelte +325 -0
- package/dist/molecules/ChipGroup.svelte.d.ts +41 -0
- package/dist/molecules/Collapsible.svelte +347 -0
- package/dist/molecules/Collapsible.svelte.d.ts +61 -0
- package/dist/molecules/CollapsibleGroup.svelte +136 -0
- package/dist/molecules/CollapsibleGroup.svelte.d.ts +14 -0
- package/dist/molecules/ComponentDemo.svelte +16 -4
- package/dist/molecules/ComponentDemo.svelte.d.ts +3 -0
- package/dist/molecules/ConfirmDialog.svelte +257 -0
- package/dist/molecules/ConfirmDialog.svelte.d.ts +58 -0
- package/dist/molecules/ContactForm.svelte +34 -17
- package/dist/molecules/ContactForm.svelte.d.ts +8 -0
- package/dist/molecules/Drawer.svelte +415 -0
- package/dist/molecules/Drawer.svelte.d.ts +55 -0
- package/dist/molecules/Dropdown.svelte +517 -48
- package/dist/molecules/Dropdown.svelte.d.ts +47 -6
- package/dist/molecules/DropdownItem.svelte +122 -0
- package/dist/molecules/DropdownItem.svelte.d.ts +28 -0
- package/dist/molecules/EmptyState.svelte +55 -10
- package/dist/molecules/EmptyState.svelte.d.ts +8 -0
- package/dist/molecules/FormField.svelte +9 -1
- package/dist/molecules/FormField.svelte.d.ts +2 -0
- package/dist/molecules/Header.svelte +1 -1
- package/dist/molecules/ImageUpload.svelte +492 -69
- package/dist/molecules/ImageUpload.svelte.d.ts +82 -2
- package/dist/molecules/LineChart.svelte +459 -0
- package/dist/molecules/LineChart.svelte.d.ts +53 -0
- package/dist/molecules/MapView.svelte +565 -0
- package/dist/molecules/MapView.svelte.d.ts +88 -0
- package/dist/molecules/MediaGrid.svelte +527 -0
- package/dist/molecules/MediaGrid.svelte.d.ts +77 -0
- package/dist/molecules/Modal.svelte +293 -72
- package/dist/molecules/Modal.svelte.d.ts +51 -2
- package/dist/molecules/NavigationMenuContent.svelte +58 -1
- package/dist/molecules/NavigationMenuItem.svelte +0 -1
- package/dist/molecules/NavigationMenuLink.svelte +1 -1
- package/dist/molecules/NavigationMenuList.svelte +10 -3
- package/dist/molecules/NavigationMenuTrigger.svelte +2 -2
- package/dist/molecules/Page.svelte +32 -2
- package/dist/molecules/Page.svelte.d.ts +11 -0
- package/dist/molecules/PhotoGrid.svelte +523 -0
- package/dist/molecules/PhotoGrid.svelte.d.ts +73 -0
- package/dist/molecules/PhotoViewer.svelte +1213 -0
- package/dist/molecules/PhotoViewer.svelte.d.ts +74 -0
- package/dist/molecules/PieChart.svelte +421 -0
- package/dist/molecules/PieChart.svelte.d.ts +51 -0
- package/dist/molecules/PropsTable.svelte +22 -10
- package/dist/molecules/PropsTable.svelte.d.ts +3 -0
- package/dist/molecules/PullToRefresh.svelte +263 -0
- package/dist/molecules/PullToRefresh.svelte.d.ts +52 -0
- package/dist/molecules/RadioGroup.svelte +72 -18
- package/dist/molecules/RadioGroup.svelte.d.ts +19 -3
- package/dist/molecules/Section.svelte +1 -1
- package/dist/molecules/SegmentedControl.svelte +456 -0
- package/dist/molecules/SegmentedControl.svelte.d.ts +40 -0
- package/dist/molecules/SidebarBrandHeader.svelte +11 -1
- package/dist/molecules/SidebarBrandHeader.svelte.d.ts +3 -0
- package/dist/molecules/SidebarFooter.svelte +30 -7
- package/dist/molecules/SidebarFooter.svelte.d.ts +3 -0
- package/dist/molecules/SidebarNavSection.svelte +1 -1
- package/dist/molecules/SlideUp.svelte +220 -61
- package/dist/molecules/SlideUp.svelte.d.ts +26 -0
- package/dist/molecules/SortableList.svelte +633 -0
- package/dist/molecules/SortableList.svelte.d.ts +69 -0
- package/dist/molecules/Stepper.svelte +562 -0
- package/dist/molecules/Stepper.svelte.d.ts +39 -0
- package/dist/molecules/StickyActionBar.svelte +250 -0
- package/dist/molecules/StickyActionBar.svelte.d.ts +78 -0
- package/dist/molecules/SwipeableListItem.svelte +334 -0
- package/dist/molecules/SwipeableListItem.svelte.d.ts +54 -0
- package/dist/molecules/Tabs.svelte +310 -9
- package/dist/molecules/Tabs.svelte.d.ts +7 -0
- package/dist/molecules/Toaster.svelte +514 -5
- package/dist/molecules/Toaster.svelte.d.ts +153 -2
- package/dist/molecules/ToasterToast.svelte +495 -77
- package/dist/molecules/ToasterToast.svelte.d.ts +15 -0
- package/dist/molecules/UnsavedChangesBar.svelte +223 -0
- package/dist/molecules/UnsavedChangesBar.svelte.d.ts +43 -0
- package/dist/molecules/index.d.ts +51 -0
- package/dist/molecules/index.js +31 -0
- package/dist/molecules/toast-store.d.ts +83 -7
- package/dist/molecules/toast-store.js +25 -1
- package/dist/organisms/AppNavigation.svelte +440 -0
- package/dist/organisms/AppNavigation.svelte.d.ts +72 -0
- package/dist/organisms/AppShell.svelte +696 -0
- package/dist/organisms/AppShell.svelte.d.ts +157 -0
- package/dist/organisms/AppShellHeaderPart.svelte +163 -0
- package/dist/organisms/AppShellHeaderPart.svelte.d.ts +57 -0
- package/dist/organisms/SidebarAccountPanel.svelte +107 -12
- package/dist/organisms/SidebarAccountPanel.svelte.d.ts +19 -0
- package/dist/organisms/SidebarNavigation.svelte +111 -43
- package/dist/organisms/SidebarNavigation.svelte.d.ts +29 -1
- package/dist/organisms/SidebarPanel.svelte +34 -17
- package/dist/organisms/SidebarPanel.svelte.d.ts +1 -0
- package/dist/organisms/SidebarShell.svelte +164 -14
- package/dist/organisms/SidebarShell.svelte.d.ts +56 -2
- package/dist/organisms/TopNavbar.svelte +353 -39
- package/dist/organisms/TopNavbar.svelte.d.ts +47 -0
- package/dist/organisms/TopNavbarSheetContent.svelte +145 -0
- package/dist/organisms/TopNavbarSheetContent.svelte.d.ts +24 -0
- package/dist/organisms/index.d.ts +10 -0
- package/dist/organisms/index.js +7 -0
- package/dist/types/components.d.ts +21 -1
- package/dist/types/components.d.ts.map +1 -1
- package/dist/types/index.d.ts +1093 -26
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/variants.ts +28 -1
- package/dist/util/app-shell.d.ts +78 -0
- package/dist/util/app-shell.js +97 -0
- package/dist/util/avatar.d.ts +38 -0
- package/dist/util/avatar.js +52 -0
- package/dist/util/bottom-sheet.d.ts +29 -0
- package/dist/util/bottom-sheet.js +43 -0
- package/dist/util/bottom-tab-bar.d.ts +40 -0
- package/dist/util/bottom-tab-bar.js +54 -0
- package/dist/util/calendar.d.ts +55 -0
- package/dist/util/calendar.js +74 -0
- package/dist/util/chart.d.ts +139 -0
- package/dist/util/chart.js +305 -0
- package/dist/util/chip.d.ts +65 -0
- package/dist/util/chip.js +58 -0
- package/dist/util/cn.js +28 -2
- package/dist/util/code-field.d.ts +62 -0
- package/dist/util/code-field.js +112 -0
- package/dist/util/collapsible.d.ts +63 -0
- package/dist/util/collapsible.js +23 -0
- package/dist/util/confirm-dialog.d.ts +11 -0
- package/dist/util/confirm-dialog.js +2 -0
- package/dist/util/date.d.ts +95 -0
- package/dist/util/date.js +237 -0
- package/dist/util/display-voice.d.ts +9 -0
- package/dist/util/display-voice.js +9 -0
- package/dist/util/drawer.d.ts +12 -0
- package/dist/util/drawer.js +7 -0
- package/dist/util/dropdown.d.ts +46 -0
- package/dist/util/dropdown.js +21 -0
- package/dist/util/field-control.d.ts +29 -0
- package/dist/util/field-control.js +32 -0
- package/dist/util/field.d.ts +44 -0
- package/dist/util/field.js +38 -0
- package/dist/util/fit-in-viewport.d.ts +200 -0
- package/dist/util/fit-in-viewport.js +399 -0
- package/dist/util/focus-utils.d.ts +77 -2
- package/dist/util/focus-utils.js +186 -9
- package/dist/util/hydration.d.ts +44 -0
- package/dist/util/hydration.js +58 -0
- package/dist/util/keyboard-inset.d.ts +17 -0
- package/dist/util/keyboard-inset.js +53 -0
- package/dist/util/map-view.d.ts +143 -0
- package/dist/util/map-view.js +121 -0
- package/dist/util/media-grid.d.ts +50 -0
- package/dist/util/media-grid.js +81 -0
- package/dist/util/media.d.ts +5 -0
- package/dist/util/media.js +10 -0
- package/dist/util/overlay-chrome.d.ts +52 -0
- package/dist/util/overlay-chrome.js +56 -0
- package/dist/util/overlay.d.ts +71 -0
- package/dist/util/overlay.js +240 -0
- package/dist/util/photo.d.ts +233 -0
- package/dist/util/photo.js +209 -0
- package/dist/util/portal.d.ts +22 -0
- package/dist/util/portal.js +50 -0
- package/dist/util/progress.d.ts +18 -0
- package/dist/util/progress.js +17 -0
- package/dist/util/pull-to-refresh.d.ts +26 -0
- package/dist/util/pull-to-refresh.js +30 -0
- package/dist/util/radio-keys.d.ts +24 -0
- package/dist/util/radio-keys.js +49 -0
- package/dist/util/rating.d.ts +22 -0
- package/dist/util/rating.js +26 -0
- package/dist/util/ready-made-strings.d.ts +76 -0
- package/dist/util/ready-made-strings.js +67 -0
- package/dist/util/scroll-edge.d.ts +32 -0
- package/dist/util/scroll-edge.js +87 -0
- package/dist/util/scroll-padding.d.ts +19 -0
- package/dist/util/scroll-padding.js +44 -0
- package/dist/util/segmented-control.d.ts +15 -0
- package/dist/util/segmented-control.js +1 -0
- package/dist/util/select.d.ts +40 -0
- package/dist/util/select.js +63 -0
- package/dist/util/sheet-drag.d.ts +83 -0
- package/dist/util/sheet-drag.js +311 -0
- package/dist/util/sidebar.d.ts +62 -0
- package/dist/util/sidebar.js +38 -0
- package/dist/util/skeleton.d.ts +14 -0
- package/dist/util/skeleton.js +22 -0
- package/dist/util/sliding-indicator.d.ts +24 -0
- package/dist/util/sliding-indicator.js +44 -0
- package/dist/util/sortable-list.d.ts +64 -0
- package/dist/util/sortable-list.js +53 -0
- package/dist/util/stepper.d.ts +39 -0
- package/dist/util/stepper.js +38 -0
- package/dist/util/swipeable-list-item.d.ts +35 -0
- package/dist/util/swipeable-list-item.js +32 -0
- package/dist/util/temporal-field.d.ts +88 -0
- package/dist/util/temporal-field.js +136 -0
- package/dist/util/theme-mode.d.ts +79 -0
- package/dist/util/theme-mode.js +121 -0
- package/dist/util/toaster.d.ts +132 -0
- package/dist/util/toaster.js +130 -0
- package/dist/util/tone-surface.d.ts +33 -0
- package/dist/util/tone-surface.js +35 -0
- package/dist/util/tooltip.d.ts +9 -0
- package/dist/util/tooltip.js +18 -0
- package/dist/util/top-navbar.d.ts +34 -0
- package/dist/util/top-navbar.js +28 -0
- package/dist/util/touch-target.d.ts +30 -0
- package/dist/util/touch-target.js +30 -0
- package/dist/util/zabi-strings.d.ts +141 -0
- package/dist/util/zabi-strings.js +105 -0
- package/dist/zabi-components-colors.css +11 -2
- package/dist/zabi-components-theme-dark-only.css +870 -258
- package/dist/zabi-components-theme-dark.css +870 -258
- package/dist/zabi-components-theme-only.css +2419 -368
- package/dist/zabi-components-theme.css +2419 -368
- package/dist/zabi-components.css +6032 -711
- package/docs/lucide-icons.md +40 -17
- package/docs/theme-imports.md +81 -11
- package/package.json +45 -8
|
@@ -1,15 +1,77 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type
|
|
3
|
-
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
2
|
+
import { tick, untrack, type Snippet } from "svelte";
|
|
3
|
+
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
|
|
4
4
|
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
5
5
|
import { cn } from "../util/cn.js";
|
|
6
|
+
import { isDevBuild } from "../util/app-shell.js";
|
|
7
|
+
import { badgeText, defaultBadgeLabel } from "../util/bottom-tab-bar.js";
|
|
8
|
+
import Badge from "./Badge.svelte";
|
|
6
9
|
|
|
10
|
+
/** The shared scale plus `xs`, which only the icon button has. */
|
|
11
|
+
type IconButtonSize = SizeVariant | "xs";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One type for the button and the link, not a union of the two elements'
|
|
15
|
+
* attributes: that union is too large for TypeScript to carry through a
|
|
16
|
+
* wrapper such as a Storybook `Meta`. Event handlers are typed for the
|
|
17
|
+
* button; on a link they are called with the same event.
|
|
18
|
+
*/
|
|
7
19
|
type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
20
|
+
/**
|
|
21
|
+
* Where the link goes. Makes this an `<a>` that looks the same;
|
|
22
|
+
* without it, it is a `<button>`. A link cannot be disabled: while
|
|
23
|
+
* `disabled` or `loading` it has no `href`, is `aria-disabled` and
|
|
24
|
+
* does nothing when pressed. A link is not
|
|
25
|
+
* a toggle: `pressed` is ignored.
|
|
26
|
+
*/
|
|
27
|
+
href?: string;
|
|
28
|
+
/** With `href`: where the link opens. */
|
|
29
|
+
target?: HTMLAnchorAttributes["target"];
|
|
30
|
+
/** With `href`: the link's relationship, such as `noopener`. */
|
|
31
|
+
rel?: HTMLAnchorAttributes["rel"];
|
|
32
|
+
/** With `href`: download the address instead of opening it. */
|
|
33
|
+
download?: HTMLAnchorAttributes["download"];
|
|
34
|
+
hreflang?: HTMLAnchorAttributes["hreflang"];
|
|
35
|
+
referrerpolicy?: HTMLAnchorAttributes["referrerpolicy"];
|
|
36
|
+
ping?: HTMLAnchorAttributes["ping"];
|
|
8
37
|
variant?: ButtonVariant;
|
|
9
|
-
|
|
38
|
+
/**
|
|
39
|
+
* `xs` is a 24px box for dense, pointer-first layouts (card headers,
|
|
40
|
+
* table rows). That is the WCAG 2.2 minimum target size and no more:
|
|
41
|
+
* where the primary input is touch, use `sm` or larger.
|
|
42
|
+
*/
|
|
43
|
+
size?: IconButtonSize;
|
|
44
|
+
/**
|
|
45
|
+
* Colour intent for the `ghost` and `outline` variants: `danger` is
|
|
46
|
+
* the quiet destructive button (inline delete). Other variants ignore it.
|
|
47
|
+
*/
|
|
48
|
+
tone?: "default" | "danger";
|
|
49
|
+
/**
|
|
50
|
+
* Makes this a toggle button. When defined (true or false) it renders
|
|
51
|
+
* `aria-pressed` and a click flips it; bind it, or pass it one-way and
|
|
52
|
+
* update your own state in `onclick`. Call `event.preventDefault()` in
|
|
53
|
+
* `onclick` to keep the current state: do that whenever the parent
|
|
54
|
+
* updates later (after a request, say) or may refuse the change, or the
|
|
55
|
+
* button shows a state the parent does not have. Leave undefined for a
|
|
56
|
+
* plain button.
|
|
57
|
+
*/
|
|
58
|
+
pressed?: boolean;
|
|
10
59
|
loading?: boolean;
|
|
11
60
|
/** Required for icon-only usage (no visible text). */
|
|
12
61
|
label?: string;
|
|
62
|
+
/**
|
|
63
|
+
* A count drawn on the button, in the attention colour, inside the
|
|
64
|
+
* button's own box (so a bar or an `overflow` ancestor cannot cut it).
|
|
65
|
+
* Nothing is drawn for 0, a negative number or when it is left out;
|
|
66
|
+
* while `loading` it is hidden. At `xs` and `sm` there is no room for
|
|
67
|
+
* a number: a dot is drawn instead. Needs `label`: the accessible name
|
|
68
|
+
* becomes the label, a comma and `countLabel(count)`.
|
|
69
|
+
*/
|
|
70
|
+
count?: number;
|
|
71
|
+
/** What the count adds to the accessible name, after the label. Default: "3 new". */
|
|
72
|
+
countLabel?: (count: number) => string;
|
|
73
|
+
/** Above this the badge reads `99+`. The accessible name keeps the real count. */
|
|
74
|
+
countMax?: number;
|
|
13
75
|
class?: string;
|
|
14
76
|
children?: Snippet;
|
|
15
77
|
};
|
|
@@ -17,72 +79,278 @@
|
|
|
17
79
|
let {
|
|
18
80
|
variant = "primary",
|
|
19
81
|
size = "md",
|
|
82
|
+
tone = "default",
|
|
83
|
+
pressed = $bindable(),
|
|
20
84
|
disabled = false,
|
|
21
85
|
loading = false,
|
|
22
|
-
type
|
|
86
|
+
type,
|
|
87
|
+
href,
|
|
23
88
|
label = "",
|
|
89
|
+
count,
|
|
90
|
+
countLabel = defaultBadgeLabel,
|
|
91
|
+
countMax = 99,
|
|
24
92
|
class: className = "",
|
|
25
93
|
onclick,
|
|
26
94
|
children,
|
|
27
95
|
...restProps
|
|
28
96
|
}: Props = $props();
|
|
29
97
|
|
|
30
|
-
const isDisabled = $derived(disabled || loading);
|
|
98
|
+
const isDisabled = $derived(!!disabled || loading);
|
|
99
|
+
|
|
100
|
+
/** A count is drawn only for a positive number, and not while loading. */
|
|
101
|
+
const hasCount = $derived(typeof count === "number" && count > 0);
|
|
102
|
+
const showCount = $derived(hasCount && !loading);
|
|
103
|
+
/** `xs` and `sm` have no room for a number beside the icon: a dot. */
|
|
104
|
+
const countAsDot = $derived(size === "xs" || size === "sm");
|
|
105
|
+
const accessibleName = $derived(
|
|
106
|
+
showCount && label ? `${label}, ${countLabel(count as number)}` : label || undefined,
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
$effect(() => {
|
|
110
|
+
if (!isDevBuild() || !hasCount || label) return;
|
|
111
|
+
console.warn(
|
|
112
|
+
"[zabi-components] IconButton: `count` needs a `label`; without it the count has no accessible name.",
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* Loading without `disabled`: unavailable, and still where focus is.
|
|
117
|
+
*
|
|
118
|
+
* `disabled` on a button, or no `href` on a link, makes the element
|
|
119
|
+
* unfocusable, and the browser then drops focus on `<body>`: whoever
|
|
120
|
+
* pressed Save with the keyboard was at the top of the page when the
|
|
121
|
+
* save came back. So a loading control says it the ARIA way
|
|
122
|
+
* (`aria-disabled`, `aria-busy`), stays a Tab stop, and swallows the
|
|
123
|
+
* press. `disabled` is the platform's: out of the Tab order.
|
|
124
|
+
*/
|
|
125
|
+
const isBusy = $derived(loading && !disabled);
|
|
126
|
+
const isLink = $derived(href !== undefined && href !== null);
|
|
127
|
+
const isToggle = $derived(pressed !== undefined && !isLink);
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* A loading link has no `href`, so it is a Tab stop only by `tabindex`.
|
|
131
|
+
* The browser takes focus from an element the moment it stops being
|
|
132
|
+
* focusable, so the two attributes must never both be missing: the
|
|
133
|
+
* `tabindex` goes on before the `href` comes off (their order in the
|
|
134
|
+
* markup), and when loading ends it stays until the `href` is back, one
|
|
135
|
+
* update longer.
|
|
136
|
+
*/
|
|
137
|
+
let keepsTabStop = $state(false);
|
|
138
|
+
$effect.pre(() => {
|
|
139
|
+
if (isBusy) {
|
|
140
|
+
keepsTabStop = true;
|
|
141
|
+
} else if (untrack(() => keepsTabStop)) {
|
|
142
|
+
void tick().then(() => (keepsTabStop = false));
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
/** A disabled link has no `href`, but a pointer can still press it. */
|
|
147
|
+
function handleLinkClick(event: MouseEvent) {
|
|
148
|
+
if (isDisabled) {
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
event.stopPropagation();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
(onclick as ((event: MouseEvent) => void) | null | undefined)?.(event);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function handleClick(
|
|
157
|
+
event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement },
|
|
158
|
+
) {
|
|
159
|
+
// A loading button is not `disabled`, so the press reaches it: it
|
|
160
|
+
// ends here, toggles nothing and submits nothing.
|
|
161
|
+
if (isBusy) {
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
event.stopPropagation();
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Read before the handler runs: a parent that flips its own state in
|
|
167
|
+
// `onclick` has already moved `pressed` by the time it returns.
|
|
168
|
+
const next = !pressed;
|
|
169
|
+
onclick?.(event);
|
|
170
|
+
if (isToggle && !event.defaultPrevented) pressed = next;
|
|
171
|
+
}
|
|
31
172
|
|
|
32
173
|
/**
|
|
33
174
|
* Square, on the same height scale as Button / Input / Select, so an icon
|
|
34
175
|
* button sits flush in a toolbar beside a text button of the same size.
|
|
35
176
|
* Previously these were 8–16px shorter than their own Button.
|
|
177
|
+
*
|
|
178
|
+
* On a coarse pointer `sm` and `md` are 44 by 44px, as Button, Input and
|
|
179
|
+
* Select are 44px tall there, so the toolbar still lines up and the box
|
|
180
|
+
* itself is the touch target. `lg` is 48px already.
|
|
181
|
+
*
|
|
182
|
+
* `xs` sits below that scale on purpose: no text control is 24px. Its
|
|
183
|
+
* target is the box itself on every pointer type. An invisible larger hit
|
|
184
|
+
* area was tried and removed: on touch it covered the visible edge of the
|
|
185
|
+
* neighbouring button, so a tap there fired the wrong one.
|
|
36
186
|
*/
|
|
37
187
|
const sizeClass = $derived.by(() => {
|
|
38
|
-
if (size === "
|
|
188
|
+
if (size === "xs") return { box: "size-6", spinner: "size-3" };
|
|
189
|
+
if (size === "sm") return { box: "size-8 pointer-coarse:min-h-11 pointer-coarse:min-w-11", spinner: "size-3.5" };
|
|
39
190
|
if (size === "lg") return { box: "size-12", spinner: "size-5" };
|
|
40
|
-
return { box: "size-10", spinner: "size-4" };
|
|
191
|
+
return { box: "size-10 pointer-coarse:min-h-11 pointer-coarse:min-w-11", spinner: "size-4" };
|
|
41
192
|
});
|
|
42
193
|
|
|
43
194
|
const disabledClass =
|
|
44
|
-
"disabled:bg-action-disabled disabled:text-action-disabled-text disabled:border-transparent disabled:shadow-none disabled:cursor-not-allowed disabled:active:scale-100";
|
|
195
|
+
"disabled:bg-action-disabled disabled:text-action-disabled-text disabled:border-transparent disabled:bg-none disabled:inset-shadow-none disabled:shadow-none disabled:cursor-not-allowed disabled:active:scale-100";
|
|
196
|
+
|
|
197
|
+
const isDangerTone = $derived(
|
|
198
|
+
tone === "danger" && (variant === "ghost" || variant === "outline"),
|
|
199
|
+
);
|
|
45
200
|
|
|
46
201
|
const variantClass = $derived.by(() => {
|
|
202
|
+
// The veil of the solid fills, as on Button. Not when disabled, and
|
|
203
|
+
// not on a toggled-on button (`pressedClass`): that holds the pressed
|
|
204
|
+
// fill flat, with its outline as the shape.
|
|
205
|
+
const veil = disabled || (isToggle && pressed) ? "" : "bg-control-gradient ";
|
|
206
|
+
const veilAccent = disabled || (isToggle && pressed) ? "" : "bg-control-gradient-accent ";
|
|
207
|
+
if (isDangerTone) {
|
|
208
|
+
const fill =
|
|
209
|
+
"text-error hover:bg-action-danger-subtle active:bg-action-danger-subtle-hover active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--danger";
|
|
210
|
+
return variant === "outline"
|
|
211
|
+
? `bg-transparent border border-error-border hover:border-error ${fill}`
|
|
212
|
+
: `bg-transparent ${fill}`;
|
|
213
|
+
}
|
|
47
214
|
switch (variant) {
|
|
48
215
|
case "secondary":
|
|
49
|
-
return "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98]";
|
|
216
|
+
return "bg-action-secondary text-headline hover:bg-action-secondary-hover active:bg-action-secondary-active active:scale-[0.98] motion-reduce:active:scale-100";
|
|
217
|
+
case "tonal":
|
|
218
|
+
return "bg-action-tonal text-action-tonal active:scale-[0.98] motion-reduce:active:scale-100";
|
|
50
219
|
case "danger":
|
|
51
|
-
return
|
|
220
|
+
return `${veil}bg-action-danger text-action-danger-text hover:bg-action-danger-hover active:bg-action-danger-active active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--danger`;
|
|
52
221
|
case "ghost":
|
|
53
|
-
return "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active active:scale-[0.98] focus-ring--muted";
|
|
222
|
+
return "bg-transparent text-headline hover:bg-surface-hover active:bg-surface-active active:scale-[0.98] motion-reduce:active:scale-100 focus-ring--muted";
|
|
54
223
|
case "outline":
|
|
55
|
-
return "bg-transparent border border-
|
|
224
|
+
return "bg-transparent border border-action-outline text-headline hover:bg-surface-hover hover:border-action-outline-hover active:bg-surface-active active:scale-[0.98] motion-reduce:active:scale-100";
|
|
56
225
|
case "link":
|
|
226
|
+
case "text":
|
|
57
227
|
return "bg-transparent text-link hover:text-link-hover focus-ring--muted";
|
|
228
|
+
case "accent":
|
|
229
|
+
return `${veilAccent}bg-accent text-on-accent hover:bg-accent-hover active:bg-accent-active active:scale-[0.98] motion-reduce:active:scale-100`;
|
|
58
230
|
case "primary":
|
|
59
231
|
default:
|
|
60
|
-
return
|
|
232
|
+
return `${veil}bg-action-primary text-action-primary hover:bg-action-primary-hover active:bg-action-primary-active active:scale-[0.98] motion-reduce:active:scale-100`;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Held down, a toggled-on ghost or danger-tone button goes one step past its
|
|
238
|
+
* hover fill (the `-subtle-active` roles): with a mouse the hover fill is
|
|
239
|
+
* already showing, so the same fill would not show the press. The solid
|
|
240
|
+
* variants have no further step and keep their fill.
|
|
241
|
+
*
|
|
242
|
+
* Pressed holds a fill that hover cannot reach and adds an inset outline in
|
|
243
|
+
* the text colour, so the state is a shape as well as a colour. It is an
|
|
244
|
+
* outline, not a ring: `.focus-ring` owns `box-shadow`, and an outline also
|
|
245
|
+
* survives forced-colors mode.
|
|
246
|
+
*/
|
|
247
|
+
const pressedClass = $derived.by(() => {
|
|
248
|
+
if (!pressed) return "";
|
|
249
|
+
const outline = "outline-2 -outline-offset-2 outline-current";
|
|
250
|
+
if (isDangerTone) {
|
|
251
|
+
return `bg-action-danger-subtle hover:bg-action-danger-subtle-hover active:bg-action-danger-subtle-active ${outline}`;
|
|
252
|
+
}
|
|
253
|
+
switch (variant) {
|
|
254
|
+
case "secondary":
|
|
255
|
+
return `bg-action-secondary-active hover:bg-action-secondary-active ${outline}`;
|
|
256
|
+
case "danger":
|
|
257
|
+
return `bg-action-danger-active hover:bg-action-danger-active ${outline}`;
|
|
258
|
+
case "ghost":
|
|
259
|
+
case "outline":
|
|
260
|
+
case "link":
|
|
261
|
+
case "text":
|
|
262
|
+
return `bg-action-primary-subtle text-link hover:bg-action-primary-subtle-hover active:bg-action-primary-subtle-active ${outline}`;
|
|
263
|
+
case "tonal":
|
|
264
|
+
// The tonal fill keeps its own hover and pressed steps; the
|
|
265
|
+
// outline is what shows it is on.
|
|
266
|
+
return outline;
|
|
267
|
+
case "accent":
|
|
268
|
+
return `bg-accent-active hover:bg-accent-active ${outline}`;
|
|
269
|
+
case "primary":
|
|
270
|
+
default:
|
|
271
|
+
return `bg-action-primary-active hover:bg-action-primary-active ${outline}`;
|
|
61
272
|
}
|
|
62
273
|
});
|
|
63
274
|
|
|
64
275
|
const buttonClasses = $derived.by(() => {
|
|
65
276
|
const base =
|
|
66
|
-
"inline-flex focus-ring items-center justify-center rounded-control shrink-0 transition-colors duration-
|
|
67
|
-
|
|
277
|
+
"inline-flex focus-ring items-center justify-center rounded-control shrink-0 transition-colors duration-(--duration-base) cursor-pointer select-none";
|
|
278
|
+
// `disabled:` does not match an `<a>`: a disabled link wears the
|
|
279
|
+
// disabled pair itself, in place of its variant. So does a loading
|
|
280
|
+
// button, which is not `:disabled` (it keeps focus): with the
|
|
281
|
+
// variant's classes left out, none of its hover or pressed fills can
|
|
282
|
+
// show. The box is a fixed square, so the border changes no size.
|
|
283
|
+
const state =
|
|
284
|
+
isDisabled && (isLink || isBusy)
|
|
285
|
+
? "bg-(--color-action-disabled) text-action-disabled-text border border-transparent cursor-not-allowed"
|
|
286
|
+
: `${variantClass} ${isLink ? "" : pressedClass} ${disabledClass}`;
|
|
287
|
+
// Relative only for the badge: it is placed against the button's own box.
|
|
288
|
+
return cn(`${base} ${showCount ? "relative " : ""}${sizeClass.box} ${state} ${className}`);
|
|
68
289
|
});
|
|
69
290
|
</script>
|
|
70
291
|
|
|
71
|
-
|
|
72
|
-
{type}
|
|
73
|
-
class={buttonClasses}
|
|
74
|
-
disabled={isDisabled}
|
|
75
|
-
aria-busy={loading ? "true" : undefined}
|
|
76
|
-
{onclick}
|
|
77
|
-
aria-label={label || undefined}
|
|
78
|
-
{...restProps}
|
|
79
|
-
>
|
|
292
|
+
{#snippet content()}
|
|
80
293
|
{#if loading}
|
|
81
294
|
<span
|
|
82
|
-
class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80"
|
|
295
|
+
class="inline-block {sizeClass.spinner} shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent opacity-80 motion-reduce:animate-pulse"
|
|
83
296
|
aria-hidden="true"
|
|
84
297
|
></span>
|
|
85
298
|
{:else if children}
|
|
86
299
|
{@render children()}
|
|
87
300
|
{/if}
|
|
88
|
-
|
|
301
|
+
{#if showCount}
|
|
302
|
+
<!-- Inside the box, in its upper end corner, whatever the size: the box
|
|
303
|
+
edge is the outer edge, so nothing outside it can cut it. Decorative; the
|
|
304
|
+
name carries the count. -->
|
|
305
|
+
{#if countAsDot}
|
|
306
|
+
<span
|
|
307
|
+
class="pointer-events-none absolute end-0.5 top-0.5 size-2 rounded-full bg-error"
|
|
308
|
+
aria-hidden="true"
|
|
309
|
+
data-icon-button-count="dot"
|
|
310
|
+
></span>
|
|
311
|
+
{:else}
|
|
312
|
+
<Badge
|
|
313
|
+
size="sm"
|
|
314
|
+
emphasis="solid"
|
|
315
|
+
variant="error"
|
|
316
|
+
aria-hidden="true"
|
|
317
|
+
data-icon-button-count="badge"
|
|
318
|
+
class="pointer-events-none absolute end-0.5 top-0.5 h-[18px] min-h-[18px] min-w-[18px] px-[5px] py-0 text-[11px] leading-[18px] whitespace-nowrap"
|
|
319
|
+
>
|
|
320
|
+
{badgeText(count as number, countMax)}
|
|
321
|
+
</Badge>
|
|
322
|
+
{/if}
|
|
323
|
+
{/if}
|
|
324
|
+
{/snippet}
|
|
325
|
+
|
|
326
|
+
{#if isLink}
|
|
327
|
+
<!-- A loading link is given its Tab stop back, so focus stays on it:
|
|
328
|
+
`tabindex` is written before `href` is taken away, in that order. -->
|
|
329
|
+
<a
|
|
330
|
+
tabindex={isBusy || keepsTabStop ? 0 : undefined}
|
|
331
|
+
href={isDisabled ? undefined : href}
|
|
332
|
+
class={buttonClasses}
|
|
333
|
+
role={isDisabled ? "link" : undefined}
|
|
334
|
+
aria-disabled={isDisabled ? "true" : undefined}
|
|
335
|
+
aria-busy={loading ? "true" : undefined}
|
|
336
|
+
aria-label={accessibleName}
|
|
337
|
+
{...(restProps as unknown as HTMLAnchorAttributes)}
|
|
338
|
+
onclick={handleLinkClick}
|
|
339
|
+
>
|
|
340
|
+
{@render content()}
|
|
341
|
+
</a>
|
|
342
|
+
{:else}
|
|
343
|
+
<button
|
|
344
|
+
type={type ?? "button"}
|
|
345
|
+
class={buttonClasses}
|
|
346
|
+
disabled={!!disabled}
|
|
347
|
+
aria-disabled={isBusy ? "true" : undefined}
|
|
348
|
+
aria-busy={loading ? "true" : undefined}
|
|
349
|
+
aria-pressed={pressed}
|
|
350
|
+
onclick={handleClick}
|
|
351
|
+
aria-label={accessibleName}
|
|
352
|
+
{...restProps}
|
|
353
|
+
>
|
|
354
|
+
{@render content()}
|
|
355
|
+
</button>
|
|
356
|
+
{/if}
|
|
@@ -1,15 +1,73 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type { HTMLButtonAttributes } from "svelte/elements";
|
|
1
|
+
import { type Snippet } from "svelte";
|
|
2
|
+
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from "svelte/elements";
|
|
3
3
|
import type { ButtonVariant, SizeVariant } from "../types/variants.js";
|
|
4
|
+
/** The shared scale plus `xs`, which only the icon button has. */
|
|
5
|
+
type IconButtonSize = SizeVariant | "xs";
|
|
6
|
+
/**
|
|
7
|
+
* One type for the button and the link, not a union of the two elements'
|
|
8
|
+
* attributes: that union is too large for TypeScript to carry through a
|
|
9
|
+
* wrapper such as a Storybook `Meta`. Event handlers are typed for the
|
|
10
|
+
* button; on a link they are called with the same event.
|
|
11
|
+
*/
|
|
4
12
|
type Props = Omit<HTMLButtonAttributes, "class"> & {
|
|
13
|
+
/**
|
|
14
|
+
* Where the link goes. Makes this an `<a>` that looks the same;
|
|
15
|
+
* without it, it is a `<button>`. A link cannot be disabled: while
|
|
16
|
+
* `disabled` or `loading` it has no `href`, is `aria-disabled` and
|
|
17
|
+
* does nothing when pressed. A link is not
|
|
18
|
+
* a toggle: `pressed` is ignored.
|
|
19
|
+
*/
|
|
20
|
+
href?: string;
|
|
21
|
+
/** With `href`: where the link opens. */
|
|
22
|
+
target?: HTMLAnchorAttributes["target"];
|
|
23
|
+
/** With `href`: the link's relationship, such as `noopener`. */
|
|
24
|
+
rel?: HTMLAnchorAttributes["rel"];
|
|
25
|
+
/** With `href`: download the address instead of opening it. */
|
|
26
|
+
download?: HTMLAnchorAttributes["download"];
|
|
27
|
+
hreflang?: HTMLAnchorAttributes["hreflang"];
|
|
28
|
+
referrerpolicy?: HTMLAnchorAttributes["referrerpolicy"];
|
|
29
|
+
ping?: HTMLAnchorAttributes["ping"];
|
|
5
30
|
variant?: ButtonVariant;
|
|
6
|
-
|
|
31
|
+
/**
|
|
32
|
+
* `xs` is a 24px box for dense, pointer-first layouts (card headers,
|
|
33
|
+
* table rows). That is the WCAG 2.2 minimum target size and no more:
|
|
34
|
+
* where the primary input is touch, use `sm` or larger.
|
|
35
|
+
*/
|
|
36
|
+
size?: IconButtonSize;
|
|
37
|
+
/**
|
|
38
|
+
* Colour intent for the `ghost` and `outline` variants: `danger` is
|
|
39
|
+
* the quiet destructive button (inline delete). Other variants ignore it.
|
|
40
|
+
*/
|
|
41
|
+
tone?: "default" | "danger";
|
|
42
|
+
/**
|
|
43
|
+
* Makes this a toggle button. When defined (true or false) it renders
|
|
44
|
+
* `aria-pressed` and a click flips it; bind it, or pass it one-way and
|
|
45
|
+
* update your own state in `onclick`. Call `event.preventDefault()` in
|
|
46
|
+
* `onclick` to keep the current state: do that whenever the parent
|
|
47
|
+
* updates later (after a request, say) or may refuse the change, or the
|
|
48
|
+
* button shows a state the parent does not have. Leave undefined for a
|
|
49
|
+
* plain button.
|
|
50
|
+
*/
|
|
51
|
+
pressed?: boolean;
|
|
7
52
|
loading?: boolean;
|
|
8
53
|
/** Required for icon-only usage (no visible text). */
|
|
9
54
|
label?: string;
|
|
55
|
+
/**
|
|
56
|
+
* A count drawn on the button, in the attention colour, inside the
|
|
57
|
+
* button's own box (so a bar or an `overflow` ancestor cannot cut it).
|
|
58
|
+
* Nothing is drawn for 0, a negative number or when it is left out;
|
|
59
|
+
* while `loading` it is hidden. At `xs` and `sm` there is no room for
|
|
60
|
+
* a number: a dot is drawn instead. Needs `label`: the accessible name
|
|
61
|
+
* becomes the label, a comma and `countLabel(count)`.
|
|
62
|
+
*/
|
|
63
|
+
count?: number;
|
|
64
|
+
/** What the count adds to the accessible name, after the label. Default: "3 new". */
|
|
65
|
+
countLabel?: (count: number) => string;
|
|
66
|
+
/** Above this the badge reads `99+`. The accessible name keeps the real count. */
|
|
67
|
+
countMax?: number;
|
|
10
68
|
class?: string;
|
|
11
69
|
children?: Snippet;
|
|
12
70
|
};
|
|
13
|
-
declare const IconButton: import("svelte").Component<Props, {}, "">;
|
|
71
|
+
declare const IconButton: import("svelte").Component<Props, {}, "pressed">;
|
|
14
72
|
type IconButton = ReturnType<typeof IconButton>;
|
|
15
73
|
export default IconButton;
|