@marianmeres/stuic 2.65.0 → 3.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.
Files changed (171) hide show
  1. package/README.md +292 -4
  2. package/dist/README.md +41 -18
  3. package/dist/actions/popover/README.md +19 -0
  4. package/dist/actions/popover/index.css +6 -9
  5. package/dist/actions/popover/popover.svelte.js +2 -2
  6. package/dist/actions/tooltip/README.md +18 -0
  7. package/dist/actions/tooltip/index.css +5 -8
  8. package/dist/actions/tooltip/tooltip.svelte.js +1 -1
  9. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +9 -10
  10. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +3 -3
  11. package/dist/components/AlertConfirmPrompt/Current.svelte +15 -17
  12. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +5 -3
  13. package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
  14. package/dist/components/AlertConfirmPrompt/index.css +62 -0
  15. package/dist/components/AssetsPreview/AssetsPreview.svelte +92 -73
  16. package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +1 -0
  17. package/dist/components/AssetsPreview/index.css +59 -0
  18. package/dist/components/Avatar/Avatar.svelte +32 -18
  19. package/dist/components/Avatar/Avatar.svelte.d.ts +1 -0
  20. package/dist/components/Avatar/README.md +166 -0
  21. package/dist/components/Avatar/index.css +128 -0
  22. package/dist/components/Backdrop/Backdrop.svelte +8 -2
  23. package/dist/components/Backdrop/Backdrop.svelte.d.ts +1 -0
  24. package/dist/components/Backdrop/README.md +71 -6
  25. package/dist/components/Backdrop/index.css +29 -0
  26. package/dist/components/Button/Button.svelte +117 -124
  27. package/dist/components/Button/Button.svelte.d.ts +35 -23
  28. package/dist/components/Button/README.md +87 -21
  29. package/dist/components/Button/index.css +473 -9
  30. package/dist/components/Button/index.d.ts +1 -1
  31. package/dist/components/Button/index.js +1 -1
  32. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -38
  33. package/dist/components/ButtonGroupRadio/README.md +82 -4
  34. package/dist/components/ButtonGroupRadio/index.css +152 -14
  35. package/dist/components/Collapsible/Collapsible.svelte +7 -7
  36. package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
  37. package/dist/components/Collapsible/README.md +34 -2
  38. package/dist/components/Collapsible/index.css +38 -0
  39. package/dist/components/CommandMenu/CommandMenu.svelte +13 -24
  40. package/dist/components/CommandMenu/README.md +39 -0
  41. package/dist/components/CommandMenu/index.css +45 -2
  42. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -50
  43. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -5
  44. package/dist/components/DismissibleMessage/README.md +93 -11
  45. package/dist/components/DismissibleMessage/index.css +122 -8
  46. package/dist/components/DismissibleMessage/index.d.ts +1 -1
  47. package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -50
  48. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -6
  49. package/dist/components/DropdownMenu/README.md +132 -0
  50. package/dist/components/DropdownMenu/index.css +231 -27
  51. package/dist/components/Input/FieldAssets.svelte +8 -5
  52. package/dist/components/Input/FieldCheckbox.svelte +7 -44
  53. package/dist/components/Input/FieldFile.svelte +1 -6
  54. package/dist/components/Input/FieldInput.svelte +1 -1
  55. package/dist/components/Input/FieldOptions.svelte +41 -38
  56. package/dist/components/Input/FieldRadios.svelte +7 -16
  57. package/dist/components/Input/FieldSelect.svelte +1 -1
  58. package/dist/components/Input/FieldSwitch.svelte +1 -5
  59. package/dist/components/Input/FieldTextarea.svelte +1 -1
  60. package/dist/components/Input/README.md +194 -0
  61. package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
  62. package/dist/components/Input/_internal/InputWrap.svelte +8 -48
  63. package/dist/components/Input/index.css +522 -127
  64. package/dist/components/ListItemButton/ListItemButton.svelte +37 -73
  65. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -9
  66. package/dist/components/ListItemButton/README.md +100 -45
  67. package/dist/components/ListItemButton/index.css +175 -56
  68. package/dist/components/ListItemButton/index.d.ts +1 -1
  69. package/dist/components/ListItemButton/index.js +1 -1
  70. package/dist/components/Modal/Modal.svelte +2 -8
  71. package/dist/components/Modal/Modal.svelte.d.ts +1 -0
  72. package/dist/components/Modal/README.md +29 -0
  73. package/dist/components/Modal/index.css +36 -0
  74. package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
  75. package/dist/components/ModalDialog/README.md +35 -0
  76. package/dist/components/ModalDialog/index.css +57 -0
  77. package/dist/components/Notifications/Notifications.svelte +44 -128
  78. package/dist/components/Notifications/Notifications.svelte.d.ts +9 -17
  79. package/dist/components/Notifications/README.md +186 -70
  80. package/dist/components/Notifications/index.css +212 -15
  81. package/dist/components/Progress/README.md +15 -0
  82. package/dist/components/Progress/_internal/Bar.svelte +2 -2
  83. package/dist/components/Progress/index.css +4 -4
  84. package/dist/components/Skeleton/Skeleton.svelte +3 -2
  85. package/dist/components/Skeleton/index.css +11 -14
  86. package/dist/components/Spinner/Spinner.svelte +2 -2
  87. package/dist/components/Spinner/SpinnerCircle.svelte +1 -1
  88. package/dist/components/Switch/README.md +15 -0
  89. package/dist/components/Switch/Switch.svelte +4 -7
  90. package/dist/components/Switch/Switch.svelte.d.ts +1 -1
  91. package/dist/components/Switch/SwitchButton.svelte +4 -5
  92. package/dist/components/Switch/index.css +3 -4
  93. package/dist/components/TabbedMenu/README.md +26 -21
  94. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -5
  95. package/dist/components/TabbedMenu/index.css +7 -22
  96. package/dist/components/ThemePreview/README.md +289 -0
  97. package/dist/components/ThemePreview/ThemePreview.svelte +341 -0
  98. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +33 -0
  99. package/dist/components/ThemePreview/index.css +493 -0
  100. package/dist/components/ThemePreview/index.d.ts +1 -0
  101. package/dist/components/ThemePreview/index.js +1 -0
  102. package/dist/components/TwCheck/TwCheck.svelte +4 -4
  103. package/dist/components/TwCheck/index.css +3 -2
  104. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +1 -1
  105. package/dist/components/X/X.svelte +16 -4
  106. package/dist/components/X/X.svelte.d.ts +1 -0
  107. package/dist/icons/index.d.ts +1 -0
  108. package/dist/icons/index.js +1 -0
  109. package/dist/index.css +31 -16
  110. package/dist/index.d.ts +1 -0
  111. package/dist/index.js +1 -0
  112. package/dist/themes/blue-orange.css +163 -0
  113. package/dist/themes/blue-orange.d.ts +6 -0
  114. package/dist/themes/blue-orange.js +151 -0
  115. package/dist/themes/cyan-red.css +163 -0
  116. package/dist/themes/cyan-red.d.ts +6 -0
  117. package/dist/themes/cyan-red.js +151 -0
  118. package/dist/themes/cyan-slate.css +163 -0
  119. package/dist/themes/cyan-slate.d.ts +6 -0
  120. package/dist/themes/cyan-slate.js +151 -0
  121. package/dist/themes/emerald-pink.css +163 -0
  122. package/dist/themes/emerald-pink.d.ts +6 -0
  123. package/dist/themes/emerald-pink.js +151 -0
  124. package/dist/themes/fuchsia-emerald.css +163 -0
  125. package/dist/themes/fuchsia-emerald.d.ts +6 -0
  126. package/dist/themes/fuchsia-emerald.js +151 -0
  127. package/dist/themes/gray.css +163 -0
  128. package/dist/themes/gray.d.ts +6 -0
  129. package/dist/themes/gray.js +151 -0
  130. package/dist/themes/indigo-amber.css +163 -0
  131. package/dist/themes/indigo-amber.d.ts +6 -0
  132. package/dist/themes/indigo-amber.js +151 -0
  133. package/dist/themes/neutral.css +163 -0
  134. package/dist/themes/neutral.d.ts +6 -0
  135. package/dist/themes/neutral.js +151 -0
  136. package/dist/themes/pink-emerald.css +163 -0
  137. package/dist/themes/pink-emerald.d.ts +6 -0
  138. package/dist/themes/pink-emerald.js +151 -0
  139. package/dist/themes/purple-yellow.css +163 -0
  140. package/dist/themes/purple-yellow.d.ts +6 -0
  141. package/dist/themes/purple-yellow.js +151 -0
  142. package/dist/themes/rainbow.css +163 -0
  143. package/dist/themes/rainbow.d.ts +6 -0
  144. package/dist/themes/rainbow.js +156 -0
  145. package/dist/themes/red-blue.css +163 -0
  146. package/dist/themes/red-blue.d.ts +6 -0
  147. package/dist/themes/red-blue.js +151 -0
  148. package/dist/themes/red-cyan.css +163 -0
  149. package/dist/themes/red-cyan.d.ts +6 -0
  150. package/dist/themes/red-cyan.js +151 -0
  151. package/dist/themes/rose-teal.css +163 -0
  152. package/dist/themes/rose-teal.d.ts +6 -0
  153. package/dist/themes/rose-teal.js +151 -0
  154. package/dist/themes/sky-amber.css +163 -0
  155. package/dist/themes/sky-amber.d.ts +6 -0
  156. package/dist/themes/sky-amber.js +151 -0
  157. package/dist/themes/slate-cyan.css +163 -0
  158. package/dist/themes/slate-cyan.d.ts +6 -0
  159. package/dist/themes/slate-cyan.js +151 -0
  160. package/dist/themes/tailwind-color-pairs.md +31 -0
  161. package/dist/themes/teal-rose.css +163 -0
  162. package/dist/themes/teal-rose.d.ts +6 -0
  163. package/dist/themes/teal-rose.js +151 -0
  164. package/dist/themes/violet-lime.css +163 -0
  165. package/dist/themes/violet-lime.d.ts +6 -0
  166. package/dist/themes/violet-lime.js +151 -0
  167. package/dist/utils/design-tokens.d.ts +43 -0
  168. package/dist/utils/design-tokens.js +100 -0
  169. package/dist/utils/index.d.ts +1 -0
  170. package/dist/utils/index.js +1 -0
  171. package/package.json +22 -2
