@getmicdrop/svelte-components 5.3.2 → 5.3.6

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.
Files changed (93) hide show
  1. package/dist/calendar/Calendar/MiniMonthCalendar.svelte +10 -10
  2. package/dist/calendar/Calendar/MiniMonthCalendar.svelte.d.ts +6 -6
  3. package/dist/calendar/OrderSummary/OrderSummary.svelte +2 -2
  4. package/dist/calendar/OrderSummary/OrderSummary.svelte.d.ts +2 -2
  5. package/dist/calendar/PublicCard/PublicCard.svelte +2 -2
  6. package/dist/calendar/PublicCard/PublicCard.svelte.d.ts +2 -2
  7. package/dist/calendar/ShowCard/ShowCard.svelte +2 -2
  8. package/dist/calendar/ShowCard/ShowCard.svelte.d.ts +2 -2
  9. package/dist/patterns/navigation/Header.svelte +38 -27
  10. package/dist/patterns/page/PageLayout.svelte +1 -1
  11. package/dist/primitives/Accordion/Accordion.stories.svelte +75 -0
  12. package/dist/primitives/Accordion/Accordion.stories.svelte.d.ts +28 -0
  13. package/dist/primitives/Accordion/Accordion.stories.svelte.d.ts.map +1 -0
  14. package/dist/primitives/Alert/Alert.stories.svelte +88 -0
  15. package/dist/primitives/Alert/Alert.stories.svelte.d.ts +28 -0
  16. package/dist/primitives/Alert/Alert.stories.svelte.d.ts.map +1 -0
  17. package/dist/primitives/Avatar/Avatar.stories.svelte +94 -0
  18. package/dist/primitives/Avatar/Avatar.stories.svelte.d.ts +28 -0
  19. package/dist/primitives/Avatar/Avatar.stories.svelte.d.ts.map +1 -0
  20. package/dist/primitives/Breadcrumb/Breadcrumb.svelte +1 -1
  21. package/dist/primitives/Button/Button.svelte +87 -22
  22. package/dist/primitives/Button/Button.svelte.d.ts +4 -0
  23. package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
  24. package/dist/primitives/Checkbox/Checkbox.stories.svelte +84 -0
  25. package/dist/primitives/Checkbox/Checkbox.stories.svelte.d.ts +28 -0
  26. package/dist/primitives/Checkbox/Checkbox.stories.svelte.d.ts.map +1 -0
  27. package/dist/primitives/Drawer/Drawer.stories.svelte +100 -0
  28. package/dist/primitives/Drawer/Drawer.stories.svelte.d.ts +28 -0
  29. package/dist/primitives/Drawer/Drawer.stories.svelte.d.ts.map +1 -0
  30. package/dist/primitives/Dropdown/Dropdown.stories.svelte +137 -0
  31. package/dist/primitives/Dropdown/Dropdown.stories.svelte.d.ts +28 -0
  32. package/dist/primitives/Dropdown/Dropdown.stories.svelte.d.ts.map +1 -0
  33. package/dist/primitives/Dropdown/Dropdown.svelte +13 -15
  34. package/dist/primitives/Dropdown/Dropdown.svelte.d.ts.map +1 -1
  35. package/dist/primitives/Icons/Icon.svelte +2 -1
  36. package/dist/primitives/Icons/Icon.svelte.d.ts.map +1 -1
  37. package/dist/primitives/Input/Select.stories.svelte +112 -0
  38. package/dist/primitives/Input/Select.stories.svelte.d.ts +28 -0
  39. package/dist/primitives/Input/Select.stories.svelte.d.ts.map +1 -0
  40. package/dist/primitives/Input/Textarea.stories.svelte +137 -0
  41. package/dist/primitives/Input/Textarea.stories.svelte.d.ts +28 -0
  42. package/dist/primitives/Input/Textarea.stories.svelte.d.ts.map +1 -0
  43. package/dist/primitives/Pagination/Pagination.stories.svelte +76 -0
  44. package/dist/primitives/Pagination/Pagination.stories.svelte.d.ts +28 -0
  45. package/dist/primitives/Pagination/Pagination.stories.svelte.d.ts.map +1 -0
  46. package/dist/primitives/Pagination/Pagination.svelte +3 -3
  47. package/dist/primitives/Pagination/Pagination.svelte.d.ts +1 -1
  48. package/dist/primitives/Radio/Radio.stories.svelte +80 -0
  49. package/dist/primitives/Radio/Radio.stories.svelte.d.ts +28 -0
  50. package/dist/primitives/Radio/Radio.stories.svelte.d.ts.map +1 -0
  51. package/dist/primitives/Skeleton/Skeleton.stories.svelte +151 -0
  52. package/dist/primitives/Skeleton/Skeleton.stories.svelte.d.ts +28 -0
  53. package/dist/primitives/Skeleton/Skeleton.stories.svelte.d.ts.map +1 -0
  54. package/dist/primitives/Tabs/Tabs.stories.svelte +112 -0
  55. package/dist/primitives/Tabs/Tabs.stories.svelte.d.ts +28 -0
  56. package/dist/primitives/Tabs/Tabs.stories.svelte.d.ts.map +1 -0
  57. package/dist/primitives/Tabs/Tabs.svelte +1 -1
  58. package/dist/primitives/Toggle.svelte +4 -4
  59. package/dist/primitives/ValidationError.spec.js +25 -1
  60. package/dist/primitives/ValidationError.stories.svelte +24 -0
  61. package/dist/primitives/ValidationError.stories.svelte.d.ts.map +1 -1
  62. package/dist/primitives/ValidationError.svelte +8 -4
  63. package/dist/primitives/ValidationError.svelte.d.ts +2 -0
  64. package/dist/primitives/ValidationError.svelte.d.ts.map +1 -1
  65. package/dist/recipes/CropImage/CropImage.svelte +3 -3
  66. package/dist/recipes/SuperLogin/SuperLogin.svelte +34 -23
  67. package/dist/recipes/SuperLogin/SuperLogin.svelte.d.ts.map +1 -1
  68. package/dist/recipes/feedback/EmptyState/EmptyState.svelte +2 -1
  69. package/dist/recipes/feedback/EmptyState/EmptyState.svelte.d.ts.map +1 -1
  70. package/dist/recipes/inputs/MultiSelect.svelte +2 -2
  71. package/dist/recipes/modals/InputModal.svelte +2 -1
  72. package/dist/recipes/modals/InputModal.svelte.d.ts.map +1 -1
  73. package/dist/stories/ComponentConsolidation.stories.svelte +276 -188
  74. package/dist/stories/ComponentConsolidation.stories.svelte.d.ts.map +1 -1
  75. package/dist/stories/PatternsGallery.stories.svelte +19 -0
  76. package/dist/stories/PatternsGallery.stories.svelte.d.ts +28 -0
  77. package/dist/stories/PatternsGallery.stories.svelte.d.ts.map +1 -0
  78. package/dist/stories/PatternsGallery.svelte +388 -0
  79. package/dist/stories/PatternsGallery.svelte.d.ts +4 -0
  80. package/dist/stories/PatternsGallery.svelte.d.ts.map +1 -0
  81. package/dist/stories/PrimitivesGallery.stories.svelte +19 -0
  82. package/dist/stories/PrimitivesGallery.stories.svelte.d.ts +28 -0
  83. package/dist/stories/PrimitivesGallery.stories.svelte.d.ts.map +1 -0
  84. package/dist/stories/PrimitivesGallery.svelte +752 -0
  85. package/dist/stories/PrimitivesGallery.svelte.d.ts +4 -0
  86. package/dist/stories/PrimitivesGallery.svelte.d.ts.map +1 -0
  87. package/dist/stories/RecipesGallery.stories.svelte +19 -0
  88. package/dist/stories/RecipesGallery.stories.svelte.d.ts +28 -0
  89. package/dist/stories/RecipesGallery.stories.svelte.d.ts.map +1 -0
  90. package/dist/stories/RecipesGallery.svelte +441 -0
  91. package/dist/stories/RecipesGallery.svelte.d.ts +4 -0
  92. package/dist/stories/RecipesGallery.svelte.d.ts.map +1 -0
  93. package/package.json +3 -2
