@getmicdrop/svelte-components 5.10.3 → 5.13.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/dist/calendar/AboutShow/AboutShow.svelte +172 -172
- package/dist/calendar/Calendar/MiniMonthCalendar.svelte +782 -782
- package/dist/calendar/FAQs/FAQs.svelte +75 -75
- package/dist/calendar/MonthSwitcher/MonthSwitcher.svelte +126 -126
- package/dist/calendar/OrderSummary/OrderSummary.svelte +367 -367
- package/dist/calendar/PublicCard/PublicCard.svelte +146 -146
- package/dist/calendar/ShowCard/ShowCard.svelte +157 -157
- package/dist/calendar/ShowTimeCard/ShowTimeCard.svelte +61 -61
- package/dist/components/Heading.svelte +60 -60
- package/dist/components/Layout/AppShell.svelte +104 -104
- package/dist/components/Layout/ContentSection.svelte +80 -80
- package/dist/components/Layout/Grid.svelte +4 -4
- package/dist/components/Layout/Heading.svelte +81 -81
- package/dist/components/Layout/PageContainer.svelte +69 -69
- package/dist/components/Layout/Responsive.svelte +75 -75
- package/dist/components/Layout/Section.svelte +80 -80
- package/dist/components/Layout/ShowOnDesktop.svelte +37 -37
- package/dist/components/Layout/ShowOnMobile.svelte +37 -37
- package/dist/components/Layout/Sidebar.svelte +108 -108
- package/dist/components/Layout/Stack.spec.js +1 -1
- package/dist/components/Layout/Stack.svelte +6 -6
- package/dist/components/Layout/Text.svelte +87 -87
- package/dist/components/Layout/TwoColumn.svelte +108 -108
- package/dist/components/Text.svelte +53 -53
- package/dist/constants/validation.js +91 -91
- package/dist/constants/validation.spec.js +64 -64
- package/dist/datetime/__tests__/format.test.js +1 -1
- package/dist/datetime/__tests__/parse.test.js +1 -1
- package/dist/datetime/__tests__/timezone.test.js +1 -1
- package/dist/datetime/parse.js +1 -1
- package/dist/forms/createFormStore.svelte.js +0 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -51
- package/dist/index.spec.js +0 -1
- package/dist/patterns/data/DataGrid.svelte +45 -45
- package/dist/patterns/data/DataList.svelte +24 -24
- package/dist/patterns/data/DataTable.svelte +36 -36
- package/dist/patterns/forms/FormActions.spec.js +95 -95
- package/dist/patterns/forms/FormActions.stories.svelte +97 -97
- package/dist/patterns/forms/FormActions.svelte +46 -46
- package/dist/patterns/forms/FormGrid.svelte +33 -33
- package/dist/patterns/forms/FormSection.svelte +32 -32
- package/dist/patterns/forms/FormValidationSummary.stories.svelte +83 -83
- package/dist/patterns/forms/FormValidationSummary.svelte +74 -74
- package/dist/patterns/layout/Sidebar.svelte +39 -39
- package/dist/patterns/layout/index.js +29 -29
- package/dist/patterns/navigation/BottomNav.stories.svelte +117 -117
- package/dist/patterns/navigation/BottomNav.svelte +74 -74
- package/dist/patterns/navigation/Header.stories.svelte +77 -77
- package/dist/patterns/navigation/Header.svelte +251 -255
- package/dist/patterns/navigation/Header.svelte.d.ts.map +1 -1
- package/dist/patterns/page/PageHeader.svelte +18 -18
- package/dist/patterns/page/PageLayout.svelte +40 -40
- package/dist/patterns/page/PageLoader.spec.js +57 -57
- package/dist/patterns/page/PageLoader.stories.svelte +137 -137
- package/dist/patterns/page/PageLoader.svelte +24 -24
- package/dist/patterns/page/SectionHeader.svelte +29 -29
- package/dist/presets/badges.js +112 -112
- package/dist/presets/buttons.js +76 -76
- package/dist/presets/index.js +9 -9
- package/dist/primitives/Accordion/Accordion.stories.svelte +75 -75
- package/dist/primitives/Accordion/Accordion.svelte +42 -42
- package/dist/primitives/Accordion/AccordionItem.svelte +95 -95
- package/dist/primitives/Alert/Alert.spec.js +173 -173
- package/dist/primitives/Alert/Alert.stories.svelte +88 -88
- package/dist/primitives/Alert/Alert.svelte +27 -27
- package/dist/primitives/Avatar/Avatar.stories.svelte +94 -94
- package/dist/primitives/Avatar/Avatar.svelte +66 -66
- package/dist/primitives/AvatarButton/AvatarButton.svelte +57 -0
- package/dist/primitives/AvatarButton/AvatarButton.svelte.d.ts +18 -0
- package/dist/primitives/AvatarButton/AvatarButton.svelte.d.ts.map +1 -0
- package/dist/primitives/Badges/Badge.spec.js +144 -144
- package/dist/primitives/Badges/Badge.stories.svelte +86 -86
- package/dist/primitives/Badges/Badge.svelte +99 -99
- package/dist/primitives/BottomSheet/BottomSheet.spec.js +136 -136
- package/dist/primitives/BottomSheet/BottomSheet.stories.svelte +83 -83
- package/dist/primitives/BottomSheet/BottomSheet.svelte +100 -100
- package/dist/primitives/BottomSheet/BottomSheet.svelte.d.ts +2 -2
- package/dist/primitives/BottomSheet/BottomSheet.svelte.d.ts.map +1 -1
- package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte +3 -3
- package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte.d.ts +1 -1
- package/dist/primitives/Breadcrumb/Breadcrumb.spec.js +123 -122
- package/dist/primitives/Breadcrumb/Breadcrumb.stories.svelte +23 -23
- package/dist/primitives/Breadcrumb/Breadcrumb.svelte +99 -98
- package/dist/primitives/Button/Button.spec.js +223 -223
- package/dist/primitives/Button/Button.stories.svelte +76 -76
- package/dist/primitives/Button/Button.svelte +278 -283
- package/dist/primitives/Button/Button.svelte.d.ts +2 -0
- package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
- package/dist/primitives/Button/ButtonGroup.svelte +50 -50
- package/dist/primitives/Button/ButtonSaveDemo.spec.js +146 -146
- package/dist/primitives/Button/ButtonSaveDemo.svelte +25 -25
- package/dist/primitives/Button/ButtonVariantShowcase.svelte +129 -129
- package/dist/primitives/Card.spec.js +49 -49
- package/dist/primitives/Card.stories.svelte +22 -22
- package/dist/primitives/Card.svelte +28 -28
- package/dist/primitives/CardAction/CardAction.svelte +68 -0
- package/dist/primitives/CardAction/CardAction.svelte.d.ts +20 -0
- package/dist/primitives/CardAction/CardAction.svelte.d.ts.map +1 -0
- package/dist/primitives/Checkbox/Checkbox.stories.svelte +84 -84
- package/dist/primitives/Checkbox/Checkbox.svelte +88 -88
- package/dist/primitives/DarkModeToggle.spec.js +390 -390
- package/dist/primitives/DarkModeToggle.stories.svelte +57 -57
- package/dist/primitives/DarkModeToggle.svelte +136 -136
- package/dist/primitives/Drawer/Drawer.spec.js +33 -33
- package/dist/primitives/Drawer/Drawer.stories.svelte +80 -80
- package/dist/primitives/Drawer/Drawer.svelte +123 -127
- package/dist/primitives/Drawer/Drawer.svelte.d.ts +2 -3
- package/dist/primitives/Drawer/Drawer.svelte.d.ts.map +1 -1
- package/dist/primitives/Dropdown/Dropdown.stories.svelte +137 -137
- package/dist/primitives/Dropdown/Dropdown.svelte +170 -170
- package/dist/primitives/Dropdown/DropdownDivider.svelte +9 -9
- package/dist/primitives/Dropdown/DropdownItem.svelte +80 -80
- package/dist/primitives/Helper/Helper.svelte +33 -33
- package/dist/primitives/Icons/ArrowLeft.svelte +8 -8
- package/dist/primitives/Icons/ArrowRight.svelte +8 -8
- package/dist/primitives/Icons/Availability.svelte +14 -14
- package/dist/primitives/Icons/Back.svelte +14 -14
- package/dist/primitives/Icons/CheckCircle.svelte +6 -6
- package/dist/primitives/Icons/CheckCircleOutline.svelte +15 -15
- package/dist/primitives/Icons/ChevronLeft.svelte +4 -4
- package/dist/primitives/Icons/ChevronRight.svelte +4 -4
- package/dist/primitives/Icons/Copy.svelte +15 -15
- package/dist/primitives/Icons/Cross.svelte +5 -5
- package/dist/primitives/Icons/DownArrow.svelte +8 -8
- package/dist/primitives/Icons/ErrorCircle.svelte +6 -6
- package/dist/primitives/Icons/FacebookIcon.svelte +2 -2
- package/dist/primitives/Icons/Home.svelte +15 -15
- package/dist/primitives/Icons/Icon.spec.js +169 -169
- package/dist/primitives/Icons/Icon.stories.svelte +100 -100
- package/dist/primitives/Icons/Icon.svelte +52 -52
- package/dist/primitives/Icons/IconGallery.stories.svelte +235 -235
- package/dist/primitives/Icons/Info.svelte +7 -7
- package/dist/primitives/Icons/InstagramIcon.svelte +4 -4
- package/dist/primitives/Icons/LogoInstagram.svelte +2 -2
- package/dist/primitives/Icons/Message.svelte +15 -15
- package/dist/primitives/Icons/MoonIcon.svelte +5 -5
- package/dist/primitives/Icons/More.svelte +21 -21
- package/dist/primitives/Icons/MoreHori.spec.js +61 -61
- package/dist/primitives/Icons/MoreHori.svelte +22 -22
- package/dist/primitives/Icons/Notification.svelte +14 -14
- package/dist/primitives/Icons/Payment.svelte +14 -14
- package/dist/primitives/Icons/Profile.svelte +21 -21
- package/dist/primitives/Icons/Reload.svelte +29 -29
- package/dist/primitives/Icons/Shows.svelte +21 -21
- package/dist/primitives/Icons/Signout.svelte +21 -21
- package/dist/primitives/Icons/SunIcon.svelte +8 -8
- package/dist/primitives/Icons/TiktokIcon.svelte +2 -2
- package/dist/primitives/Icons/TwitterIcon.svelte +2 -2
- package/dist/primitives/Icons/WarningIcon.spec.js +18 -18
- package/dist/primitives/Icons/WarningIcon.svelte +5 -5
- package/dist/primitives/Input/Input.spec.js +573 -573
- package/dist/primitives/Input/Input.stories.svelte +139 -139
- package/dist/primitives/Input/Input.svelte +423 -423
- package/dist/primitives/Input/Select.spec.js +218 -218
- package/dist/primitives/Input/Select.stories.svelte +112 -112
- package/dist/primitives/Input/Select.svelte +252 -252
- package/dist/primitives/Input/Textarea.stories.svelte +137 -137
- package/dist/primitives/Input/Textarea.svelte +105 -105
- package/dist/primitives/Label/Label.svelte +37 -37
- package/dist/primitives/LandingButton/LandingButton.svelte +92 -0
- package/dist/primitives/LandingButton/LandingButton.svelte.d.ts +22 -0
- package/dist/primitives/LandingButton/LandingButton.svelte.d.ts.map +1 -0
- package/dist/primitives/MenuItem/MenuItem.svelte +85 -0
- package/dist/primitives/MenuItem/MenuItem.svelte.d.ts +24 -0
- package/dist/primitives/MenuItem/MenuItem.svelte.d.ts.map +1 -0
- package/dist/primitives/Modal/Modal.spec.js +99 -99
- package/dist/primitives/Modal/Modal.stories.svelte +86 -86
- package/dist/primitives/Modal/Modal.svelte +181 -157
- package/dist/primitives/Modal/Modal.svelte.d.ts +7 -5
- package/dist/primitives/Modal/Modal.svelte.d.ts.map +1 -1
- package/dist/primitives/Modal/ModalTestWrapper.svelte +3 -3
- package/dist/primitives/Modal/ModalTestWrapper.svelte.d.ts +2 -2
- package/dist/primitives/NavItem/NavItem.svelte +75 -0
- package/dist/primitives/NavItem/NavItem.svelte.d.ts +20 -0
- package/dist/primitives/NavItem/NavItem.svelte.d.ts.map +1 -0
- package/dist/primitives/Pagination/Pagination.stories.svelte +76 -76
- package/dist/primitives/Pagination/Pagination.svelte +261 -261
- package/dist/primitives/Radio/Radio.stories.svelte +80 -80
- package/dist/primitives/Radio/Radio.svelte +67 -67
- package/dist/primitives/SearchResultItem/SearchResultItem.svelte +109 -0
- package/dist/primitives/SearchResultItem/SearchResultItem.svelte.d.ts +26 -0
- package/dist/primitives/SearchResultItem/SearchResultItem.svelte.d.ts.map +1 -0
- package/dist/primitives/SidebarToggle/SidebarToggle.svelte +55 -0
- package/dist/primitives/SidebarToggle/SidebarToggle.svelte.d.ts +18 -0
- package/dist/primitives/SidebarToggle/SidebarToggle.svelte.d.ts.map +1 -0
- package/dist/primitives/Skeleton/CardPlaceholder.svelte +87 -87
- package/dist/primitives/Skeleton/ImagePlaceholder.svelte +59 -59
- package/dist/primitives/Skeleton/ListPlaceholder.svelte +76 -76
- package/dist/primitives/Skeleton/Skeleton.stories.svelte +151 -151
- package/dist/primitives/Skeleton/Skeleton.svelte +26 -26
- package/dist/primitives/Spinner/Spinner.spec.js +71 -71
- package/dist/primitives/Spinner/Spinner.stories.svelte +29 -29
- package/dist/primitives/Spinner/Spinner.svelte +20 -20
- package/dist/primitives/Tabs/TabItem.svelte +49 -49
- package/dist/primitives/Tabs/Tabs.stories.svelte +112 -112
- package/dist/primitives/Tabs/Tabs.svelte +137 -137
- package/dist/primitives/Toggle.spec.js +146 -146
- package/dist/primitives/Toggle.stories.svelte +92 -92
- package/dist/primitives/Toggle.svelte +141 -131
- package/dist/primitives/Toggle.svelte.d.ts +2 -0
- package/dist/primitives/Toggle.svelte.d.ts.map +1 -1
- package/dist/primitives/Tooltip/Tooltip.svelte +83 -83
- package/dist/primitives/Typography/Typography.svelte +53 -53
- package/dist/primitives/ValidationError.spec.js +103 -103
- package/dist/primitives/ValidationError.stories.svelte +69 -69
- package/dist/primitives/ValidationError.svelte +29 -29
- package/dist/primitives/index.d.ts +7 -0
- package/dist/primitives/index.js +113 -92
- package/dist/recipes/CropImage/CropImage.spec.js +208 -208
- package/dist/recipes/CropImage/CropImage.stories.svelte +104 -104
- package/dist/recipes/CropImage/CropImage.svelte +219 -219
- package/dist/recipes/ImageUploader/ImageUploader.stories.svelte +125 -125
- package/dist/recipes/ImageUploader/ImageUploader.svelte +970 -970
- package/dist/recipes/SuperLogin/SuperLogin.svelte +3 -3
- package/dist/recipes/SuperLogin/SuperLogin.svelte.d.ts.map +1 -1
- package/dist/recipes/Toaster/Toaster.stories.svelte +62 -62
- package/dist/recipes/feedback/EmptyState/EmptyState.svelte +1 -1
- package/dist/recipes/feedback/ErrorDisplay.spec.js +69 -69
- package/dist/recipes/feedback/ErrorDisplay.stories.svelte +101 -101
- package/dist/recipes/feedback/ErrorDisplay.svelte +1 -1
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.spec.js +133 -133
- package/dist/recipes/feedback/StatusIndicator/StatusIndicator.svelte +157 -157
- package/dist/recipes/fields/CheckboxField.svelte +85 -85
- package/dist/recipes/fields/FormField.svelte +58 -58
- package/dist/recipes/fields/RadioGroup.svelte +95 -95
- package/dist/recipes/fields/SelectField.svelte +80 -80
- package/dist/recipes/fields/TextareaField.svelte +97 -97
- package/dist/recipes/fields/ToggleField.svelte +60 -60
- package/dist/recipes/fields/index.js +7 -7
- package/dist/recipes/inputs/MultiSelect.spec.js +260 -260
- package/dist/recipes/inputs/MultiSelect.stories.svelte +133 -133
- package/dist/recipes/inputs/MultiSelect.svelte +283 -283
- package/dist/recipes/inputs/OTPInput.spec.js +251 -251
- package/dist/recipes/inputs/OTPInput.stories.svelte +162 -162
- package/dist/recipes/inputs/OTPInput.svelte +117 -117
- package/dist/recipes/inputs/PasswordInput.svelte +22 -22
- package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte +131 -131
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.stories.svelte +123 -123
- package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.svelte +344 -344
- package/dist/recipes/inputs/Search.svelte +102 -102
- package/dist/recipes/inputs/index.d.ts +0 -1
- package/dist/recipes/inputs/index.js +0 -1
- package/dist/recipes/modals/AlertModal.spec.js +2 -2
- package/dist/recipes/modals/AlertModal.svelte +130 -130
- package/dist/recipes/modals/AlertModal.svelte.d.ts +3 -3
- package/dist/recipes/modals/ConfirmationModal.spec.js +206 -206
- package/dist/recipes/modals/ConfirmationModal.stories.svelte +119 -119
- package/dist/recipes/modals/ConfirmationModal.svelte +162 -152
- package/dist/recipes/modals/ConfirmationModal.svelte.d.ts +5 -3
- package/dist/recipes/modals/ConfirmationModal.svelte.d.ts.map +1 -1
- package/dist/recipes/modals/InputModal.spec.js +2 -2
- package/dist/recipes/modals/InputModal.svelte +182 -182
- package/dist/recipes/modals/InputModal.svelte.d.ts +3 -3
- package/dist/recipes/modals/ModalStateManager.spec.js +100 -100
- package/dist/recipes/modals/ModalStateManager.svelte +77 -77
- package/dist/recipes/modals/ModalTestWrapper.spec.js +49 -49
- package/dist/recipes/modals/ModalTestWrapper.svelte +65 -65
- package/dist/recipes/modals/ModalTestWrapper.svelte.d.ts +2 -2
- package/dist/recipes/modals/StatusModal.spec.js +2 -2
- package/dist/recipes/modals/StatusModal.svelte +206 -206
- package/dist/recipes/modals/StatusModal.svelte.d.ts +3 -3
- package/dist/services/EventService.js +75 -75
- package/dist/services/EventService.spec.js +217 -217
- package/dist/services/ShowService.spec.js +345 -345
- package/dist/stores/toaster.js +13 -13
- package/dist/stories/ButtonAuditReview.stories.svelte +14 -14
- package/dist/stories/ButtonAuditReview.svelte +427 -427
- package/dist/stories/ComponentConsolidation.stories.svelte +10 -10
- package/dist/stories/PatternsGallery.stories.svelte +19 -19
- package/dist/stories/PatternsGallery.svelte +206 -206
- package/dist/stories/PrimitivesGallery.stories.svelte +19 -19
- package/dist/stories/PrimitivesGallery.svelte +756 -752
- package/dist/stories/PrimitivesGallery.svelte.d.ts.map +1 -1
- package/dist/stories/RecipesGallery.spec.js +9 -18
- package/dist/stories/RecipesGallery.stories.svelte +19 -19
- package/dist/stories/RecipesGallery.svelte +454 -471
- package/dist/stories/RecipesGallery.svelte.d.ts.map +1 -1
- package/dist/stories/button-audit-manifest.json +11186 -11186
- package/dist/tailwind/preset.cjs +82 -82
- package/dist/telemetry.js +405 -405
- package/dist/telemetry.spec.js +1169 -1169
- package/dist/tokens/tokens.css +87 -87
- package/dist/tokens/typography-base.css +163 -163
- package/dist/tokens/utilities.css +353 -353
- package/dist/utils/apiConfig.spec.js +219 -219
- package/dist/utils/haptic.d.ts +41 -0
- package/dist/utils/haptic.d.ts.map +1 -0
- package/dist/utils/haptic.js +115 -0
- package/dist/utils/transitions.js +4 -4
- package/dist/utils/utils.js +693 -693
- package/package.json +297 -297
- package/dist/recipes/inputs/SelectDropdown.spec.d.ts +0 -2
- package/dist/recipes/inputs/SelectDropdown.spec.d.ts.map +0 -1
- package/dist/recipes/inputs/SelectDropdown.spec.js +0 -518
- package/dist/recipes/inputs/SelectDropdown.svelte +0 -171
- package/dist/recipes/inputs/SelectDropdown.svelte.d.ts +0 -16
- package/dist/recipes/inputs/SelectDropdown.svelte.d.ts.map +0 -1
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
<script module>
|
|
2
|
-
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
-
|
|
4
|
-
import DarkModeToggle from './DarkModeToggle.svelte';
|
|
5
|
-
|
|
6
|
-
const { Story } = defineMeta({
|
|
7
|
-
title: 'Components/DarkModeToggle',
|
|
8
|
-
component: DarkModeToggle,
|
|
9
|
-
tags: ['autodocs'],
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
</script>
|
|
13
|
-
|
|
14
|
-
<script>
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<Story name="Default">
|
|
18
|
-
<div class="flex flex-col gap-4 p-4">
|
|
19
|
-
<h3 class="text-lg font-semibold">Theme Toggle (3-State)</h3>
|
|
20
|
-
<p class="text-sm text-gray-500 dark:text-gray-400 dark:text-gray-500 dark:text-gray-400">
|
|
21
|
-
Cycles through: Auto → Light → Dark → Auto
|
|
22
|
-
</p>
|
|
23
|
-
<DarkModeToggle />
|
|
24
|
-
<p class="text-xs text-gray-500 dark:text-gray-400">
|
|
25
|
-
Click the toggle to cycle through theme modes. In auto mode, it follows system preferences.
|
|
26
|
-
</p>
|
|
27
|
-
</div>
|
|
28
|
-
</Story>
|
|
29
|
-
|
|
30
|
-
<Story name="In Header">
|
|
31
|
-
<div class="bg-white dark:bg-gray-900 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-4 rounded-lg">
|
|
32
|
-
<div class="flex items-center justify-between">
|
|
33
|
-
<h2 class="text-xl font-bold text-gray-900 dark:text-white dark:text-white">Application Header</h2>
|
|
34
|
-
<DarkModeToggle />
|
|
35
|
-
</div>
|
|
36
|
-
</div>
|
|
37
|
-
</Story>
|
|
38
|
-
|
|
39
|
-
<Story name="Theme States Demo">
|
|
40
|
-
<div class="space-y-4 p-4">
|
|
41
|
-
<div class="bg-white dark:bg-gray-900 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
42
|
-
<h3 class="text-lg font-semibold text-gray-900 dark:text-white dark:text-white mb-2">
|
|
43
|
-
Current Theme Demo
|
|
44
|
-
</h3>
|
|
45
|
-
<p class="text-gray-500 dark:text-gray-400 dark:text-gray-300 mb-4">
|
|
46
|
-
This content changes appearance based on the selected theme mode.
|
|
47
|
-
</p>
|
|
48
|
-
<DarkModeToggle />
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<div class="text-sm text-gray-500 dark:text-gray-400 dark:text-gray-500 dark:text-gray-400">
|
|
52
|
-
<p><strong>Auto Mode:</strong> Follows system preferences</p>
|
|
53
|
-
<p><strong>Light Mode:</strong> Forces light theme</p>
|
|
54
|
-
<p><strong>Dark Mode:</strong> Forces dark theme</p>
|
|
55
|
-
</div>
|
|
56
|
-
</div>
|
|
57
|
-
</Story>
|
|
1
|
+
<script module>
|
|
2
|
+
import { defineMeta } from "@storybook/addon-svelte-csf";
|
|
3
|
+
|
|
4
|
+
import DarkModeToggle from './DarkModeToggle.svelte';
|
|
5
|
+
|
|
6
|
+
const { Story } = defineMeta({
|
|
7
|
+
title: 'Components/DarkModeToggle',
|
|
8
|
+
component: DarkModeToggle,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<Story name="Default">
|
|
18
|
+
<div class="flex flex-col gap-4 p-4">
|
|
19
|
+
<h3 class="text-lg font-semibold">Theme Toggle (3-State)</h3>
|
|
20
|
+
<p class="text-sm text-gray-500 dark:text-gray-400 dark:text-gray-500 dark:text-gray-400">
|
|
21
|
+
Cycles through: Auto → Light → Dark → Auto
|
|
22
|
+
</p>
|
|
23
|
+
<DarkModeToggle />
|
|
24
|
+
<p class="text-xs text-gray-500 dark:text-gray-400">
|
|
25
|
+
Click the toggle to cycle through theme modes. In auto mode, it follows system preferences.
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
</Story>
|
|
29
|
+
|
|
30
|
+
<Story name="In Header">
|
|
31
|
+
<div class="bg-white dark:bg-gray-900 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 p-4 rounded-lg">
|
|
32
|
+
<div class="flex items-center justify-between">
|
|
33
|
+
<h2 class="text-xl font-bold text-gray-900 dark:text-white dark:text-white">Application Header</h2>
|
|
34
|
+
<DarkModeToggle />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</Story>
|
|
38
|
+
|
|
39
|
+
<Story name="Theme States Demo">
|
|
40
|
+
<div class="space-y-4 p-4">
|
|
41
|
+
<div class="bg-white dark:bg-gray-900 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
|
42
|
+
<h3 class="text-lg font-semibold text-gray-900 dark:text-white dark:text-white mb-2">
|
|
43
|
+
Current Theme Demo
|
|
44
|
+
</h3>
|
|
45
|
+
<p class="text-gray-500 dark:text-gray-400 dark:text-gray-300 mb-4">
|
|
46
|
+
This content changes appearance based on the selected theme mode.
|
|
47
|
+
</p>
|
|
48
|
+
<DarkModeToggle />
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="text-sm text-gray-500 dark:text-gray-400 dark:text-gray-500 dark:text-gray-400">
|
|
52
|
+
<p><strong>Auto Mode:</strong> Follows system preferences</p>
|
|
53
|
+
<p><strong>Light Mode:</strong> Forces light theme</p>
|
|
54
|
+
<p><strong>Dark Mode:</strong> Forces dark theme</p>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</Story>
|
|
@@ -1,136 +1,136 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
|
-
import SunIcon from "./Icons/SunIcon.svelte";
|
|
4
|
-
import MoonIcon from "./Icons/MoonIcon.svelte";
|
|
5
|
-
import Button from "./Button/Button.svelte";
|
|
6
|
-
|
|
7
|
-
interface Props {
|
|
8
|
-
/** Container selector for applying dark class */
|
|
9
|
-
containerSelector?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let { containerSelector = ".performer-portal" }: Props = $props();
|
|
13
|
-
|
|
14
|
-
let themeMode = $state<"auto" | "light" | "dark">("auto");
|
|
15
|
-
let isDark = $state(false);
|
|
16
|
-
|
|
17
|
-
function setMicdropDarkClass(enable: boolean) {
|
|
18
|
-
const container = document.querySelector(containerSelector);
|
|
19
|
-
if (enable) {
|
|
20
|
-
if (container) container.classList.add("dark");
|
|
21
|
-
document.documentElement.classList.add("dark");
|
|
22
|
-
} else {
|
|
23
|
-
if (container) container.classList.remove("dark");
|
|
24
|
-
document.documentElement.classList.remove("dark");
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getSystemPreference() {
|
|
29
|
-
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function applyTheme() {
|
|
33
|
-
if (themeMode === "auto") {
|
|
34
|
-
isDark = getSystemPreference();
|
|
35
|
-
} else {
|
|
36
|
-
isDark = themeMode === "dark";
|
|
37
|
-
}
|
|
38
|
-
setMicdropDarkClass(isDark);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
onMount(() => {
|
|
42
|
-
const savedTheme = localStorage.getItem("theme");
|
|
43
|
-
|
|
44
|
-
if (savedTheme === "dark" || savedTheme === "light") {
|
|
45
|
-
themeMode = savedTheme;
|
|
46
|
-
} else {
|
|
47
|
-
themeMode = "auto";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
applyTheme();
|
|
51
|
-
|
|
52
|
-
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
53
|
-
const handleChange = () => {
|
|
54
|
-
if (themeMode === "auto") {
|
|
55
|
-
applyTheme();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
mediaQuery.addEventListener("change", handleChange);
|
|
59
|
-
|
|
60
|
-
return () => {
|
|
61
|
-
mediaQuery.removeEventListener("change", handleChange);
|
|
62
|
-
};
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
function toggleTheme(event: MouseEvent) {
|
|
66
|
-
if (themeMode === "auto") {
|
|
67
|
-
themeMode = "light";
|
|
68
|
-
localStorage.setItem("theme", "light");
|
|
69
|
-
} else if (themeMode === "light") {
|
|
70
|
-
themeMode = "dark";
|
|
71
|
-
localStorage.setItem("theme", "dark");
|
|
72
|
-
} else {
|
|
73
|
-
themeMode = "auto";
|
|
74
|
-
localStorage.removeItem("theme");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
applyTheme();
|
|
78
|
-
|
|
79
|
-
if (event?.currentTarget) {
|
|
80
|
-
(event.currentTarget as HTMLElement).blur();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let titleText = $derived(
|
|
85
|
-
themeMode === "auto"
|
|
86
|
-
? "Auto theme (following device) - click for light mode"
|
|
87
|
-
: themeMode === "light"
|
|
88
|
-
? "Light mode - click for dark mode"
|
|
89
|
-
: "Dark mode - click for auto"
|
|
90
|
-
);
|
|
91
|
-
</script>
|
|
92
|
-
|
|
93
|
-
<Button
|
|
94
|
-
variant="alternative"
|
|
95
|
-
onclick={toggleTheme}
|
|
96
|
-
class="relative h-10 w-10 overflow-hidden p-0"
|
|
97
|
-
aria-label="Toggle theme"
|
|
98
|
-
title={titleText}
|
|
99
|
-
>
|
|
100
|
-
<span
|
|
101
|
-
class="text-amber-500 transition-all duration-300 {themeMode === 'light'
|
|
102
|
-
? 'scale-100 rotate-0 opacity-100'
|
|
103
|
-
: 'pointer-events-none absolute scale-0 rotate-180 opacity-0'}"
|
|
104
|
-
>
|
|
105
|
-
<SunIcon size="20" />
|
|
106
|
-
</span>
|
|
107
|
-
|
|
108
|
-
<span
|
|
109
|
-
class="transition-all duration-300 {themeMode === 'dark'
|
|
110
|
-
? 'scale-100 rotate-0 opacity-100'
|
|
111
|
-
: 'pointer-events-none absolute scale-0 rotate-180 opacity-0'}"
|
|
112
|
-
>
|
|
113
|
-
<MoonIcon size="20" color="white" />
|
|
114
|
-
</span>
|
|
115
|
-
|
|
116
|
-
{#if themeMode === "auto"}
|
|
117
|
-
<div class="absolute inset-0 overflow-hidden rounded-lg">
|
|
118
|
-
<div
|
|
119
|
-
class="absolute flex h-full w-full items-center justify-center bg-white"
|
|
120
|
-
style="clip-path: polygon(0 0, 100% 0, 0 100%)"
|
|
121
|
-
>
|
|
122
|
-
<span class="-translate-x-1 -translate-y-1 text-amber-500">
|
|
123
|
-
<SunIcon size="12" />
|
|
124
|
-
</span>
|
|
125
|
-
</div>
|
|
126
|
-
<div
|
|
127
|
-
class="absolute flex h-full w-full items-center justify-center bg-gray-800"
|
|
128
|
-
style="clip-path: polygon(100% 0, 100% 100%, 0 100%)"
|
|
129
|
-
>
|
|
130
|
-
<span class="translate-x-1 translate-y-1">
|
|
131
|
-
<MoonIcon size="12" color="white" />
|
|
132
|
-
</span>
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
135
|
-
{/if}
|
|
136
|
-
</Button>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import SunIcon from "./Icons/SunIcon.svelte";
|
|
4
|
+
import MoonIcon from "./Icons/MoonIcon.svelte";
|
|
5
|
+
import Button from "./Button/Button.svelte";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
/** Container selector for applying dark class */
|
|
9
|
+
containerSelector?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { containerSelector = ".performer-portal" }: Props = $props();
|
|
13
|
+
|
|
14
|
+
let themeMode = $state<"auto" | "light" | "dark">("auto");
|
|
15
|
+
let isDark = $state(false);
|
|
16
|
+
|
|
17
|
+
function setMicdropDarkClass(enable: boolean) {
|
|
18
|
+
const container = document.querySelector(containerSelector);
|
|
19
|
+
if (enable) {
|
|
20
|
+
if (container) container.classList.add("dark");
|
|
21
|
+
document.documentElement.classList.add("dark");
|
|
22
|
+
} else {
|
|
23
|
+
if (container) container.classList.remove("dark");
|
|
24
|
+
document.documentElement.classList.remove("dark");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function getSystemPreference() {
|
|
29
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function applyTheme() {
|
|
33
|
+
if (themeMode === "auto") {
|
|
34
|
+
isDark = getSystemPreference();
|
|
35
|
+
} else {
|
|
36
|
+
isDark = themeMode === "dark";
|
|
37
|
+
}
|
|
38
|
+
setMicdropDarkClass(isDark);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
onMount(() => {
|
|
42
|
+
const savedTheme = localStorage.getItem("theme");
|
|
43
|
+
|
|
44
|
+
if (savedTheme === "dark" || savedTheme === "light") {
|
|
45
|
+
themeMode = savedTheme;
|
|
46
|
+
} else {
|
|
47
|
+
themeMode = "auto";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
applyTheme();
|
|
51
|
+
|
|
52
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
53
|
+
const handleChange = () => {
|
|
54
|
+
if (themeMode === "auto") {
|
|
55
|
+
applyTheme();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
mediaQuery.addEventListener("change", handleChange);
|
|
59
|
+
|
|
60
|
+
return () => {
|
|
61
|
+
mediaQuery.removeEventListener("change", handleChange);
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
function toggleTheme(event: MouseEvent) {
|
|
66
|
+
if (themeMode === "auto") {
|
|
67
|
+
themeMode = "light";
|
|
68
|
+
localStorage.setItem("theme", "light");
|
|
69
|
+
} else if (themeMode === "light") {
|
|
70
|
+
themeMode = "dark";
|
|
71
|
+
localStorage.setItem("theme", "dark");
|
|
72
|
+
} else {
|
|
73
|
+
themeMode = "auto";
|
|
74
|
+
localStorage.removeItem("theme");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
applyTheme();
|
|
78
|
+
|
|
79
|
+
if (event?.currentTarget) {
|
|
80
|
+
(event.currentTarget as HTMLElement).blur();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let titleText = $derived(
|
|
85
|
+
themeMode === "auto"
|
|
86
|
+
? "Auto theme (following device) - click for light mode"
|
|
87
|
+
: themeMode === "light"
|
|
88
|
+
? "Light mode - click for dark mode"
|
|
89
|
+
: "Dark mode - click for auto"
|
|
90
|
+
);
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<Button
|
|
94
|
+
variant="alternative"
|
|
95
|
+
onclick={toggleTheme}
|
|
96
|
+
class="relative h-10 w-10 overflow-hidden p-0"
|
|
97
|
+
aria-label="Toggle theme"
|
|
98
|
+
title={titleText}
|
|
99
|
+
>
|
|
100
|
+
<span
|
|
101
|
+
class="text-amber-500 transition-all duration-300 {themeMode === 'light'
|
|
102
|
+
? 'scale-100 rotate-0 opacity-100'
|
|
103
|
+
: 'pointer-events-none absolute scale-0 rotate-180 opacity-0'}"
|
|
104
|
+
>
|
|
105
|
+
<SunIcon size="20" />
|
|
106
|
+
</span>
|
|
107
|
+
|
|
108
|
+
<span
|
|
109
|
+
class="transition-all duration-300 {themeMode === 'dark'
|
|
110
|
+
? 'scale-100 rotate-0 opacity-100'
|
|
111
|
+
: 'pointer-events-none absolute scale-0 rotate-180 opacity-0'}"
|
|
112
|
+
>
|
|
113
|
+
<MoonIcon size="20" color="white" />
|
|
114
|
+
</span>
|
|
115
|
+
|
|
116
|
+
{#if themeMode === "auto"}
|
|
117
|
+
<div class="absolute inset-0 overflow-hidden rounded-lg">
|
|
118
|
+
<div
|
|
119
|
+
class="absolute flex h-full w-full items-center justify-center bg-white"
|
|
120
|
+
style="clip-path: polygon(0 0, 100% 0, 0 100%)"
|
|
121
|
+
>
|
|
122
|
+
<span class="-translate-x-1 -translate-y-1 text-amber-500">
|
|
123
|
+
<SunIcon size="12" />
|
|
124
|
+
</span>
|
|
125
|
+
</div>
|
|
126
|
+
<div
|
|
127
|
+
class="absolute flex h-full w-full items-center justify-center bg-gray-800"
|
|
128
|
+
style="clip-path: polygon(100% 0, 100% 100%, 0 100%)"
|
|
129
|
+
>
|
|
130
|
+
<span class="translate-x-1 translate-y-1">
|
|
131
|
+
<MoonIcon size="12" color="white" />
|
|
132
|
+
</span>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
{/if}
|
|
136
|
+
</Button>
|
|
@@ -14,52 +14,52 @@ describe('Drawer Component', () => {
|
|
|
14
14
|
document.body.style.overflow = '';
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test('does not render when
|
|
18
|
-
const { container } = render(Drawer, { props: {
|
|
17
|
+
test('does not render when open is false', () => {
|
|
18
|
+
const { container } = render(Drawer, { props: { open: false } });
|
|
19
19
|
expect(container.querySelector('[role="dialog"]')).not.toBeInTheDocument();
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
test('renders when
|
|
23
|
-
const { container } = render(Drawer, { props: {
|
|
22
|
+
test('renders when open is true', () => {
|
|
23
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
24
24
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
test('renders when
|
|
28
|
-
const { container } = render(Drawer, { props: {
|
|
27
|
+
test('renders when open is true (explicit)', () => {
|
|
28
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
29
29
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('has role="dialog" and aria-modal="true"', () => {
|
|
33
|
-
const { container } = render(Drawer, { props: {
|
|
33
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
34
34
|
const dialog = container.querySelector('[role="dialog"]');
|
|
35
35
|
expect(dialog).toHaveAttribute('aria-modal', 'true');
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test('renders title when provided', () => {
|
|
39
|
-
render(Drawer, { props: {
|
|
39
|
+
render(Drawer, { props: { open: true, title: 'Test Drawer', id: 'test-drawer' } });
|
|
40
40
|
expect(screen.getByText('Test Drawer')).toBeInTheDocument();
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
test('applies custom className', () => {
|
|
44
|
-
const { container } = render(Drawer, { props: {
|
|
44
|
+
const { container } = render(Drawer, { props: { open: true, class: 'custom-drawer' } });
|
|
45
45
|
const dialog = container.querySelector('[role="dialog"]');
|
|
46
46
|
expect(dialog).toHaveClass('custom-drawer');
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
test('renders backdrop by default when visible', () => {
|
|
50
|
-
const { container } = render(Drawer, { props: {
|
|
50
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
51
51
|
const backdrop = container.querySelector('[role="presentation"]');
|
|
52
52
|
expect(backdrop).toBeInTheDocument();
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
test('does not render backdrop when backdrop is false', () => {
|
|
56
|
-
const { container } = render(Drawer, { props: {
|
|
56
|
+
const { container } = render(Drawer, { props: { open: true, backdrop: false } });
|
|
57
57
|
const backdrop = container.querySelector('[role="presentation"]');
|
|
58
58
|
expect(backdrop).not.toBeInTheDocument();
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
test('passes through id prop', () => {
|
|
62
|
-
const { container } = render(Drawer, { props: {
|
|
62
|
+
const { container } = render(Drawer, { props: { open: true, id: 'my-drawer' } });
|
|
63
63
|
const dialog = container.querySelector('#my-drawer');
|
|
64
64
|
expect(dialog).toBeInTheDocument();
|
|
65
65
|
});
|
|
@@ -67,25 +67,25 @@ describe('Drawer Component', () => {
|
|
|
67
67
|
|
|
68
68
|
describe('Drawer Placements', () => {
|
|
69
69
|
test('left placement has left-0 class', () => {
|
|
70
|
-
const { container } = render(Drawer, { props: {
|
|
70
|
+
const { container } = render(Drawer, { props: { open: true, placement: 'left' } });
|
|
71
71
|
const dialog = container.querySelector('[role="dialog"]');
|
|
72
72
|
expect(dialog).toHaveClass('left-0');
|
|
73
73
|
});
|
|
74
74
|
|
|
75
75
|
test('right placement has right-0 class', () => {
|
|
76
|
-
const { container } = render(Drawer, { props: {
|
|
76
|
+
const { container } = render(Drawer, { props: { open: true, placement: 'right' } });
|
|
77
77
|
const dialog = container.querySelector('[role="dialog"]');
|
|
78
78
|
expect(dialog).toHaveClass('right-0');
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
test('top placement has top-0 class', () => {
|
|
82
|
-
const { container } = render(Drawer, { props: {
|
|
82
|
+
const { container } = render(Drawer, { props: { open: true, placement: 'top' } });
|
|
83
83
|
const dialog = container.querySelector('[role="dialog"]');
|
|
84
84
|
expect(dialog).toHaveClass('top-0');
|
|
85
85
|
});
|
|
86
86
|
|
|
87
87
|
test('bottom placement has bottom-0 class', () => {
|
|
88
|
-
const { container } = render(Drawer, { props: {
|
|
88
|
+
const { container } = render(Drawer, { props: { open: true, placement: 'bottom' } });
|
|
89
89
|
const dialog = container.querySelector('[role="dialog"]');
|
|
90
90
|
expect(dialog).toHaveClass('bottom-0');
|
|
91
91
|
});
|
|
@@ -93,25 +93,25 @@ describe('Drawer Placements', () => {
|
|
|
93
93
|
|
|
94
94
|
describe('Drawer Widths', () => {
|
|
95
95
|
test('sm width applies w-64', () => {
|
|
96
|
-
const { container } = render(Drawer, { props: {
|
|
96
|
+
const { container } = render(Drawer, { props: { open: true, width: 'sm' } });
|
|
97
97
|
const dialog = container.querySelector('[role="dialog"]');
|
|
98
98
|
expect(dialog).toHaveClass('w-64');
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test('md width applies w-80 (default)', () => {
|
|
102
|
-
const { container } = render(Drawer, { props: {
|
|
102
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
103
103
|
const dialog = container.querySelector('[role="dialog"]');
|
|
104
104
|
expect(dialog).toHaveClass('w-80');
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
test('lg width applies w-96', () => {
|
|
108
|
-
const { container } = render(Drawer, { props: {
|
|
108
|
+
const { container } = render(Drawer, { props: { open: true, width: 'lg' } });
|
|
109
109
|
const dialog = container.querySelector('[role="dialog"]');
|
|
110
110
|
expect(dialog).toHaveClass('w-96');
|
|
111
111
|
});
|
|
112
112
|
|
|
113
113
|
test('full width applies w-full', () => {
|
|
114
|
-
const { container } = render(Drawer, { props: {
|
|
114
|
+
const { container } = render(Drawer, { props: { open: true, width: 'full' } });
|
|
115
115
|
const dialog = container.querySelector('[role="dialog"]');
|
|
116
116
|
expect(dialog).toHaveClass('w-full');
|
|
117
117
|
});
|
|
@@ -119,13 +119,13 @@ describe('Drawer Widths', () => {
|
|
|
119
119
|
|
|
120
120
|
describe('Drawer Accessibility', () => {
|
|
121
121
|
test('has tabindex="-1" for focus management', () => {
|
|
122
|
-
const { container } = render(Drawer, { props: {
|
|
122
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
123
123
|
const dialog = container.querySelector('[role="dialog"]');
|
|
124
124
|
expect(dialog).toHaveAttribute('tabindex', '-1');
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
test('has aria-labelledby when title and id are provided', () => {
|
|
128
|
-
const { container } = render(Drawer, { props: {
|
|
128
|
+
const { container } = render(Drawer, { props: { open: true, title: 'Test', id: 'test-drawer' } });
|
|
129
129
|
const dialog = container.querySelector('[role="dialog"]');
|
|
130
130
|
expect(dialog).toHaveAttribute('aria-labelledby', 'test-drawer-label');
|
|
131
131
|
});
|
|
@@ -133,32 +133,32 @@ describe('Drawer Accessibility', () => {
|
|
|
133
133
|
|
|
134
134
|
describe('Drawer Styling', () => {
|
|
135
135
|
test('has fixed positioning', () => {
|
|
136
|
-
const { container } = render(Drawer, { props: {
|
|
136
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
137
137
|
const dialog = container.querySelector('[role="dialog"]');
|
|
138
138
|
expect(dialog).toHaveClass('fixed');
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
test('has z-40 for stacking', () => {
|
|
142
|
-
const { container } = render(Drawer, { props: {
|
|
142
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
143
143
|
const dialog = container.querySelector('[role="dialog"]');
|
|
144
144
|
expect(dialog).toHaveClass('z-40');
|
|
145
145
|
});
|
|
146
146
|
|
|
147
147
|
test('has flex flex-col layout', () => {
|
|
148
|
-
const { container } = render(Drawer, { props: {
|
|
148
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
149
149
|
const dialog = container.querySelector('[role="dialog"]');
|
|
150
150
|
expect(dialog).toHaveClass('flex');
|
|
151
151
|
expect(dialog).toHaveClass('flex-col');
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
test('has bg-white background', () => {
|
|
155
|
-
const { container } = render(Drawer, { props: {
|
|
155
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
156
156
|
const dialog = container.querySelector('[role="dialog"]');
|
|
157
157
|
expect(dialog).toHaveClass('bg-white');
|
|
158
158
|
});
|
|
159
159
|
|
|
160
160
|
test('has dark mode background', () => {
|
|
161
|
-
const { container } = render(Drawer, { props: {
|
|
161
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
162
162
|
const dialog = container.querySelector('[role="dialog"]');
|
|
163
163
|
expect(dialog).toHaveClass('dark:bg-gray-800');
|
|
164
164
|
});
|
|
@@ -166,13 +166,13 @@ describe('Drawer Styling', () => {
|
|
|
166
166
|
|
|
167
167
|
describe('Drawer Edge Mode', () => {
|
|
168
168
|
test('shows edge trigger when edge=true, placement=bottom, and not visible', () => {
|
|
169
|
-
const { container } = render(Drawer, { props: { edge: true, placement: 'bottom',
|
|
169
|
+
const { container } = render(Drawer, { props: { edge: true, placement: 'bottom', open: false } });
|
|
170
170
|
const edgeTrigger = container.querySelector('.cursor-pointer');
|
|
171
171
|
expect(edgeTrigger).toBeInTheDocument();
|
|
172
172
|
});
|
|
173
173
|
|
|
174
174
|
test('hides edge trigger when drawer is visible', () => {
|
|
175
|
-
const { container } = render(Drawer, { props: { edge: true, placement: 'bottom',
|
|
175
|
+
const { container } = render(Drawer, { props: { edge: true, placement: 'bottom', open: true } });
|
|
176
176
|
// Edge trigger should not be visible when drawer is open
|
|
177
177
|
const edgeTriggers = container.querySelectorAll('.cursor-pointer.fixed');
|
|
178
178
|
// The drawer itself might have cursor classes, so check for the specific edge trigger pattern
|
|
@@ -184,20 +184,20 @@ describe('Drawer Callbacks', () => {
|
|
|
184
184
|
test('onclose prop is accepted', () => {
|
|
185
185
|
const onclose = vi.fn();
|
|
186
186
|
const { container } = render(Drawer, {
|
|
187
|
-
props: {
|
|
187
|
+
props: { open: true, closeOnBackdropClick: true, onclose }
|
|
188
188
|
});
|
|
189
189
|
// Verify drawer renders with onclose callback
|
|
190
190
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
|
191
191
|
});
|
|
192
192
|
|
|
193
193
|
test('closeOnBackdropClick prop defaults to true', () => {
|
|
194
|
-
const { container } = render(Drawer, { props: {
|
|
194
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
195
195
|
// Drawer renders with default closeOnBackdropClick behavior
|
|
196
196
|
expect(container.querySelector('[role="presentation"]')).toBeInTheDocument();
|
|
197
197
|
});
|
|
198
198
|
|
|
199
199
|
test('closeOnEscape prop defaults to true', () => {
|
|
200
|
-
const { container } = render(Drawer, { props: {
|
|
200
|
+
const { container } = render(Drawer, { props: { open: true } });
|
|
201
201
|
// Drawer accepts closeOnEscape prop
|
|
202
202
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
|
203
203
|
});
|
|
@@ -205,7 +205,7 @@ describe('Drawer Callbacks', () => {
|
|
|
205
205
|
test('onopen prop is accepted', () => {
|
|
206
206
|
const onopen = vi.fn();
|
|
207
207
|
const { container } = render(Drawer, {
|
|
208
|
-
props: {
|
|
208
|
+
props: { open: true, onopen }
|
|
209
209
|
});
|
|
210
210
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
|
211
211
|
});
|