@@ -1,60 +1,6 @@
1
1
  # Notifications
2
2
 
3
- A toast notification system with auto-disposal, deduplication, progress indicators, and flexible positioning.
4
-
5
- ## Props
6
-
7
- | Prop | Type | Default | Description |
8
- |------|------|---------|-------------|
9
- | `notifications` | `NotificationsStack` | - | Stack instance (required) |
10
- | `posX` | `"left" \| "center" \| "right"` | `"right"` | Horizontal position (desktop) |
11
- | `posY` | `"top" \| "center" \| "bottom"` | `"top"` | Vertical position (desktop) |
12
- | `posXMobile` | `"left" \| "center" \| "right"` | `"center"` | Horizontal position (mobile) |
13
- | `posYMobile` | `"top" \| "center" \| "bottom"` | `"top"` | Vertical position (mobile) |
14
- | `themeInfo` | `TW_COLORS` | `"neutral"` | Color theme for info notifications |
15
- | `themeError` | `TW_COLORS` | `"red"` | Color theme for error notifications |
16
- | `themeWarn` | `TW_COLORS` | `"yellow"` | Color theme for warning notifications |
17
- | `themeSuccess` | `TW_COLORS` | `"green"` | Color theme for success notifications |
18
- | `noTheme` | `boolean` | `false` | Disable color theming |
19
- | `noIcons` | `boolean` | `false` | Hide notification icons |
20
- | `noProgress` | `boolean` | `false` | Hide TTL progress bar |
21
- | `noXButton` | `boolean` | `false` | Hide close button |
22
- | `duration` | `number` | `200` | Fade transition duration (ms) |
23
- | `forceAsHtml` | `boolean` | - | Render content as HTML |
24
- | `iconFns` | `Record<type, () => string>` | - | Custom icon functions |
25
-
26
- ## NotificationsStack API
27
-
28
- ### Constructor Options
29
-
30
- | Option | Type | Default | Description |
31
- |--------|------|---------|-------------|
32
- | `maxCapacity` | `number` | `5` | Maximum notifications in queue |
33
- | `defaultTtl` | `number` | `3000` | Default time-to-live (ms) |
34
- | `extraTtlPerChar` | `number` | `20` | Extra TTL per content character |
35
- | `sortOrder` | `"asc" \| "desc"` | `"asc"` | Stack sort order |
36
- | `disposeInterval` | `number` | `500` | Auto-dispose check interval (ms) |
37
-
38
- ### Methods
39
-
40
- | Method | Description |
41
- |--------|-------------|
42
- | `info(content, opts?)` | Add info notification |
43
- | `success(content, opts?)` | Add success notification |
44
- | `warn(content, opts?)` | Add warning notification |
45
- | `error(content, opts?)` | Add error notification |
46
- | `removeById(id)` | Remove notification by ID |
47
- | `reset()` | Clear all notifications |
48
- | `destroy()` | Cleanup and stop ticker |
49
-
50
- ### Notification Options
51
-
52
- | Option | Type | Description |
53
- |--------|------|-------------|
54
- | `id` | `string \| number` | Unique ID (auto-generated from content if omitted) |
55
- | `ttl` | `number` | Time-to-live in ms (0 = no auto-dismiss) |
56
- | `iconFn` | `(() => string) \| false` | Custom icon or `false` to hide |
57
- | `forceAsHtml` | `boolean` | Render content as HTML |
3
+ A toast notification system with automatic stacking, progress indicators, and type-based theming using design tokens.
58
4
 