@@ -0,0 +1,151 @@
1
+ <script module>
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Skeleton from './Skeleton.svelte';
4
+ import ImagePlaceholder from './ImagePlaceholder.svelte';
5
+ import CardPlaceholder from './CardPlaceholder.svelte';
6
+ import ListPlaceholder from './ListPlaceholder.svelte';
7
+
8
+ const { Story } = defineMeta({
9
+ title: 'Primitives/Skeleton',
10
+ component: Skeleton,
11
+ tags: ['autodocs'],
12
+ parameters: {
13
+ docs: {
14
+ description: {
15
+ component: 'Loading placeholder components that animate while content loads.',
16
+ },
17
+ },
18
+ },
19
+ });
20
+ </script>
21
+
22
+ <Story name="Basic Lines">
23
+ {#snippet template()}
24
+ <div class="space-y-2 max-w-md">
25
+ <Skeleton class="h-4 w-full" />
26
+ <Skeleton class="h-4 w-3/4" />
27
+ <Skeleton class="h-4 w-1/2" />
28
+ </div>
29
+ {/snippet}
30
+ </Story>
31
+
32
+ <Story name="Paragraph">
33
+ {#snippet template()}
34
+ <div class="space-y-3 max-w-lg">
35
+ <Skeleton class="h-6 w-1/3" />
36
+ <div class="space-y-2">
37
+ <Skeleton class="h-4 w-full" />
38
+ <Skeleton class="h-4 w-full" />
39
+ <Skeleton class="h-4 w-5/6" />
40
+ </div>
41
+ </div>
42
+ {/snippet}
43
+ </Story>
44
+
45
+ <Story name="Avatar + Text">
46
+ {#snippet template()}
47
+ <div class="flex items-center gap-4">
48
+ <Skeleton class="h-12 w-12 rounded-full" />
49
+ <div class="space-y-2 flex-1">
50
+ <Skeleton class="h-4 w-32" />
51
+ <Skeleton class="h-3 w-48" />
52
+ </div>
53
+ </div>
54
+ {/snippet}
55
+ </Story>
56
+
57
+ <Story name="Image Placeholder">
58
+ {#snippet template()}
59
+ <div class="max-w-sm">
60
+ <ImagePlaceholder />
61
+ </div>
62
+ {/snippet}
63
+ </Story>
64
+
65
+ <Story name="Card Placeholder">
66
+ {#snippet template()}
67
+ <div class="max-w-sm">
68
+ <CardPlaceholder />
69
+ </div>
70
+ {/snippet}
71
+ </Story>
72
+
73
+ <Story name="List Placeholder">
74
+ {#snippet template()}
75
+ <div class="max-w-md">
76
+ <ListPlaceholder />
77
+ </div>
78
+ {/snippet}
79
+ </Story>
80
+
81
+ <Story name="Grid of Cards">
82
+ {#snippet template()}
83
+ <div class="grid grid-cols-3 gap-4">
84
+ <CardPlaceholder />
85
+ <CardPlaceholder />
86
+ <CardPlaceholder />
87
+ </div>
88
+ {/snippet}
89
+ </Story>
90
+
91
+ <Story name="Page Layout Loading">
92
+ {#snippet template()}
93
+ <div class="space-y-6 max-w-2xl">
94
+ <!-- Header -->
95
+ <div class="flex items-center justify-between">
96
+ <Skeleton class="h-8 w-48" />
97
+ <Skeleton class="h-10 w-24 rounded-lg" />
98
+ </div>
99
+
100
+ <!-- Stats -->
101
+ <div class="grid grid-cols-3 gap-4">
102
+ {#each [1, 2, 3] as _}
103
+ <div class="border rounded-lg p-4">
104
+ <Skeleton class="h-4 w-20 mb-2" />
105
+ <Skeleton class="h-8 w-16" />
106
+ </div>
107
+ {/each}
108
+ </div>
109
+
110
+ <!-- Table -->
111
+ <div class="border rounded-lg">
112
+ <div class="border-b p-4 flex gap-4">
113
+ <Skeleton class="h-4 w-24" />
114
+ <Skeleton class="h-4 w-32" />
115
+ <Skeleton class="h-4 w-20" />
116
+ </div>
117
+ <ListPlaceholder />
118
+ </div>
119
+ </div>
120
+ {/snippet}
121
+ </Story>
122
+
123
+ <Story name="All Variants">
124
+ {#snippet template()}
125
+ <div class="space-y-8">
126
+ <div>
127
+ <h3 class="text-sm font-medium text-gray-700 mb-3">Basic Skeleton</h3>
128
+ <div class="space-y-2 max-w-md">
129
+ <Skeleton class="h-4 w-full" />
130
+ <Skeleton class="h-4 w-3/4" />
131
+ <Skeleton class="h-4 w-1/2" />
132
+ </div>
133
+ </div>
134
+
135
+ <div class="grid grid-cols-3 gap-6">
136
+ <div>
137
+ <h3 class="text-sm font-medium text-gray-700 mb-3">Image Placeholder</h3>
138
+ <ImagePlaceholder />
139
+ </div>
140
+ <div>
141
+ <h3 class="text-sm font-medium text-gray-700 mb-3">Card Placeholder</h3>
142
+ <CardPlaceholder />
143
+ </div>
144
+ <div>
145
+ <h3 class="text-sm font-medium text-gray-700 mb-3">List Placeholder</h3>
146
+ <ListPlaceholder />
147
+ </div>
148
+ </div>
149
+ </div>
150
+ {/snippet}
151
+ </Story>
@@ -0,0 +1,28 @@
1
+ export default Skeleton;
2
+ type Skeleton = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const Skeleton: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ import Skeleton from './Skeleton.svelte';
15
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
16
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
17
+ $$bindings?: Bindings;
18
+ } & Exports;
19
+ (internal: unknown, props: {
20
+ $$events?: Events;
21
+ $$slots?: Slots;
22
+ }): Exports & {
23
+ $set?: any;
24
+ $on?: any;
25
+ };
26
+ z_$$bindings?: Bindings;
27
+ }
28
+ //# sourceMappingURL=Skeleton.stories.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Skeleton.stories.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/primitives/Skeleton/Skeleton.stories.svelte.js"],"names":[],"mappings":";;;;;;;;AAqKA;;;;mBAAoH;qBAjK7F,mBAAmB;6CAwJG,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,112 @@
1
+ <script module>
2
+ import { defineMeta } from '@storybook/addon-svelte-csf';
3
+ import Tabs from './Tabs.svelte';
4
+ import TabItem from './TabItem.svelte';
5
+
6
+ const { Story } = defineMeta({
7
+ title: 'Primitives/Tabs',
8
+ component: Tabs,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component: 'Tabbed content navigation component. Use TabItem children for each tab panel.',
14
+ },
15
+ },
16
+ },
17
+ });
18
+
19
+ let activeTab = $state(0);
20
+ </script>
21
+
22
+ <Story name="Default">
23
+ {#snippet template()}
24
+ <Tabs>
25
+ <TabItem title="Profile">
26
+ <div class="p-4">
27
+ <h3 class="font-medium mb-2">Profile Settings</h3>
28
+ <p class="text-gray-600">Manage your profile information and preferences.</p>
29
+ </div>
30
+ </TabItem>
31
+ <TabItem title="Account">
32
+ <div class="p-4">
33
+ <h3 class="font-medium mb-2">Account Settings</h3>
34
+ <p class="text-gray-600">Manage your account security and billing.</p>
35
+ </div>
36
+ </TabItem>
37
+ <TabItem title="Notifications">
38
+ <div class="p-4">
39
+ <h3 class="font-medium mb-2">Notification Settings</h3>
40
+ <p class="text-gray-600">Configure how you receive notifications.</p>
41
+ </div>
42
+ </TabItem>
43
+ </Tabs>
44
+ {/snippet}
45
+ </Story>
46
+
47
+ <Story name="Controlled">
48
+ {#snippet template()}
49
+ <div>
50
+ <p class="text-sm text-gray-500 mb-4">Active tab: {activeTab}</p>
51
+ <Tabs bind:activeTab={activeTab}>
52
+ <TabItem title="Tab 1">
53
+ <div class="p-4">Content for Tab 1</div>
54
+ </TabItem>
55
+ <TabItem title="Tab 2">
56
+ <div class="p-4">Content for Tab 2</div>
57
+ </TabItem>
58
+ <TabItem title="Tab 3">
59
+ <div class="p-4">Content for Tab 3</div>
60
+ </TabItem>
61
+ </Tabs>
62
+ <div class="mt-4 flex gap-2">
63
+ <button
64
+ class="px-3 py-1 bg-gray-200 rounded text-sm"
65
+ onclick={() => activeTab = 0}
66
+ >Go to Tab 1</button>
67
+ <button
68
+ class="px-3 py-1 bg-gray-200 rounded text-sm"
69
+ onclick={() => activeTab = 2}
70
+ >Go to Tab 3</button>
71
+ </div>
72
+ </div>
73
+ {/snippet}
74
+ </Story>
75
+
76
+ <Story name="With Icons">
77
+ {#snippet template()}
78
+ <Tabs>
79
+ <TabItem title="🏠 Home">
80
+ <div class="p-4">Home tab content</div>
81
+ </TabItem>
82
+ <TabItem title="⚙️ Settings">
83
+ <div class="p-4">Settings tab content</div>
84
+ </TabItem>
85
+ <TabItem title="👤 Profile">
86
+ <div class="p-4">Profile tab content</div>
87
+ </TabItem>
88
+ </Tabs>
89
+ {/snippet}
90
+ </Story>
91
+
92
+ <Story name="Many Tabs">
93
+ {#snippet template()}
94
+ <Tabs>
95
+ <TabItem title="Overview">
96
+ <div class="p-4">Overview content</div>
97
+ </TabItem>
98
+ <TabItem title="Analytics">
99
+ <div class="p-4">Analytics content</div>
100
+ </TabItem>
101
+ <TabItem title="Reports">
102
+ <div class="p-4">Reports content</div>
103
+ </TabItem>
104
+ <TabItem title="Notifications">
105
+ <div class="p-4">Notifications content</div>
106
+ </TabItem>
107
+ <TabItem title="Settings">
108
+ <div class="p-4">Settings content</div>
109
+ </TabItem>
110
+ </Tabs>
111
+ {/snippet}
112
+ </Story>
@@ -0,0 +1,28 @@
1
+ export default Tabs;
2
+ type Tabs = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const Tabs: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ import Tabs from './Tabs.svelte';
15
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
16
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
17
+ $$bindings?: Bindings;
18
+ } & Exports;
19
+ (internal: unknown, props: {
20
+ $$events?: Events;
21
+ $$slots?: Slots;
22
+ }): Exports & {
23
+ $set?: any;
24
+ $on?: any;
25
+ };
26
+ z_$$bindings?: Bindings;
27
+ }
28
+ //# sourceMappingURL=Tabs.stories.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tabs.stories.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/primitives/Tabs/Tabs.stories.svelte.js"],"names":[],"mappings":";;;;;;;;AAwHA;;;;mBAAgH;iBApH7F,eAAe;6CA2GW,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,eAAe,QAAQ,CAAC"}
@@ -81,7 +81,7 @@
81
81
 
82
82
  // Tab button classes by style
83
83
  function getTabClasses(isActive: boolean) {
84
- const base = "inline-flex items-center justify-center whitespace-nowrap transition-colors focus:outline-none focus:ring-4 focus:ring-blue-300 dark:focus:ring-blue-800";
84
+ const base = "inline-flex items-center justify-center whitespace-nowrap transition-colors focus:outline-none";
85
85
 
86
86
  switch (tabStyle) {
87
87
  case 'underline':
@@ -28,21 +28,21 @@
28
28
  onchange?.({ checked });
29
29
  }
30
30
 
31
- // Flowbite toggle sizes
31
+ // Flowbite toggle sizes - thumb uses after: pseudo-element
32
32
  const sizes = {
33
33
  sm: {
34
34
  track: 'w-9 h-5',
35
- thumb: 'h-4 w-4 after:top-0.5 after:start-0.5',
35
+ thumb: 'after:h-4 after:w-4 after:top-0.5 after:start-0.5',
36
36
  translate: 'peer-checked:after:translate-x-full'
37
37
  },
38
38
  md: {
39
39
  track: 'w-11 h-6',
40
- thumb: 'h-5 w-5 after:top-0.5 after:start-0.5',
40
+ thumb: 'after:h-5 after:w-5 after:top-0.5 after:start-0.5',
41
41
  translate: 'peer-checked:after:translate-x-full'
42
42
  },
43
43
  lg: {
44
44
  track: 'w-14 h-7',
45
- thumb: 'h-6 w-6 after:top-0.5 after:start-1',
45
+ thumb: 'after:h-6 after:w-6 after:top-0.5 after:start-0.5',
46
46
  translate: 'peer-checked:after:translate-x-full'
47
47
  }
48
48
  };
@@ -74,6 +74,30 @@ describe('ValidationError Component', () => {
74
74
  });
75
75
  const alert = container.querySelector('[role="alert"]');
76
76
  expect(alert.classList.contains('flex')).toBe(true);
77
- expect(alert.classList.contains('items-center')).toBe(true);
77
+ expect(alert.classList.contains('items-start')).toBe(true);
78
+ });
79
+
80
+ it('has aria-live="assertive" for screen reader announcements', () => {
81
+ const { container } = render(ValidationError, {
82
+ props: { error: 'Error message' },
83
+ });
84
+ const alert = container.querySelector('[role="alert"]');
85
+ expect(alert.getAttribute('aria-live')).toBe('assertive');
86
+ });
87
+
88
+ it('renders with id when provided', () => {
89
+ const { container } = render(ValidationError, {
90
+ props: { error: 'Error message', id: 'my-error-id' },
91
+ });
92
+ const alert = container.querySelector('[role="alert"]');
93
+ expect(alert.getAttribute('id')).toBe('my-error-id');
94
+ });
95
+
96
+ it('does not render id when not provided', () => {
97
+ const { container } = render(ValidationError, {
98
+ props: { error: 'Error message' },
99
+ });
100
+ const alert = container.querySelector('[role="alert"]');
101
+ expect(alert.getAttribute('id')).toBeFalsy();
78
102
  });
79
103
  });
@@ -10,6 +10,7 @@
10
10
  argTypes: {
11
11
  error: { control: 'text' },
12
12
  show: { control: 'boolean' },
13
+ id: { control: 'text' },
13
14
  },
14
15
  });
15
16
 
@@ -85,3 +86,26 @@
85
86
  <p class="text-sm text-gray-500 dark:text-gray-400 mt-2">Validation error is hidden until field is touched</p>
86
87
  </div>
87
88
  </Story>
89
+
90
+ <Story name="Accessible with aria-describedby">
91
+ <div class="max-w-md">
92
+ <label for="accessible-email" class="block text-sm font-medium mb-1">Email Address</label>
93
+ <input
94
+ id="accessible-email"
95
+ type="email"
96
+ aria-describedby="email-error"
97
+ aria-invalid="true"
98
+ class="w-full px-3 py-2 border border-red-300 rounded focus:ring-red-500 focus:border-red-500"
99
+ value="invalid-email"
100
+ />
101
+ <ValidationError
102
+ id="email-error"
103
+ error="Please enter a valid email address"
104
+ show={true}
105
+ />
106
+ <p class="text-sm text-gray-500 mt-4">
107
+ This example shows proper accessibility: the input references the error via aria-describedby,
108
+ and the error has aria-live="assertive" for screen reader announcements.
109
+ </p>
110
+ </div>
111
+ </Story>
@@ -1 +1 @@
1
- {"version":3,"file":"ValidationError.stories.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/primitives/ValidationError.stories.svelte.js"],"names":[],"mappings":";;;;;;;;AAyFA;;;;mBAA2H;4BApF7F,0BAA0B;6CA2EX,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"ValidationError.stories.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/primitives/ValidationError.stories.svelte.js"],"names":[],"mappings":";;;;;;;;AAsGA;;;;mBAA2H;4BAjG7F,0BAA0B;6CAwFX,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,OAAO,OAAO,QAAQ;IAC3L,cAAc,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,WAAW,OAAO,SAAS;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,eAAe,QAAQ,CAAC"}
@@ -8,18 +8,22 @@
8
8
  error?: string;
9
9
  /** Whether to show the error */
10
10
  show?: boolean;
11
+ /** Optional ID for aria-describedby linking from input fields */
12
+ id?: string;
11
13
  }
12
14
 
13
- let { error = '', show = true }: Props = $props();
15
+ let { error = '', show = true, id }: Props = $props();
14
16
  </script>
15
17
 
16
18
  {#if error && show}
17
19
  <div
18
20
  transition:slide={{ duration: 300, easing: cubicOut }}
19
- class="flex items-center gap-1.5 text-red-600 dark:text-red-500 mt-2"
21
+ class="flex items-start gap-1.5 text-red-600 dark:text-red-500 mt-2"
20
22
  role="alert"
23
+ aria-live="assertive"
24
+ {id}
21
25
  >
22
- <WarningIcon className="shrink-0" />
23
- <p class="text-sm font-medium">{error}</p>
26
+ <WarningIcon className="shrink-0 mt-[1px]" />
27
+ <p class="text-sm leading-tight m-0">{error}</p>
24
28
  </div>
25
29
  {/if}
@@ -3,6 +3,8 @@ interface Props {
3
3
  error?: string;
4
4
  /** Whether to show the error */
5
5
  show?: boolean;
6
+ /** Optional ID for aria-describedby linking from input fields */
7
+ id?: string;
6
8
  }
7
9
  declare const ValidationError: import("svelte").Component<Props, {}, "">;
8
10
  type ValidationError = ReturnType<typeof ValidationError>;
@@ -1 +1 @@
1
- {"version":3,"file":"ValidationError.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/primitives/ValidationError.svelte.ts"],"names":[],"mappings":"AAQE,UAAU,KAAK;IACb,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAmBH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"ValidationError.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/primitives/ValidationError.svelte.ts"],"names":[],"mappings":"AAQE,UAAU,KAAK;IACb,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iEAAiE;IACjE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAmBH,QAAA,MAAM,eAAe,2CAAwC,CAAC;AAC9D,KAAK,eAAe,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC1D,eAAe,eAAe,CAAC"}
@@ -39,8 +39,8 @@
39
39
  }
40
40
  });
