@synthaxai/ui 1.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 (185) hide show
  1. package/README.md +262 -0
  2. package/dist/app.css +2 -0
  3. package/dist/app.html +12 -0
  4. package/dist/data-display/DataTable/DataTable.svelte +773 -0
  5. package/dist/data-display/DataTable/DataTable.svelte.d.ts +120 -0
  6. package/dist/data-display/DataTable/DataTable.svelte.d.ts.map +1 -0
  7. package/dist/data-display/DataTable/index.d.ts +2 -0
  8. package/dist/data-display/DataTable/index.d.ts.map +1 -0
  9. package/dist/data-display/DataTable/index.js +1 -0
  10. package/dist/data-display/StatCard/StatCard.svelte +409 -0
  11. package/dist/data-display/StatCard/StatCard.svelte.d.ts +63 -0
  12. package/dist/data-display/StatCard/StatCard.svelte.d.ts.map +1 -0
  13. package/dist/data-display/StatCard/index.d.ts +2 -0
  14. package/dist/data-display/StatCard/index.d.ts.map +1 -0
  15. package/dist/data-display/StatCard/index.js +1 -0
  16. package/dist/data-display/index.d.ts +8 -0
  17. package/dist/data-display/index.d.ts.map +1 -0
  18. package/dist/data-display/index.js +7 -0
  19. package/dist/dialogs/ConfirmDialog/ConfirmDialog.svelte +693 -0
  20. package/dist/dialogs/ConfirmDialog/ConfirmDialog.svelte.d.ts +66 -0
  21. package/dist/dialogs/ConfirmDialog/ConfirmDialog.svelte.d.ts.map +1 -0
  22. package/dist/dialogs/ConfirmDialog/index.d.ts +2 -0
  23. package/dist/dialogs/ConfirmDialog/index.d.ts.map +1 -0
  24. package/dist/dialogs/ConfirmDialog/index.js +1 -0
  25. package/dist/dialogs/Modal/Modal.svelte +441 -0
  26. package/dist/dialogs/Modal/Modal.svelte.d.ts +69 -0
  27. package/dist/dialogs/Modal/Modal.svelte.d.ts.map +1 -0
  28. package/dist/dialogs/Modal/index.d.ts +2 -0
  29. package/dist/dialogs/Modal/index.d.ts.map +1 -0
  30. package/dist/dialogs/Modal/index.js +1 -0
  31. package/dist/dialogs/index.d.ts +8 -0
  32. package/dist/dialogs/index.d.ts.map +1 -0
  33. package/dist/dialogs/index.js +7 -0
  34. package/dist/feedback/Alert/Alert.svelte +565 -0
  35. package/dist/feedback/Alert/Alert.svelte.d.ts +60 -0
  36. package/dist/feedback/Alert/Alert.svelte.d.ts.map +1 -0
  37. package/dist/feedback/Alert/index.d.ts +2 -0
  38. package/dist/feedback/Alert/index.d.ts.map +1 -0
  39. package/dist/feedback/Alert/index.js +1 -0
  40. package/dist/feedback/EmptyState/EmptyState.svelte +377 -0
  41. package/dist/feedback/EmptyState/EmptyState.svelte.d.ts +63 -0
  42. package/dist/feedback/EmptyState/EmptyState.svelte.d.ts.map +1 -0
  43. package/dist/feedback/EmptyState/index.d.ts +2 -0
  44. package/dist/feedback/EmptyState/index.d.ts.map +1 -0
  45. package/dist/feedback/EmptyState/index.js +1 -0
  46. package/dist/feedback/ProgressBar/ProgressBar.svelte +585 -0
  47. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts +68 -0
  48. package/dist/feedback/ProgressBar/ProgressBar.svelte.d.ts.map +1 -0
  49. package/dist/feedback/ProgressBar/index.d.ts +2 -0
  50. package/dist/feedback/ProgressBar/index.d.ts.map +1 -0
  51. package/dist/feedback/ProgressBar/index.js +1 -0
  52. package/dist/feedback/Skeleton/Skeleton.svelte +568 -0
  53. package/dist/feedback/Skeleton/Skeleton.svelte.d.ts +54 -0
  54. package/dist/feedback/Skeleton/Skeleton.svelte.d.ts.map +1 -0
  55. package/dist/feedback/Skeleton/index.d.ts +2 -0
  56. package/dist/feedback/Skeleton/index.d.ts.map +1 -0
  57. package/dist/feedback/Skeleton/index.js +1 -0
  58. package/dist/feedback/Spinner/Spinner.svelte +434 -0
  59. package/dist/feedback/Spinner/Spinner.svelte.d.ts +49 -0
  60. package/dist/feedback/Spinner/Spinner.svelte.d.ts.map +1 -0
  61. package/dist/feedback/Spinner/index.d.ts +2 -0
  62. package/dist/feedback/Spinner/index.d.ts.map +1 -0
  63. package/dist/feedback/Spinner/index.js +1 -0
  64. package/dist/feedback/Toast/Toast.svelte +587 -0
  65. package/dist/feedback/Toast/Toast.svelte.d.ts +55 -0
  66. package/dist/feedback/Toast/Toast.svelte.d.ts.map +1 -0
  67. package/dist/feedback/Toast/ToastContainer.svelte +168 -0
  68. package/dist/feedback/Toast/ToastContainer.svelte.d.ts +28 -0
  69. package/dist/feedback/Toast/ToastContainer.svelte.d.ts.map +1 -0
  70. package/dist/feedback/Toast/index.d.ts +4 -0
  71. package/dist/feedback/Toast/index.d.ts.map +1 -0
  72. package/dist/feedback/Toast/index.js +3 -0
  73. package/dist/feedback/Toast/toast-store.d.ts +72 -0
  74. package/dist/feedback/Toast/toast-store.d.ts.map +1 -0
  75. package/dist/feedback/Toast/toast-store.js +157 -0
  76. package/dist/feedback/index.d.ts +13 -0
  77. package/dist/feedback/index.d.ts.map +1 -0
  78. package/dist/feedback/index.js +12 -0
  79. package/dist/forms/Checkbox/Checkbox.svelte +404 -0
  80. package/dist/forms/Checkbox/Checkbox.svelte.d.ts +62 -0
  81. package/dist/forms/Checkbox/Checkbox.svelte.d.ts.map +1 -0
  82. package/dist/forms/Checkbox/index.d.ts +2 -0
  83. package/dist/forms/Checkbox/index.d.ts.map +1 -0
  84. package/dist/forms/Checkbox/index.js +1 -0
  85. package/dist/forms/FormField/FormField.svelte +299 -0
  86. package/dist/forms/FormField/FormField.svelte.d.ts +43 -0
  87. package/dist/forms/FormField/FormField.svelte.d.ts.map +1 -0
  88. package/dist/forms/FormField/index.d.ts +2 -0
  89. package/dist/forms/FormField/index.d.ts.map +1 -0
  90. package/dist/forms/FormField/index.js +1 -0
  91. package/dist/forms/RadioGroup/RadioGroup.svelte +418 -0
  92. package/dist/forms/RadioGroup/RadioGroup.svelte.d.ts +70 -0
  93. package/dist/forms/RadioGroup/RadioGroup.svelte.d.ts.map +1 -0
  94. package/dist/forms/RadioGroup/index.d.ts +2 -0
  95. package/dist/forms/RadioGroup/index.d.ts.map +1 -0
  96. package/dist/forms/RadioGroup/index.js +1 -0
  97. package/dist/forms/Select/Select.svelte +548 -0
  98. package/dist/forms/Select/Select.svelte.d.ts +74 -0
  99. package/dist/forms/Select/Select.svelte.d.ts.map +1 -0
  100. package/dist/forms/Select/index.d.ts +2 -0
  101. package/dist/forms/Select/index.d.ts.map +1 -0
  102. package/dist/forms/Select/index.js +1 -0
  103. package/dist/forms/TextInput/TextInput.svelte +628 -0
  104. package/dist/forms/TextInput/TextInput.svelte.d.ts +97 -0
  105. package/dist/forms/TextInput/TextInput.svelte.d.ts.map +1 -0
  106. package/dist/forms/TextInput/index.d.ts +2 -0
  107. package/dist/forms/TextInput/index.d.ts.map +1 -0
  108. package/dist/forms/TextInput/index.js +1 -0
  109. package/dist/forms/Textarea/Textarea.svelte +587 -0
  110. package/dist/forms/Textarea/Textarea.svelte.d.ts +71 -0
  111. package/dist/forms/Textarea/Textarea.svelte.d.ts.map +1 -0
  112. package/dist/forms/Textarea/index.d.ts +2 -0
  113. package/dist/forms/Textarea/index.d.ts.map +1 -0
  114. package/dist/forms/Textarea/index.js +1 -0
  115. package/dist/forms/index.d.ts +13 -0
  116. package/dist/forms/index.d.ts.map +1 -0
  117. package/dist/forms/index.js +12 -0
  118. package/dist/index.d.ts +37 -0
  119. package/dist/index.d.ts.map +1 -0
  120. package/dist/index.js +65 -0
  121. package/dist/layout/Card/Card.svelte +316 -0
  122. package/dist/layout/Card/Card.svelte.d.ts +63 -0
  123. package/dist/layout/Card/Card.svelte.d.ts.map +1 -0
  124. package/dist/layout/Card/index.d.ts +2 -0
  125. package/dist/layout/Card/index.d.ts.map +1 -0
  126. package/dist/layout/Card/index.js +1 -0
  127. package/dist/layout/Container/Container.svelte +252 -0
  128. package/dist/layout/Container/Container.svelte.d.ts +50 -0
  129. package/dist/layout/Container/Container.svelte.d.ts.map +1 -0
  130. package/dist/layout/Container/index.d.ts +2 -0
  131. package/dist/layout/Container/index.d.ts.map +1 -0
  132. package/dist/layout/Container/index.js +1 -0
  133. package/dist/layout/index.d.ts +8 -0
  134. package/dist/layout/index.d.ts.map +1 -0
  135. package/dist/layout/index.js +7 -0
  136. package/dist/navigation/StepIndicator/StepIndicator.svelte +601 -0
  137. package/dist/navigation/StepIndicator/StepIndicator.svelte.d.ts +70 -0
  138. package/dist/navigation/StepIndicator/StepIndicator.svelte.d.ts.map +1 -0
  139. package/dist/navigation/StepIndicator/index.d.ts +2 -0
  140. package/dist/navigation/StepIndicator/index.d.ts.map +1 -0
  141. package/dist/navigation/StepIndicator/index.js +1 -0
  142. package/dist/navigation/index.d.ts +7 -0
  143. package/dist/navigation/index.d.ts.map +1 -0
  144. package/dist/navigation/index.js +6 -0
  145. package/dist/primitives/Badge/Badge.svelte +365 -0
  146. package/dist/primitives/Badge/Badge.svelte.d.ts +39 -0
  147. package/dist/primitives/Badge/Badge.svelte.d.ts.map +1 -0
  148. package/dist/primitives/Badge/index.d.ts +2 -0
  149. package/dist/primitives/Badge/index.d.ts.map +1 -0
  150. package/dist/primitives/Badge/index.js +1 -0
  151. package/dist/primitives/Button/Button.svelte +430 -0
  152. package/dist/primitives/Button/Button.svelte.d.ts +50 -0
  153. package/dist/primitives/Button/Button.svelte.d.ts.map +1 -0
  154. package/dist/primitives/Button/index.d.ts +2 -0
  155. package/dist/primitives/Button/index.d.ts.map +1 -0
  156. package/dist/primitives/Button/index.js +1 -0
  157. package/dist/primitives/index.d.ts +9 -0
  158. package/dist/primitives/index.d.ts.map +1 -0
  159. package/dist/primitives/index.js +8 -0
  160. package/dist/routes/+layout.svelte +12 -0
  161. package/dist/routes/+layout.svelte.d.ts +12 -0
  162. package/dist/routes/+layout.svelte.d.ts.map +1 -0
  163. package/dist/routes/+page.svelte +53 -0
  164. package/dist/routes/+page.svelte.d.ts +27 -0
  165. package/dist/routes/+page.svelte.d.ts.map +1 -0
  166. package/dist/styles/tokens.css +399 -0
  167. package/dist/types/index.d.ts +175 -0
  168. package/dist/types/index.d.ts.map +1 -0
  169. package/dist/types/index.js +7 -0
  170. package/dist/utils/accessibility.d.ts +103 -0
  171. package/dist/utils/accessibility.d.ts.map +1 -0
  172. package/dist/utils/accessibility.js +202 -0
  173. package/dist/utils/cn.d.ts +71 -0
  174. package/dist/utils/cn.d.ts.map +1 -0
  175. package/dist/utils/cn.js +61 -0
  176. package/dist/utils/form-styles.d.ts +76 -0
  177. package/dist/utils/form-styles.d.ts.map +1 -0
  178. package/dist/utils/form-styles.js +95 -0
  179. package/dist/utils/index.d.ts +10 -0
  180. package/dist/utils/index.d.ts.map +1 -0
  181. package/dist/utils/index.js +13 -0
  182. package/dist/utils/keyboard.d.ts +94 -0
  183. package/dist/utils/keyboard.d.ts.map +1 -0
  184. package/dist/utils/keyboard.js +179 -0
  185. package/package.json +119 -0