59
5
  ## Usage
60
6
 
@@ -62,7 +8,7 @@ A toast notification system with auto-disposal, deduplication, progress indicato
62
8
 
63
9
  ```svelte
64
10
  <script lang="ts">
65
- import { Notifications, NotificationsStack } from 'stuic';
11
+ import { Notifications, NotificationsStack } from '@marianmeres/stuic';
66
12
 
67
13
  const notifications = new NotificationsStack();
68
14
  </script>
@@ -70,11 +16,11 @@ A toast notification system with auto-disposal, deduplication, progress indicato
70
16
  <Notifications {notifications} />
71
17
 
72
18
  <button onclick={() => notifications.info('Hello!')}>
73
- Show Info
19
+ Show notification
74
20
  </button>
75
21
  ```
76
22
 
77
- ### Different Types
23
+ ### Notification Types
78
24
 
79
25
  ```svelte
80
26
  <script lang="ts">
@@ -85,14 +31,14 @@ A toast notification system with auto-disposal, deduplication, progress indicato
85
31
  </script>
86
32
  ```
87
33
 
88
- ### Custom TTL
34
+ ### Custom TTL (Time to Live)
89
35
 
90
36
  ```svelte
91
37
  <script lang="ts">
92
38
  // Auto-dismiss after 10 seconds
93
- notifications.info('Long message', { ttl: 10000 });
39
+ notifications.info('Long notification', { ttl: 10000 });
94
40
 
95
- // Never auto-dismiss
41
+ // No auto-dismiss (sticky)
96
42
  notifications.error('Critical error', { ttl: 0 });
97
43
  </script>
98
44
  ```