41
41
 
42
- function handleCropComplete(e: CustomEvent<{ pixels: { x: number; y: number; width: number; height: number } }>) {
43
- croppedAreaPixels = e.detail.pixels;
42
+ function handleCropComplete(e: { pixels: { x: number; y: number; width: number; height: number } }) {
43
+ croppedAreaPixels = e.pixels;
44
44
  isLoading = false;
45
45
  }
46
46
 
@@ -161,7 +161,7 @@
161
161
  minZoom={1}
162
162
  maxZoom={3}
163
163
  showGrid={true}
164
- on:cropcomplete={handleCropComplete}
164
+ onCropComplete={handleCropComplete}
165
165
  />
166
166
  </div>
167
167
 
@@ -690,15 +690,14 @@
690
690
 
691
691
  <!-- Password field - slides between slot 2 and slot 3 -->
692
692
  <div class="password-field-container">
693
- <div class="mb-2">
693
+ <div class="mb-2 password-field-wrapper">
694
694
  <div class="flex justify-between items-center mb-2">
695
695
  <label
696
696
  for="password"
697
697
  class="block text-sm font-medium text-gray-900 dark:text-white"
698
698
  >Password</label>
699
- <Button variant="link" onclick={() => { view = "reset"; }}>
700
- Forgot your password?
701
- </Button>
699
+ <!-- Placeholder to maintain layout - actual button is after input for tab order -->
700
+ <span class="forgot-password-placeholder"></span>
702
701
  </div>
703
702
  <Input
704
703
  id="password"
@@ -707,6 +706,10 @@
707
706
  type="password"
708
707
  autocomplete="current-password"
709
708
  />
709
+ <!-- Forgot password button: after input in DOM for correct tab order, positioned visually in label row -->
710
+ <Button variant="link" type="button" class="forgot-password-btn" onclick={() => { view = "reset"; }}>
711
+ Forgot your password?
712
+ </Button>
710
713
  </div>
711
714
  </div>
712
715
 
@@ -788,8 +791,10 @@
788
791
 
789
792
  <div class="space-y-3">
790
793
  {#each accounts as account}
791
- <button
792
- class="w-full flex items-center p-4 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-left group"
794
+ <Button
795
+ variant="card"
796
+ size="md"
797
+ class="group"
793
798
  onclick={() => handleAccountSelectInternal(account)}
794
799
  >
795
800
  <div
@@ -837,7 +842,7 @@
837
842
  />
838
843
  </svg>
839
844
  </div>
840
- </button>
845
+ </Button>
841
846
  {/each}
842
847
  </div>
843
848
 
@@ -1088,12 +1093,10 @@
1088
1093
  > if it is an email on file.
1089
1094
  </p>
1090
1095
  <p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed text-left">
1091
- Please check again. If you still haven't received an email, <button
1092
- type="button"
1093
- class="text-blue-600 font-medium dark:text-blue-400"
1096
+ Please check again. If you still haven't received an email, <Button
1097
+ variant="link"
1094
1098
  onclick={handleTryDifferentEmail}
1095
- >try a different email</button
1096
- >.
1099
+ >try a different email</Button>.
1097
1100
  </p>
1098
1101
  {:else}
1099
1102
  <p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed text-left">
@@ -1108,17 +1111,8 @@
1108
1111
  </p>
1109
1112
  <p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed text-left">
1110
1113
  If you haven't received an email in 5 minutes, check your
1111
- spam, <button
1112
- type="button"
1113
- class="text-blue-600 font-medium dark:text-blue-400"
1114
- onclick={handleResend}>resend</button
1115
- >, or
1116
- <button
1117
- type="button"
1118
- class="text-blue-600 font-medium dark:text-blue-400"
1119
- onclick={handleTryDifferentEmail}
1120
- >try a different email</button
1121
- >.
1114
+ spam, <Button variant="link" onclick={handleResend}>resend</Button>, or
1115
+ <Button variant="link" onclick={handleTryDifferentEmail}>try a different email</Button>.
1122
1116
  </p>
1123
1117
  {/if}
1124
1118
  </div>
@@ -1211,6 +1205,23 @@
1211
1205
  margin-bottom: 0;
1212
1206
  }
1213
1207
 
1208
+ /* Password field tab order fix: button after input in DOM, positioned visually in label row */
1209
+ .password-field-wrapper {
1210
+ position: relative;
1211
+ }
1212
+
1213
+ .password-field-wrapper :global(.forgot-password-btn) {
1214
+ position: absolute;
1215
+ top: 0;
1216
+ right: 0;
1217
+ }
1218
+
1219
+ .forgot-password-placeholder {
1220
+ /* Invisible placeholder to maintain label row height */
1221
+ display: inline-block;
1222
+ height: 1em;
1223
+ }
1224
+
1214
1225
  /* Card fade-in animation */
1215
1226
  .card-hidden {
1216
1227
  opacity: 0;
@@ -1 +1 @@
1
- {"version":3,"file":"SuperLogin.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/recipes/SuperLogin/SuperLogin.svelte.js"],"names":[],"mappings":";;;;;AAy9BA;iBA76BkC,MAAM;cAAY,MAAM;cAAY,MAAM;kBAAgB,MAAM;kBAAgB,OAAO;gBAAc,MAAM;gBAAc,MAAM;iBAAe,MAAM;0BAAwB,MAAM;wBAAsB,MAAM;aAAW,MAAM;;;;;yBAAoI,OAAO;mBAAiB,MAAM;WA66B1W;wBA76BtC;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,WAAW;IAAC,eAAe,CAAC,WAAW;IAAC,UAAU,CAAC,WAAW;IAAC,kBAAkB,CAAC,WAAW;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE"}
1
+ {"version":3,"file":"SuperLogin.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/recipes/SuperLogin/SuperLogin.svelte.js"],"names":[],"mappings":";;;;;AA49BA;iBAh7BkC,MAAM;cAAY,MAAM;cAAY,MAAM;kBAAgB,MAAM;kBAAgB,OAAO;gBAAc,MAAM;gBAAc,MAAM;iBAAe,MAAM;0BAAwB,MAAM;wBAAsB,MAAM;aAAW,MAAM;;;;;yBAAoI,OAAO;mBAAiB,MAAM;WAg7B1W;wBAh7BtC;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,WAAW;IAAC,eAAe,CAAC,WAAW;IAAC,UAAU,CAAC,WAAW;IAAC,kBAAkB,CAAC,WAAW;IAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE"}
@@ -32,7 +32,8 @@
32
32
  <div class="flex flex-col items-center justify-center px-6 py-10 text-center {className}">