@@ -0,0 +1,565 @@
1
+ <!--
2
+ @component Alert
3
+
4
+ A comprehensive alert/banner component for displaying important messages and notifications.
5
+ Critical for healthcare applications where users need to be aware of important information,
6
+ warnings, or errors. Follows WCAG 2.1 and VA.gov design system best practices.
7
+
8
+ @example
9
+ <Alert type="warning" title="Allergy Alert">
10
+ Patient has documented penicillin allergy.
11
+ </Alert>
12
+
13
+ @example
14
+ <Alert type="error" dismissible onclose={() => showAlert = false}>
15
+ Failed to save patient record. Please try again.
16
+ </Alert>
17
+
18
+ @example
19
+ <Alert type="info" variant="slim">
20
+ Your changes have been saved.
21
+ </Alert>
22
+ -->
23
+ <script lang="ts">
24
+ import type { Snippet } from 'svelte';
25
+ import { X, AlertTriangle, AlertCircle, CheckCircle2, Info, Bell, ChevronDown, ChevronUp } from 'lucide-svelte';
26
+ import type { Status } from '../../types/index.js';
27
+
28
+ type AlertVariant = 'standard' | 'slim' | 'banner' | 'bordered';
29
+ type HeadingLevel = 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
30
+
31
+ interface Props {
32
+ /** Alert type/severity */
33
+ type?: Status | 'clinical';
34
+ /** Alert variant/style */
35
+ variant?: AlertVariant;
36
+ /** Optional title/heading */
37
+ title?: string;
38
+ /** Heading level for the title (for proper document structure) */
39
+ headingLevel?: HeadingLevel;
40
+ /** Whether the alert can be dismissed */
41
+ dismissible?: boolean;
42
+ /** Whether to show the icon */
43
+ showIcon?: boolean;
44
+ /** Whether the alert content is expandable (for longer content) */
45
+ expandable?: boolean;
46
+ /** Whether expandable alert starts expanded */
47
+ defaultExpanded?: boolean;
48
+ /** Additional CSS classes */
49
+ class?: string;
50
+ /** Alert content */
51
+ children?: Snippet;
52
+ /** Action buttons slot */
53
+ actions?: Snippet;
54
+ /** Close handler - receives a callback to manage focus */
55
+ onclose?: () => void;
56
+ /** Custom close button aria-label */
57
+ closeBtnAriaLabel?: string;
58
+ /** ID for the alert element */
59
+ id?: string;
60
+ }
61
+
62
+ let {
63
+ type = 'info',
64
+ variant = 'standard',
65
+ title = '',
66
+ headingLevel = 'h3',
67
+ dismissible = false,
68
+ showIcon = true,
69
+ expandable = false,
70
+ defaultExpanded = true,
71
+ class: className = '',
72
+ children,
73
+ actions,
74
+ onclose,
75
+ closeBtnAriaLabel,
76
+ id
77
+ }: Props = $props();
78
+
79
+ // Expandable state - use a stable initial value
80
+ let isExpanded = $state(true);
81
+
82
+ // Sync with defaultExpanded prop on mount
83
+ $effect(() => {
84
+ isExpanded = defaultExpanded;
85
+ });
86
+
87
+ // Generate a stable unique ID
88
+ const generatedId = `alert-${Math.random().toString(36).substr(2, 9)}`;
89
+ const alertId = $derived(id || generatedId);
90
+ const contentId = $derived(`${alertId}-content`);
91
+ const titleId = $derived(`${alertId}-title`);
92
+
93
+ // Type configurations using CSS custom properties
94
+ const typeStyles = {
95
+ success: 'alert-success',
96
+ error: 'alert-error',
97
+ warning: 'alert-warning',
98
+ info: 'alert-info',
99
+ neutral: 'alert-neutral',
100
+ clinical: 'alert-clinical'
101
+ };
102
+
103
+ // Determine ARIA attributes based on type
104
+ const ariaRole = $derived(type === 'error' || type === 'warning' ? 'alert' : 'status');
105
+ const ariaLive = $derived(type === 'error' ? 'assertive' : 'polite');
106
+
107
+ // Compute close button aria-label
108
+ const closeLabel = $derived(
109
+ closeBtnAriaLabel || `Close ${title || type} notification`
110
+ );
111
+
112
+ function handleDismiss() {
113
+ onclose?.();
114
+ }
115
+
116
+ function toggleExpanded() {
117
+ isExpanded = !isExpanded;
118
+ }
119
+
120
+ // Icon component based on type
121
+ const iconSize = $derived(variant === 'slim' ? 16 : 20);
122
+ </script>
123
+
124
+ <div
125
+ {id}
126
+ class="alert alert-{variant} {typeStyles[type]} {className}"
127
+ class:alert-expandable={expandable}
128
+ class:alert-expanded={expandable && isExpanded}
129
+ role={ariaRole}
130
+ aria-live={ariaLive}
131
+ aria-labelledby={title ? titleId : undefined}
132
+ >
133
+ <!-- Icon -->
134
+ {#if showIcon}
135
+ <span class="alert-icon" aria-hidden="true">
136
+ {#if type === 'success'}
137
+ <CheckCircle2 size={iconSize} />
138
+ {:else if type === 'error'}
139
+ <AlertCircle size={iconSize} />
140
+ {:else if type === 'warning'}
141
+ <AlertTriangle size={iconSize} />
142
+ {:else if type === 'clinical'}
143
+ <Bell size={iconSize} />
144
+ {:else}
145
+ <Info size={iconSize} />
146
+ {/if}
147
+ </span>
148
+ {/if}
149
+
150
+ <!-- Content -->
151
+ <div class="alert-content">
152
+ {#if title}
153
+ {#if expandable}
154
+ <button
155
+ type="button"
156
+ class="alert-title-button"
157
+ onclick={toggleExpanded}
158
+ aria-expanded={isExpanded}
159
+ aria-controls={contentId}
160
+ >
161
+ <svelte:element this={headingLevel} id={titleId} class="alert-title">
162
+ {title}
163
+ </svelte:element>
164
+ <span class="alert-expand-icon" aria-hidden="true">
165
+ {#if isExpanded}
166
+ <ChevronUp size={18} />
167
+ {:else}
168
+ <ChevronDown size={18} />
169
+ {/if}
170
+ </span>
171
+ </button>
172
+ {:else}
173
+ <svelte:element this={headingLevel} id={titleId} class="alert-title">
174
+ {title}
175
+ </svelte:element>
176
+ {/if}
177
+ {/if}
178
+
179
+ {#if children}
180
+ <div
181
+ id={contentId}
182
+ class="alert-body"
183
+ class:alert-body-hidden={expandable && !isExpanded}
184
+ aria-hidden={expandable && !isExpanded}
185
+ >
186
+ {@render children()}
187
+ </div>
188
+ {/if}
189
+
190
+ {#if actions && (!expandable || isExpanded)}
191
+ <div class="alert-actions">
192
+ {@render actions()}
193
+ </div>
194
+ {/if}
195
+ </div>
196
+
197
+ <!-- Dismiss button -->
198
+ {#if dismissible}
199
+ <button
200
+ type="button"
201
+ class="alert-dismiss"
202
+ onclick={handleDismiss}
203
+ aria-label={closeLabel}
204
+ >
205
+ <X size={variant === 'slim' ? 16 : 18} />
206
+ </button>
207
+ {/if}
208
+ </div>
209
+
210
+ <style>
211
+ /* ========================================
212
+ BASE ALERT STYLES
213
+ ======================================== */
214
+ .alert {
215
+ display: flex;
216
+ gap: 0.75rem;
217
+ padding: 1rem;
218
+ border-radius: 12px;
219
+ border: 1px solid transparent;
220
+ transition: all 0.2s ease;
221
+ }
222
+
223
+ /* ========================================
224
+ VARIANT STYLES
225
+ ======================================== */
226
+
227
+ /* Standard - rounded with subtle background */
228
+ .alert-standard {
229
+ border-radius: 12px;
230
+ }
231
+
232
+ /* Slim - compact for form feedback */
233
+ .alert-slim {
234
+ padding: 0.625rem 0.875rem;
235
+ gap: 0.5rem;
236
+ border-radius: 8px;
237
+ }
238
+
239
+ .alert-slim .alert-title {
240
+ font-size: 0.875rem;
241
+ margin-bottom: 0;
242
+ }
243
+
244
+ .alert-slim .alert-body {
245
+ font-size: 0.8125rem;
246
+ }
247
+
248
+ .alert-slim .alert-icon {
249
+ margin-top: 0;
250
+ }
251
+
252
+ /* Banner - full width, no rounded corners */
253
+ .alert-banner {
254
+ border-radius: 0;
255
+ border-left: none;
256
+ border-right: none;
257
+ border-top: none;
258
+ }
259
+
260
+ /* Bordered - left accent border */
261
+ .alert-bordered {
262
+ border-radius: 8px;
263
+ border-left-width: 4px;
264
+ background: var(--ui-bg-primary);
265
+ }
266
+
267
+ /* ========================================
268
+ TYPE STYLES (Colors)
269
+ ======================================== */
270
+
271
+ /* Success */
272
+ .alert-success {
273
+ background-color: rgb(var(--ui-color-success) / 0.08);
274
+ border-color: rgb(var(--ui-color-success) / 0.25);
275
+ }
276
+
277
+ .alert-success .alert-icon {
278
+ color: rgb(var(--ui-color-success));
279
+ }
280
+
281
+ .alert-success .alert-title {
282
+ color: rgb(var(--ui-color-success-dark, var(--ui-color-success)));
283
+ }
284
+
285
+ .alert-bordered.alert-success {
286
+ border-left-color: rgb(var(--ui-color-success));
287
+ background: var(--ui-bg-primary);
288
+ }
289
+
290
+ /* Error */
291
+ .alert-error {
292
+ background-color: rgb(var(--ui-color-error) / 0.08);
293
+ border-color: rgb(var(--ui-color-error) / 0.25);
294
+ }
295
+
296
+ .alert-error .alert-icon {
297
+ color: rgb(var(--ui-color-error));
298
+ }
299
+
300
+ .alert-error .alert-title {
301
+ color: rgb(var(--ui-color-error));
302
+ }
303
+
304
+ .alert-bordered.alert-error {
305
+ border-left-color: rgb(var(--ui-color-error));
306
+ background: var(--ui-bg-primary);
307
+ }
308
+
309
+ /* Warning */
310
+ .alert-warning {
311
+ background-color: rgb(var(--ui-color-warning) / 0.08);
312
+ border-color: rgb(var(--ui-color-warning) / 0.25);
313
+ }
314
+
315
+ .alert-warning .alert-icon {
316
+ color: rgb(var(--ui-color-warning));
317
+ }
318
+
319
+ .alert-warning .alert-title {
320
+ color: rgb(var(--ui-color-warning-dark, var(--ui-color-warning)));
321
+ }
322
+
323
+ .alert-bordered.alert-warning {
324
+ border-left-color: rgb(var(--ui-color-warning));
325
+ background: var(--ui-bg-primary);
326
+ }
327
+
328
+ /* Info */
329
+ .alert-info {
330
+ background-color: rgb(var(--ui-color-info) / 0.08);
331
+ border-color: rgb(var(--ui-color-info) / 0.25);
332
+ }
333
+
334
+ .alert-info .alert-icon {
335
+ color: rgb(var(--ui-color-info));
336
+ }
337
+
338
+ .alert-info .alert-title {
339
+ color: rgb(var(--ui-color-info));
340
+ }
341
+
342
+ .alert-bordered.alert-info {
343
+ border-left-color: rgb(var(--ui-color-info));
344
+ background: var(--ui-bg-primary);
345
+ }
346
+
347
+ /* Neutral */
348
+ .alert-neutral {
349
+ background-color: var(--ui-bg-tertiary);
350
+ border-color: var(--ui-border-default);
351
+ }
352
+
353
+ .alert-neutral .alert-icon {
354
+ color: var(--ui-text-tertiary);
355
+ }
356
+
357
+ .alert-neutral .alert-title {
358
+ color: var(--ui-text-primary);
359
+ }
360
+
361
+ .alert-bordered.alert-neutral {
362
+ border-left-color: var(--ui-border-strong);
363
+ background: var(--ui-bg-primary);
364
+ }
365
+
366
+ /* Clinical - special healthcare type */
367
+ .alert-clinical {
368
+ background-color: rgb(var(--ui-color-primary) / 0.08);
369
+ border-color: rgb(var(--ui-color-primary) / 0.25);
370
+ }
371
+
372
+ .alert-clinical .alert-icon {
373
+ color: rgb(var(--ui-color-primary));
374
+ }
375
+
376
+ .alert-clinical .alert-title {
377
+ color: rgb(var(--ui-color-primary));
378
+ }
379
+
380
+ .alert-bordered.alert-clinical {
381
+ border-left-color: rgb(var(--ui-color-primary));
382
+ background: var(--ui-bg-primary);
383
+ }
384
+
385
+ /* ========================================
386
+ DARK MODE ADJUSTMENTS
387
+ ======================================== */
388
+ :global([data-theme='dark']) .alert-success .alert-title,
389
+ :global([data-theme='dark']) .alert-warning .alert-title {
390
+ color: rgb(var(--ui-color-success-light, var(--ui-color-success)));
391
+ }
392
+
393
+ :global([data-theme='dark']) .alert-warning .alert-title {
394
+ color: rgb(var(--ui-color-warning-light, var(--ui-color-warning)));
395
+ }
396
+
397
+ :global([data-theme='dark']) .alert-clinical .alert-icon,
398
+ :global([data-theme='dark']) .alert-clinical .alert-title {
399
+ color: rgb(var(--ui-color-primary-light));
400
+ }
401
+
402
+ @media (prefers-color-scheme: dark) {
403
+ :global(:root:not([data-theme='light'])) .alert-success .alert-title {
404
+ color: rgb(var(--ui-color-success-light, var(--ui-color-success)));
405
+ }
406
+
407
+ :global(:root:not([data-theme='light'])) .alert-warning .alert-title {
408
+ color: rgb(var(--ui-color-warning-light, var(--ui-color-warning)));
409
+ }
410
+
411
+ :global(:root:not([data-theme='light'])) .alert-clinical .alert-icon,
412
+ :global(:root:not([data-theme='light'])) .alert-clinical .alert-title {
413
+ color: rgb(var(--ui-color-primary-light));
414
+ }
415
+ }
416
+
417
+ /* ========================================
418
+ ICON STYLES
419
+ ======================================== */
420
+ .alert-icon {
421
+ flex-shrink: 0;
422
+ margin-top: 0.125rem;
423
+ display: flex;
424
+ align-items: flex-start;
425
+ }
426
+
427
+ /* ========================================
428
+ CONTENT STYLES
429
+ ======================================== */
430
+ .alert-content {
431
+ flex: 1;
432
+ min-width: 0;
433
+ }
434
+
435
+ .alert-title {
436
+ font-size: 0.9375rem;
437
+ font-weight: 600;
438
+ line-height: 1.4;
439
+ margin: 0 0 0.25rem 0;
440
+ }
441
+
442
+ /* Reset heading styles */
443
+ .alert-title:where(h2, h3, h4, h5, h6) {
444
+ font-size: inherit;
445
+ margin: inherit;
446
+ }
447
+
448
+ .alert-body {
449
+ font-size: 0.875rem;
450
+ color: var(--ui-text-secondary);
451
+ line-height: 1.5;
452
+ }
453
+
454
+ .alert-body-hidden {
455
+ display: none;
456
+ }
457
+
458
+ .alert-actions {
459
+ display: flex;
460
+ flex-wrap: wrap;
461
+ align-items: center;
462
+ gap: 0.5rem;
463
+ margin-top: 0.75rem;
464
+ }
465
+
466
+ /* ========================================
467
+ EXPANDABLE STYLES
468
+ ======================================== */
469
+ .alert-title-button {
470
+ display: flex;
471
+ align-items: center;
472
+ justify-content: space-between;
473
+ width: 100%;
474
+ gap: 0.5rem;
475
+ padding: 0.125rem 0 0 0;
476
+ margin: 0 0 0.25rem 0;
477
+ background: none;
478
+ border: none;
479
+ cursor: pointer;
480
+ text-align: left;
481
+ color: inherit;
482
+ }
483
+
484
+ .alert-title-button:focus-visible {
485
+ outline: none;
486
+ border-radius: 4px;
487
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary) / 0.4);
488
+ }
489
+
490
+ :global([data-theme='dark']) .alert-title-button:focus-visible {
491
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary-light) / 0.5);
492
+ }
493
+
494
+ @media (prefers-color-scheme: dark) {
495
+ :global(:root:not([data-theme='light'])) .alert-title-button:focus-visible {
496
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary-light) / 0.5);
497
+ }
498
+ }
499
+
500
+ .alert-title-button .alert-title {
501
+ margin-bottom: 0;
502
+ }
503
+
504
+ .alert-expand-icon {
505
+ flex-shrink: 0;
506
+ color: var(--ui-text-tertiary);
507
+ transition: transform 0.2s ease;
508
+ }
509
+
510
+ /* ========================================
511
+ DISMISS BUTTON
512
+ ======================================== */
513
+ .alert-dismiss {
514
+ flex-shrink: 0;
515
+ display: flex;
516
+ align-items: center;
517
+ justify-content: center;
518
+ padding: 0.375rem;
519
+ margin: -0.25rem -0.25rem -0.25rem 0;
520
+ border: none;
521
+ border-radius: 8px;
522
+ background: transparent;
523
+ color: var(--ui-text-tertiary);
524
+ cursor: pointer;
525
+ transition: all 0.15s ease;
526
+ }
527
+
528
+ .alert-dismiss:hover {
529
+ color: var(--ui-text-primary);
530
+ background: var(--ui-bg-tertiary);
531
+ }
532
+
533
+ .alert-dismiss:focus-visible {
534
+ outline: none;
535
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary) / 0.4);
536
+ }
537
+
538
+ :global([data-theme='dark']) .alert-dismiss:focus-visible {
539
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary-light) / 0.5);
540
+ }
541
+
542
+ @media (prefers-color-scheme: dark) {
543
+ :global(:root:not([data-theme='light'])) .alert-dismiss:focus-visible {
544
+ box-shadow: 0 0 0 3px rgb(var(--ui-color-primary-light) / 0.5);
545
+ }
546
+ }
547
+
548
+ /* Slim variant dismiss button adjustments */
549
+ .alert-slim .alert-dismiss {
550
+ padding: 0.25rem;
551
+ margin: -0.125rem -0.25rem -0.125rem 0;
552
+ }
553
+
554
+ /* ========================================
555
+ REDUCED MOTION
556
+ ======================================== */
557
+ @media (prefers-reduced-motion: reduce) {
558
+ .alert,
559
+ .alert-dismiss,
560
+ .alert-title-button,
561
+ .alert-expand-icon {
562
+ transition: none;
563
+ }
564
+ }
565
+ </style>
@@ -0,0 +1,60 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { Status } from '../../types/index.js';
3
+ type AlertVariant = 'standard' | 'slim' | 'banner' | 'bordered';
4
+ type HeadingLevel = 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
5
+ interface Props {
6
+ /** Alert type/severity */
7
+ type?: Status | 'clinical';
8
+ /** Alert variant/style */
9
+ variant?: AlertVariant;
10
+ /** Optional title/heading */
11
+ title?: string;
12
+ /** Heading level for the title (for proper document structure) */
13
+ headingLevel?: HeadingLevel;
14
+ /** Whether the alert can be dismissed */
15
+ dismissible?: boolean;
16
+ /** Whether to show the icon */
17
+ showIcon?: boolean;
18
+ /** Whether the alert content is expandable (for longer content) */
19
+ expandable?: boolean;
20
+ /** Whether expandable alert starts expanded */
21
+ defaultExpanded?: boolean;
22
+ /** Additional CSS classes */
23
+ class?: string;
24
+ /** Alert content */
25
+ children?: Snippet;
26
+ /** Action buttons slot */
27
+ actions?: Snippet;
28
+ /** Close handler - receives a callback to manage focus */
29
+ onclose?: () => void;
30
+ /** Custom close button aria-label */
31
+ closeBtnAriaLabel?: string;
32
+ /** ID for the alert element */
33
+ id?: string;
34
+ }
35
+ /**
36
+ * Alert
37
+ *
38
+ * A comprehensive alert/banner component for displaying important messages and notifications.
39
+ * Critical for healthcare applications where users need to be aware of important information,
40
+ * warnings, or errors. Follows WCAG 2.1 and VA.gov design system best practices.
41
+ *
42
+ * @example
43
+ * <Alert type="warning" title="Allergy Alert">
44
+ * Patient has documented penicillin allergy.
45
+ * </Alert>
46
+ *
47
+ * @example
48
+ * <Alert type="error" dismissible onclose={() => showAlert = false}>
49
+ * Failed to save patient record. Please try again.
50
+ * </Alert>
51
+ *
52
+ * @example
53
+ * <Alert type="info" variant="slim">
54
+ * Your changes have been saved.
55
+ * </Alert>
56
+ */
57
+ declare const Alert: import("svelte").Component<Props, {}, "">;
58
+ type Alert = ReturnType<typeof Alert>;
59
+ export default Alert;
60
+ //# sourceMappingURL=Alert.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.svelte.d.ts","sourceRoot":"","sources":["../../../src/feedback/Alert/Alert.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGlD,KAAK,YAAY,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAChE,KAAK,YAAY,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC;AAE3D,UAAU,KAAK;IACd,0BAA0B;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IAC3B,0BAA0B;IAC1B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+BAA+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AA0IF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,QAAA,MAAM,KAAK,2CAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { default as Alert } from './Alert.svelte';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/feedback/Alert/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1 @@
1
+ export { default as Alert } from './Alert.svelte';