@@ -107,30 +53,193 @@ A toast notification system with auto-disposal, deduplication, progress indicato
107
53
  </script>
108
54
  ```
109
55
 
110
- ### Custom Positioning
56
+ ### Positioning
111
57
 
112
58
  ```svelte
59
+ <!-- Top right (default) -->
60
+ <Notifications {notifications} />
61
+
62
+ <!-- Bottom center -->
63
+ <Notifications {notifications} posX="center" posY="bottom" />
64
+
65
+ <!-- Different positions for mobile vs desktop -->
113
66
  <Notifications
114
67
  {notifications}
115
- posX="left"
116
- posY="bottom"
68
+ posX="right"
117
69
  posXMobile="center"
70
+ posY="top"
118
71
  posYMobile="bottom"
119
72
  />
120
73
  ```
121
74
 
122
- ### Custom Stack Options
75
+ ### Without Icons or Progress
76
+
77
+ ```svelte
78
+ <Notifications {notifications} noIcons />
79
+ <Notifications {notifications} noProgress />
80
+ <Notifications {notifications} noXButton />
81
+ ```
82
+
83
+ ### Custom Icons
123
84
 
124
85
  ```svelte
125
86
  <script lang="ts">
126
- const notifications = new NotificationsStack([], {
127
- maxCapacity: 3,
128
- defaultTtl: 5000,
129
- sortOrder: 'desc'
130
- });
87
+ const customIcons = {
88
+ info: () => '<svg>...</svg>',
89
+ success: () => '<svg>...</svg>',
90
+ warn: () => '<svg>...</svg>',
91
+ error: () => '<svg>...</svg>',
92
+ };
131
93
  </script>