33
33
  {#if icon || imageSrc}
34
34
  {#if iconType === 'component' && icon}
35
- <svelte:component this={icon} class="mb-3 text-gray-400 dark:text-gray-500 {iconSize}" />
35
+ {@const IconComponent = icon}
36
+ <IconComponent class="mb-3 text-gray-400 dark:text-gray-500 {iconSize}" />
36
37
  {:else if iconType === 'image' && imageSrc}
37
38
  <img src={imageSrc} alt="" class="mb-3 {iconSize}" />
38
39
  {/if}
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/recipes/feedback/EmptyState/EmptyState.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGtC,UAAU,KAAK;IACb,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IACjC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAiCH,QAAA,MAAM,UAAU,0BAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"EmptyState.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/recipes/feedback/EmptyState/EmptyState.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGtC,UAAU,KAAK;IACb,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,IAAI,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IACjC,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkCH,QAAA,MAAM,UAAU,0BAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -165,8 +165,8 @@
165
165
  {#if hasSelection}
166
166
  <div class="flex flex-wrap gap-1.5">
167
167
  {#each selectedItems as item}
168
- <span class="inline-flex items-center px-2 py-1 text-sm font-medium text-blue-800 bg-blue-100 rounded dark:bg-blue-900 dark:text-blue-300">
169
- <span class="overflow-hidden text-ellipsis whitespace-nowrap">{item.name}</span>
168
+ <span class="inline-flex items-center px-2 py-1 text-sm font-medium bg-blue-100 rounded dark:bg-blue-900">
169
+ <span class="overflow-hidden text-ellipsis whitespace-nowrap text-gray-900 dark:text-white" style="color-scheme: light dark;">{item.name}</span>
170
170
  <button
171
171
  type="button"
172
172
  class="inline-flex items-center p-0.5 ms-1.5 text-sm text-blue-400 bg-transparent rounded-sm hover:bg-blue-200 hover:text-blue-900 dark:hover:bg-blue-800 dark:hover:text-blue-300"