94
+
95
+ <Notifications {notifications} iconFns={customIcons} />
132
96
  ```
133
97
 
98
+ ## Props
99
+
100
+ | Prop | Type | Default | Description |
101
+ |------|------|---------|-------------|
102
+ | `notifications` | `NotificationsStack` | required | The notifications stack instance |
103
+ | `posX` | `"left" \| "center" \| "right"` | `"right"` | Horizontal position (desktop) |
104
+ | `posXMobile` | `"left" \| "center" \| "right"` | `"center"` | Horizontal position (mobile) |
105
+ | `posY` | `"top" \| "center" \| "bottom"` | `"top"` | Vertical position (desktop) |
106
+ | `posYMobile` | `"top" \| "center" \| "bottom"` | `"top"` | Vertical position (mobile) |
107
+ | `noIcons` | `boolean` | `false` | Hide notification icons |
108
+ | `noProgress` | `boolean` | `false` | Hide TTL progress bar |
109
+ | `noXButton` | `boolean` | `false` | Hide close button |
110
+ | `forceAsHtml` | `boolean` | `false` | Render content as HTML |
111
+ | `ariaCloseLabel` | `string` | `"Close"` | Accessibility label for close button |
112
+ | `duration` | `number` | `200` | Fade transition duration (ms) |
113
+ | `iconFns` | `Record<type, () => string>` | - | Custom icon render functions |
114
+ | `class` | `string` | - | Additional CSS classes for notification box |
115
+ | `classWrapX` | `string` | - | Additional CSS classes for horizontal wrapper |
116
+ | `classWrapY` | `string` | - | Additional CSS classes for vertical wrapper |
117
+ | `classNotifCount` | `string` | - | Additional CSS classes for count badge |
118
+ | `classNotifIcon` | `string` | - | Additional CSS classes for icon |
119
+ | `classNotifContent` | `string` | - | Additional CSS classes for content |
120
+ | `classProgress` | `string` | - | Additional CSS classes for progress container |
121
+ | `classProgressBar` | `string` | - | Additional CSS classes for progress bar |
122
+ | `el` | `HTMLDivElement` | - | Bindable element reference |
123
+
124
+ ## CSS Variables
125
+
126
+ ### Component Tokens
127
+
128
+ Override globally in `:root` or locally via `style` attribute:
129
+
130
+ ```css
131
+ :root {
132
+ /* Layout */
133
+ --stuic-notification-max-width: var(--container-sm); /* 24rem */
134
+ --stuic-notification-radius: var(--radius-lg); /* 0.5rem */
135
+ --stuic-notification-padding-x: calc(var(--spacing) * 4); /* 1rem */
136
+ --stuic-notification-padding-y: calc(var(--spacing) * 3); /* 0.75rem */
137
+ --stuic-notification-gap: calc(var(--spacing) * 4); /* 1rem */
138
+
139
+ /* Typography */
140
+ --stuic-notification-font-size: var(--text-sm);
141
+
142
+ /* Animation */
143
+ --stuic-notification-transition: 200ms;
144
+
145
+ /* Shadow */
146
+ --stuic-notification-shadow: var(--shadow-lg);
147
+
148
+ /* Icon */
149
+ --stuic-notification-icon-size: calc(var(--spacing) * 6); /* 1.5rem */
150
+
151
+ /* Counter badge */
152
+ --stuic-notification-badge-font-size: var(--text-xs);
153
+ --stuic-notification-badge-padding-x: calc(var(--spacing) * 2);
154
+ --stuic-notification-badge-padding-y: calc(var(--spacing) * 1);
155
+ --stuic-notification-badge-radius: 9999px;
156
+ --stuic-notification-badge-bg: var(--color-neutral-950);
157
+ --stuic-notification-badge-text: var(--color-neutral-50);
158
+
159
+ /* Progress bar */
160
+ --stuic-notification-progress-opacity: 0.1;
161
+ }
162
+ ```
163
+
164
+ ### Example Override
165
+
166
+ ```css
167
+ /* Make notifications more compact */
168
+ :root {
169
+ --stuic-notification-padding-x: calc(var(--spacing) * 3);
170
+ --stuic-notification-padding-y: calc(var(--spacing) * 2);
171
+ --stuic-notification-radius: var(--radius-md);
172
+ }
173
+ ```
174
+
175
+ ```svelte
176
+ <!-- Local override -->
177
+ <Notifications
178
+ {notifications}
179
+ style="--stuic-notification-radius: 9999px;"
180
+ />
181
+ ```
182
+
183
+ ### Type Colors
184
+
185
+ Notification types use the global STUIC design tokens:
186
+
187
+ | Type | Background | Foreground | Border |
188
+ |------|------------|------------|--------|
189
+ | `info` | `--stuic-color-info` | `--stuic-color-info-foreground` | `--stuic-color-info-hover` |
190
+ | `success` | `--stuic-color-success` | `--stuic-color-success-foreground` | `--stuic-color-success-hover` |
191
+ | `warn` | `--stuic-color-warning` | `--stuic-color-warning-foreground` | `--stuic-color-warning-hover` |
192
+ | `error` | `--stuic-color-destructive` | `--stuic-color-destructive-foreground` | `--stuic-color-destructive-hover` |
193
+
194
+ To customize type colors, override the global intent tokens:
195
+
196
+ ```css
197
+ :root {
198
+ --stuic-color-info: var(--color-blue-600);
199
+ --stuic-color-info-foreground: var(--color-white);
200
+ --stuic-color-info-hover: var(--color-blue-700);
201
+ }
202
+ ```
203
+
204
+ ## Data Attributes
205
+
206
+ The notification box uses data attributes for type-based styling:
207
+
208
+ - `data-type` - The notification type (`info`, `success`, `warn`, `error`)
209
+
210
+ ## NotificationsStack API
211
+
212
+ ### Constructor Options
213
+
214
+ | Option | Type | Default | Description |
215
+ |--------|------|---------|-------------|
216
+ | `maxCapacity` | `number` | `5` | Maximum notifications in queue |
217
+ | `defaultTtl` | `number` | `3000` | Default time-to-live (ms) |
218
+ | `extraTtlPerChar` | `number` | `20` | Extra TTL per content character |
219
+ | `sortOrder` | `"asc" \| "desc"` | `"asc"` | Stack sort order |
220
+ | `disposeInterval` | `number` | `500` | Auto-dispose check interval (ms) |
221
+
222
+ ### Methods
223
+
224
+ | Method | Description |
225
+ |--------|-------------|
226
+ | `info(content, opts?)` | Add info notification |
227
+ | `success(content, opts?)` | Add success notification |
228
+ | `warn(content, opts?)` | Add warning notification |
229
+ | `error(content, opts?)` | Add error notification |
230
+ | `removeById(id)` | Remove notification by ID |
231
+ | `reset()` | Clear all notifications |
232
+ | `destroy()` | Cleanup and stop ticker |
233
+
234
+ ### Notification Options
235
+
236
+ | Option | Type | Description |
237
+ |--------|------|-------------|
238
+ | `id` | `string \| number` | Unique ID (auto-generated from content if omitted) |
239
+ | `ttl` | `number` | Time-to-live in ms (0 = no auto-dismiss) |
240
+ | `iconFn` | `(() => string) \| false` | Custom icon or `false` to hide |
241
+ | `forceAsHtml` | `boolean` | Render content as HTML |
242
+
134
243
  ## Cleanup
135
244
 
136
245
  ```svelte
@@ -142,3 +251,10 @@ A toast notification system with auto-disposal, deduplication, progress indicato
142
251
  onDestroy(() => notifications.destroy());
143
252
  </script>
144
253
  ```
254
+
255
+ ## Accessibility
256
+
257
+ - Uses `role="alert"` for screen reader announcements
258
+ - Uses `aria-live="assertive"` on the container
259
+ - Close button has configurable `aria-label`
260
+ - Renders in a popover layer for proper stacking context
@@ -1,20 +1,217 @@
1
- /*
2
- When defining theme variables that reference other variables, use the inline option.
1
+ /* ============================================================================
2
+ NOTIFICATION COMPONENT TOKENS
3
+ Override globally: :root { --stuic-notification-radius: 0; }
4
+ Override locally: <Notifications style="--stuic-notification-radius: 9999px;">
5
+ ============================================================================ */
3
6
 
4
- Using the inline option, the utility class will use the theme variable value instead
5
- of referencing the actual theme variable.
7
+ :root {
8
+ /* Layout */
9
+ --stuic-notification-max-width: var(--container-sm); /* 24rem */
10
+ --stuic-notification-radius: var(--radius-lg); /* 0.5rem */
11
+ --stuic-notification-padding-x: calc(var(--spacing) * 4); /* 1rem */
12
+ --stuic-notification-padding-y: calc(var(--spacing) * 3); /* 0.75rem */
13
+ --stuic-notification-gap: calc(
14
+ var(--spacing) * 4
15
+ ); /* 1rem - gap between notifications */
6
16
 
7
- Without using inline, your utility classes might resolve to unexpected values because
8
- of how variables are resolved in CSS.
9
- */
17
+ /* Typography */
18
+ --stuic-notification-font-size: var(--text-base);
10
19
 
11
- /* prettier-ignore */
12
- @theme inline {
13
- --color-notif-bg: var(--color-notif-bg, var(--color-neutral-700));
14
- --color-notif-text: var(--color-notif-text, var(--color-neutral-50));
15
- --color-notif-border: var(--color-notif-border, var(--color-neutral-900));
20
+ /* Animation */
21
+ --stuic-notification-transition: 200ms;
16
22
 
17
- --color-notif-bg-dark: var(--color-notif-bg-dark, var(--color-neutral-950));
18
- --color-notif-text-dark: var(--color-notif-text-dark, var(--color-neutral-200));
19
- --color-notif-border-dark: var(--color-notif-border-dark, var(--color-neutral-500));
23
+ /* Shadow */
24
+ --stuic-notification-shadow: var(--shadow-lg);
25
+
26
+ /* Icon */
27
+ --stuic-notification-icon-size: calc(var(--spacing) * 6); /* 1.5rem */
28
+
29
+ /* Counter badge */
30
+ --stuic-notification-badge-font-size: var(--text-xs);
31
+ --stuic-notification-badge-padding-x: calc(var(--spacing) * 2);
32
+ --stuic-notification-badge-padding-y: calc(var(--spacing) * 1);
33
+ --stuic-notification-badge-radius: 9999px;
34
+ --stuic-notification-badge-bg: var(--color-neutral-950);
35
+ --stuic-notification-badge-text: var(--color-neutral-50);
36
+
37
+ /* Progress bar */
38
+ --stuic-notification-progress-opacity: 0.1;
39
+ }
40
+
41
+ /* ============================================================================
42
+ TYPE-BASED COLOR MAPPING
43
+ Each type sets the color palette via internal CSS vars.
44
+ ============================================================================ */
45
+
46
+ /* Default / info */
47
+ .stuic-notification {
48
+ --_bg: var(--stuic-color-info);
49
+ --_text: var(--stuic-color-info-foreground);
50
+ --_border: var(--stuic-color-info-hover);
51
+ }
52
+
53
+ .stuic-notification[data-type="success"] {
54
+ --_bg: var(--stuic-color-success);
55
+ --_text: var(--stuic-color-success-foreground);
56
+ --_border: var(--stuic-color-success-hover);
57
+ }
58
+
59
+ .stuic-notification[data-type="warn"] {
60
+ --_bg: var(--stuic-color-warning);
61
+ --_text: var(--stuic-color-warning-foreground);
62
+ --_border: var(--stuic-color-warning-hover);
63
+ }
64
+
65
+ .stuic-notification[data-type="error"] {
66
+ --_bg: var(--stuic-color-destructive);
67
+ --_text: var(--stuic-color-destructive-foreground);
68
+ --_border: var(--stuic-color-destructive-hover);
69
+ }
70
+
71
+ /* ============================================================================
72
+ BASE STYLES
73
+ ============================================================================ */
74
+
75
+ .stuic-notification {
76
+ /* Layout */
77
+ position: relative;
78
+ display: flex;
79
+ align-items: center;
80
+ width: 100%;
81
+ max-width: 100%;
82
+
83
+ /* Box model */
84
+ border-width: 1px;
85
+ border-style: solid;
86
+ border-radius: var(--stuic-notification-radius);
87
+
88
+ /* Shadow */
89
+ box-shadow: var(--stuic-notification-shadow);
90
+
91
+ /* Colors - use internal vars set by type */
92
+ background: var(--_bg);
93
+ color: var(--_text);
94
+ border-color: var(--_border);
95
+
96
+ /* Interaction */
97
+ pointer-events: auto;
98
+ }
99
+
100
+ @media (min-width: 40rem) {
101
+ .stuic-notification {
102
+ width: var(--stuic-notification-max-width);
103
+ }
104
+ }
105
+
106
+ /* ============================================================================
107
+ ICON
108
+ ============================================================================ */
109
+
110
+ .stuic-notification .icon {
111
+ display: flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ padding-top: var(--stuic-notification-padding-y);
115
+ padding-bottom: var(--stuic-notification-padding-y);
116
+ padding-left: var(--stuic-notification-padding-x);
117
+ padding-right: 0;
118
+ color: var(--_text);
119
+ opacity: 0.85;
120
+ }
121
+
122
+ .stuic-notification .icon svg {
123
+ width: var(--stuic-notification-icon-size);
124
+ height: var(--stuic-notification-icon-size);
125
+ }
126
+
127
+ /* ============================================================================
128
+ CONTENT
129
+ ============================================================================ */
130
+
131
+ .stuic-notification .content {
132
+ flex: 1;
133
+ display: flex;
134
+ flex-direction: column;
135
+ justify-content: center;
136
+ padding: var(--stuic-notification-padding-y) calc(var(--spacing) * 1)
137
+ var(--stuic-notification-padding-y) var(--stuic-notification-padding-x);
138
+ font-size: var(--stuic-notification-font-size);
139
+ letter-spacing: var(--tracking-tight);
140
+ }
141
+
142
+ .stuic-notification .content.no-close-button {
143
+ padding-right: var(--stuic-notification-padding-x);
144
+ }
145
+
146
+ /* ============================================================================
147
+ CLOSE BUTTON
148
+ ============================================================================ */
149
+
150
+ .stuic-notification .close-button {
151
+ align-self: stretch;
152
+ display: flex;
153
+ flex-direction: column;
154
+ align-items: center;
155
+ justify-content: center;
156
+ padding: 0 calc(var(--spacing) * 3);
157
+ border-top-right-radius: var(--stuic-notification-radius);
158
+ border-bottom-right-radius: var(--stuic-notification-radius);
159
+ color: var(--_text);
160
+ opacity: 0.75;
161
+ transition: opacity var(--stuic-notification-transition);
162
+ }
163
+
164
+ .stuic-notification .close-button:hover {
165
+ opacity: 1;
166
+ background: rgb(0 0 0 / 0.1);
167
+ }
168
+
169
+ .stuic-notification .close-button:focus-visible {
170
+ opacity: 1;
171
+ outline: none;
172
+ background: rgb(0 0 0 / 0.1);
173
+ }
174
+
175
+ /* ============================================================================
176
+ COUNTER BADGE
177
+ ============================================================================ */
178
+
179
+ .stuic-notification .count {
180
+ position: absolute;
181
+ top: calc(var(--spacing) * -2);
182
+ right: calc(var(--spacing) * -2);
183
+ display: flex;
184
+ align-items: center;
185
+ justify-content: center;
186
+ padding: var(--stuic-notification-badge-padding-y)
187
+ var(--stuic-notification-badge-padding-x);
188
+ border-radius: var(--stuic-notification-badge-radius);
189
+ font-size: var(--stuic-notification-badge-font-size);
190
+ line-height: 1;
191
+ background: var(--stuic-notification-badge-bg);
192
+ color: var(--stuic-notification-badge-text);
193
+ }
194
+
195
+ /* ============================================================================
196
+ PROGRESS BAR
197
+ ============================================================================ */
198
+
199
+ .stuic-notification .progress {
200
+ position: absolute;
201
+ inset: 0;
202
+ width: 100%;
203
+ height: 100%;
204
+ background: transparent;
205
+ border-top-left-radius: var(--stuic-notification-radius);
206
+ border-bottom-left-radius: var(--stuic-notification-radius);
207
+ overflow: hidden;
208
+ pointer-events: none;
209
+ }
210
+
211
+ .stuic-notification .progress-bar {
212
+ width: 100%;
213
+ height: 100%;
214
+ background: rgb(255 255 255 / var(--stuic-notification-progress-opacity));
215
+ border-top-left-radius: var(--stuic-notification-radius);
216
+ border-bottom-left-radius: var(--stuic-notification-radius);
20
217
  }
@@ -69,3 +69,18 @@ A progress indicator available as either a horizontal bar or circular display.
69
69
  classBar="transition-all duration-300"
70
70
  />
71
71
  ```
72
+
73
+ ## CSS Variables
74
+
75
+ | Variable | Default | Description |
76
+ |----------|---------|-------------|
77
+ | `--stuic-progress-bg` | `--stuic-surface-interactive` | Track background |
78
+ | `--stuic-progress-accent` | `--stuic-accent` | Progress bar fill color |
79
+
80
+ ### Example Override
81
+
82
+ ```css
83
+ :root {
84
+ --stuic-progress-accent: var(--color-green-500);
85
+ }
86
+ ```
@@ -16,14 +16,14 @@
16
16
  <div
17
17
  class={twMerge(
18
18
  "stuic-progress-bar",
19
- "w-full h-2 bg-progress-bg flex justify-start pointer-events-none",
19
+ "w-full h-2 bg-(--stuic-progress-bg) flex justify-start pointer-events-none",
20
20
  classProp
21
21
  )}
22
22
  >
23
23
  <div
24
24
  class={twMerge(
25
25
  "bar",
26
- "w-full h-full bg-progress-accent transition-[width] ease-linear duration-100",
26
+ "w-full h-full bg-(--stuic-progress-accent) transition-[width] ease-linear duration-100",
27
27
  classBar
28
28
  )}
29
29
  style="width:{Math.min(100, Math.max(0, progress))}%; {styleBar}"
@@ -1,5 +1,5 @@
1
- /* prettier-ignore */
2
- @theme inline {
3
- --color-progress-bg: var(--color-progress-bg, var(--color-neutral-200));
4
- --color-progress-accent: var(--color-progress-accent, var(--color-neutral-600));
1
+ /* Progress component tokens */
2
+ :root {
3
+ --stuic-progress-bg: var(--stuic-color-muted);
4
+ --stuic-progress-accent: var(--stuic-color-primary);
5
5
  }
@@ -62,9 +62,10 @@
62
62
 
63
63
  const baseClass = $derived(
64
64
  twMerge(
65
- "block bg-neutral-200 dark:bg-neutral-700",
65
+ "block",
66
66
  effectiveAnimation === "shimmer" && "stuic-skeleton-shimmer",
67
67
  effectiveAnimation === "pulse" && "stuic-skeleton-pulse",
68
+ effectiveAnimation === "none" && "bg-[var(--stuic-skeleton-bg)]",
68
69
  variant === "circle" && "stuic-skeleton-circle",
69
70
  rounded === true && variant !== "circle" && "rounded",
70
71
  classProp
@@ -73,7 +74,7 @@
73
74
 
74
75
  const baseStyle = $derived.by(() => {
75
76
  const styles: string[] = [];
76
- if (duration) styles.push(`--skeleton-duration: ${duration}`);
77
+ if (duration) styles.push(`--stuic-skeleton-duration: ${duration}`);
77
78
  if (variant === "circle" && size) {
78
79
  styles.push(`width: ${size}`, `height: ${size}`);
79
80
  } else {
@@ -1,12 +1,8 @@
1
- /* Define CSS custom properties for use in gradients */
2
- :root {
3
- --skeleton-base: #e5e5e5;
4
- --skeleton-highlight: #f5f5f5;
5
- }
6
-
7
- .dark {
8
- --skeleton-base: #404040;
9
- --skeleton-highlight: #525252;
1
+ /* prettier-ignore */
2
+ @theme inline {
3
+ /* Skeleton component tokens */
4
+ --stuic-skeleton-bg: var(--stuic-skeleton-bg, var(--stuic-surface-interactive));
5
+ --stuic-skeleton-bg-highlight: var(--stuic-skeleton-bg-highlight, var(--stuic-surface-interactive-hover));
10
6
  }
11
7
 
12
8
  .stuic-skeleton-circle {
@@ -31,12 +27,12 @@
31
27
  .stuic-skeleton-shimmer {
32
28
  background: linear-gradient(
33
29
  90deg,
34
- var(--skeleton-base) 25%,
35
- var(--skeleton-highlight) 50%,
36
- var(--skeleton-base) 75%
30
+ var(--stuic-skeleton-bg) 25%,
31
+ var(--stuic-skeleton-bg-highlight) 50%,
32
+ var(--stuic-skeleton-bg) 75%
37
33
  );
38
34
  background-size: 200% 100%;
39
- animation: skeleton-shimmer var(--skeleton-duration, 1.5s) ease-in-out infinite;
35
+ animation: skeleton-shimmer var(--stuic-skeleton-duration, 1.5s) ease-in-out infinite;
40
36
  }
41
37
 
42
38
  /* Pulse animation */
@@ -50,7 +46,8 @@
50
46
  }
51
47
 
52
48
  .stuic-skeleton-pulse {
53
- animation: skeleton-pulse var(--skeleton-duration, 1.5s) ease-in-out infinite;
49
+ background-color: var(--stuic-skeleton-bg);
50
+ animation: skeleton-pulse var(--stuic-skeleton-duration, 1.5s) ease-in-out infinite;
54
51
  }
55
52
 
56
53
  /* Reduced motion */
@@ -30,7 +30,7 @@
30
30
  };
31
31
  const heightMap: Record<NonNullable<Props["height"]>, number> = {
32
32
  short: 5,
33
- normal: 7,
33
+ normal: 6,
34
34
  tall: 10,
35
35
  };
36
36
 
@@ -42,7 +42,7 @@
42
42
  </script>
43
43
 
44
44
  <div
45
- class={twMerge("spinner opacity-50", classProp)}
45
+ class={twMerge("spinner opacity-80", classProp)}
46
46
  style:--size="{size}px"
47
47
  style:--duration="{duration}ms"
48
48
  >
@@ -27,7 +27,7 @@
27
27
  </script>
28
28
 
29
29
  <span
30
- class={twMerge("stuic-spinner-basic inline-block size-5", _thickness, classProp)}
30
+ class={twMerge("stuic-spinner-basic inline-block size-4", _thickness, classProp)}
31
31
  style="animation-duration: {duration}ms; animation-direction: {direction === 'ccw'
32
32
  ? 'reverse'
33
33
  : 'normal'};"