@happyvertical/smrt-ui 0.55.15 → 0.55.17

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 (138) hide show
  1. package/AGENTS.md +14 -0
  2. package/README.md +68 -0
  3. package/dist/components/calendar/Calendar.svelte +59 -56
  4. package/dist/components/calendar/CalendarView.svelte +79 -76
  5. package/dist/components/calendar/DayView.svelte +39 -36
  6. package/dist/components/chat/MessageBubble.svelte +26 -23
  7. package/dist/components/chat/ReactionPicker.svelte +10 -7
  8. package/dist/components/chat/TypingIndicator.svelte +12 -9
  9. package/dist/components/data/CollectionList.svelte +10 -7
  10. package/dist/components/data/CollectionToolbar.svelte +5 -2
  11. package/dist/components/data/DataTable.svelte +51 -48
  12. package/dist/components/data/ListSortSelect.svelte +8 -5
  13. package/dist/components/data/SortableHeader.svelte +9 -6
  14. package/dist/components/display/ConfidenceBadge.svelte +11 -8
  15. package/dist/components/display/CurrencyDisplay.svelte +7 -4
  16. package/dist/components/display/DateDisplay.svelte +6 -3
  17. package/dist/components/display/Icon.svelte +4 -1
  18. package/dist/components/display/StatusBadge.svelte +9 -6
  19. package/dist/components/feedback/Alert.svelte +9 -6
  20. package/dist/components/feedback/ConfirmDialog.svelte +13 -10
  21. package/dist/components/feedback/LoadingOverlay.svelte +35 -32
  22. package/dist/components/feedback/Meter.svelte +4 -1
  23. package/dist/components/feedback/Modal.svelte +20 -17
  24. package/dist/components/feedback/PhoneSheet.svelte +4 -1
  25. package/dist/components/feedback/Progress.svelte +8 -5
  26. package/dist/components/feedback/ProgressBar.svelte +13 -10
  27. package/dist/components/feedback/Spinner.svelte +4 -1
  28. package/dist/components/feedback/ToastViewport.svelte +17 -14
  29. package/dist/components/feedback/WorkingStrip.svelte +6 -3
  30. package/dist/components/forms/CameraCapture.svelte +6 -3
  31. package/dist/components/forms/Checkbox.svelte +10 -7
  32. package/dist/components/forms/Combobox.svelte +4 -1
  33. package/dist/components/forms/DatePicker.svelte +7 -2
  34. package/dist/components/forms/DictationButton.svelte +17 -14
  35. package/dist/components/forms/DictationStatus.svelte +12 -9
  36. package/dist/components/forms/ErrorSummary.svelte +4 -1
  37. package/dist/components/forms/FieldLabel.svelte +9 -6
  38. package/dist/components/forms/Fieldset.svelte +4 -1
  39. package/dist/components/forms/FilePicker.svelte +4 -1
  40. package/dist/components/forms/Form.svelte +1 -1
  41. package/dist/components/forms/FormActionBar.svelte +4 -1
  42. package/dist/components/forms/FormGroup.svelte +6 -3
  43. package/dist/components/forms/Input.svelte +14 -11
  44. package/dist/components/forms/InputGroup.svelte +5 -2
  45. package/dist/components/forms/Listbox.svelte +4 -1
  46. package/dist/components/forms/MultiSelect.svelte +4 -1
  47. package/dist/components/forms/Radio.svelte +8 -5
  48. package/dist/components/forms/RadioGroup.svelte +5 -2
  49. package/dist/components/forms/RangeSlider.svelte +4 -1
  50. package/dist/components/forms/RelationInput.svelte +7 -4
  51. package/dist/components/forms/SearchInput.svelte +5 -2
  52. package/dist/components/forms/SegmentedControl.svelte +5 -2
  53. package/dist/components/forms/Select.svelte +12 -9
  54. package/dist/components/forms/SignaturePad.svelte +6 -3
  55. package/dist/components/forms/Slider.svelte +4 -1
  56. package/dist/components/forms/StagedControlReview.svelte +15 -12
  57. package/dist/components/forms/Switch.svelte +7 -4
  58. package/dist/components/forms/TagsInput.svelte +4 -1
  59. package/dist/components/forms/Textarea.svelte +13 -10
  60. package/dist/components/forms/TimePicker.svelte +7 -2
  61. package/dist/components/forms/Toggle.svelte +13 -10
  62. package/dist/components/forms/ToggleButton.svelte +4 -1
  63. package/dist/components/layout/ActionGroup.svelte +4 -1
  64. package/dist/components/layout/Container.svelte +4 -1
  65. package/dist/components/layout/EmptyState.svelte +11 -8
  66. package/dist/components/layout/Footer.svelte +4 -1
  67. package/dist/components/layout/Grid.svelte +13 -10
  68. package/dist/components/layout/Header.svelte +4 -1
  69. package/dist/components/layout/Masthead.svelte +4 -1
  70. package/dist/components/layout/PageHeader.svelte +10 -7
  71. package/dist/components/layout/PageLayout.svelte +3 -0
  72. package/dist/components/layout/SummaryCard.svelte +9 -6
  73. package/dist/components/memberships/MembershipCard.svelte +5 -2
  74. package/dist/components/memberships/MembershipList.svelte +5 -2
  75. package/dist/components/nav/FilterChips.svelte +13 -10
  76. package/dist/components/nav/Tabs.svelte +28 -24
  77. package/dist/components/permissions/PermissionPicker.svelte +4 -1
  78. package/dist/components/roles/RoleBadge.svelte +8 -5
  79. package/dist/components/roles/RoleSelector.svelte +21 -18
  80. package/dist/components/theme/ThemeProvider.svelte +7 -4
  81. package/dist/components/ui/Accordion.svelte +4 -1
  82. package/dist/components/ui/AccordionItem.svelte +4 -1
  83. package/dist/components/ui/Avatar.svelte +10 -7
  84. package/dist/components/ui/Badge.svelte +4 -1
  85. package/dist/components/ui/Button.svelte +11 -8
  86. package/dist/components/ui/Card.svelte +7 -4
  87. package/dist/components/ui/Chip.svelte +12 -9
  88. package/dist/components/ui/Disclosure.svelte +4 -1
  89. package/dist/components/ui/Dropdown.svelte +17 -14
  90. package/dist/components/ui/IconToggle.svelte +10 -7
  91. package/dist/components/ui/IconToggle.svelte.d.ts +1 -1
  92. package/dist/components/ui/IconToggle.svelte.d.ts.map +1 -1
  93. package/dist/components/ui/IconToggleGroup.svelte +8 -5
  94. package/dist/components/ui/Pagination.svelte +11 -8
  95. package/dist/components/ui/Popover.svelte +5 -2
  96. package/dist/components/ui/Skeleton.svelte +10 -7
  97. package/dist/components/ui/Tooltip.svelte +12 -9
  98. package/dist/components/ui/Tree.svelte +10 -7
  99. package/dist/styles/layers.css +8 -0
  100. package/dist/styles/layers.d.ts +9 -0
  101. package/dist/styles/layers.d.ts.map +1 -0
  102. package/dist/styles/layers.js +8 -0
  103. package/dist/styles/tokens.css +27 -69
  104. package/dist/styles/unstyled.css +65 -0
  105. package/dist/svelte/playground/BaseControlsPreview.svelte +3 -0
  106. package/dist/svelte/playground/CalendarPreview.svelte +5 -2
  107. package/dist/svelte/playground/CapturePreview.svelte +3 -0
  108. package/dist/svelte/playground/CodeSelectorsPreview.svelte +3 -0
  109. package/dist/svelte/playground/CollectionsPreview.svelte +3 -0
  110. package/dist/svelte/playground/DataTablePreview.svelte +3 -0
  111. package/dist/svelte/playground/FeedbackPreview.svelte +3 -0
  112. package/dist/svelte/playground/InteractiveControlsPreview.svelte +3 -0
  113. package/dist/svelte/playground/StylelessPreview.svelte +110 -0
  114. package/dist/svelte/playground/StylelessPreview.svelte.d.ts +4 -0
  115. package/dist/svelte/playground/StylelessPreview.svelte.d.ts.map +1 -0
  116. package/dist/svelte/playground.d.ts.map +1 -1
  117. package/dist/svelte/playground.js +10 -0
  118. package/dist/test-support/setup.js +9 -0
  119. package/dist/theme/ThemeProvider.svelte +3 -0
  120. package/dist/themes/CUSTOM_THEME_GUIDE.md +25 -0
  121. package/dist/themes/README.md +25 -0
  122. package/dist/themes/ThemeProvider.svelte +11 -2
  123. package/dist/themes/ThemeProvider.svelte.d.ts.map +1 -1
  124. package/dist/themes/components/ColorSchemeToggle.svelte +17 -14
  125. package/dist/themes/components/ThemeSwitcher.svelte +14 -11
  126. package/dist/themes/create-theme.d.ts.map +1 -1
  127. package/dist/themes/create-theme.js +8 -5
  128. package/dist/themes/css-generator.d.ts.map +1 -1
  129. package/dist/themes/css-generator.js +5 -4
  130. package/dist/themes/required-tokens.generated.json +172 -0
  131. package/dist/themes/styles/base.css +4 -1
  132. package/dist/themes/styles/glass.css +4 -1
  133. package/dist/themes/styles/happyvertical.css +7 -3
  134. package/dist/themes/styles/smrt.css +4 -1
  135. package/dist/themes/styles/studio.css +4 -1
  136. package/dist/utils/theme/typography.d.ts +21 -21
  137. package/dist/utils/theme/typography.js +21 -21
  138. package/package.json +8 -2
@@ -97,7 +97,7 @@ const timeText = $derived(
97
97
  class="bubble bubble--{effectiveVariant}"
98
98
  class:bubble--own={effectiveOwn}
99
99
  role={hasHeader ? 'group' : undefined}
100
- aria-label={hasHeader ? groupLabel : undefined}
100
+ aria-label={hasHeader ? groupLabel : undefined} data-smrt-component="MessageBubble"
101
101
  >
102
102
  {#if hasHeader}
103
103
  <div class="bubble__header">
@@ -126,13 +126,15 @@ const timeText = $derived(
126
126
  </div>
127
127
 
128
128
  <style>
129
+ @layer smrt.reset, smrt.structure, smrt.theme;
130
+ @layer smrt.theme {
129
131
  .bubble {
130
132
  display: flex;
131
133
  flex-direction: column;
132
- gap: var(--smrt-spacing-1, 4px);
134
+ gap: var(--smrt-spacing-1);
133
135
  max-width: 75%;
134
- padding: var(--smrt-spacing-3, 12px) var(--smrt-spacing-4, 16px);
135
- border-radius: var(--smrt-radius-large, 12px);
136
+ padding: var(--smrt-spacing-3) var(--smrt-spacing-4);
137
+ border-radius: var(--smrt-radius-large);
136
138
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
137
139
  line-height: 1.4;
138
140
  word-break: break-word;
@@ -140,39 +142,39 @@ const timeText = $derived(
140
142
 
141
143
  /* default — a peer message; `own` is the current viewer's message. */
142
144
  .bubble--default {
143
- background: var(--smrt-color-surface-container, #f3f4f6);
144
- color: var(--smrt-color-on-surface, #1b1b1f);
145
- border-bottom-left-radius: var(--smrt-radius-small, 4px);
145
+ background: var(--smrt-color-surface-container);
146
+ color: var(--smrt-color-on-surface);
147
+ border-bottom-left-radius: var(--smrt-radius-small);
146
148
  }
147
149
  .bubble--default.bubble--own {
148
- background: var(--smrt-color-primary, #005ac1);
149
- color: var(--smrt-color-on-primary, #ffffff);
150
- border-bottom-right-radius: var(--smrt-radius-small, 4px);
151
- border-bottom-left-radius: var(--smrt-radius-large, 12px);
150
+ background: var(--smrt-color-primary);
151
+ color: var(--smrt-color-on-primary);
152
+ border-bottom-right-radius: var(--smrt-radius-small);
153
+ border-bottom-left-radius: var(--smrt-radius-large);
152
154
  }
153
155
 
154
156
  /* agent — assistant message, accented on the leading edge. */
155
157
  .bubble--agent {
156
- background: var(--smrt-color-tertiary-container, #ffd8e4);
157
- color: var(--smrt-color-on-tertiary-container, #31111d);
158
- border-bottom-left-radius: var(--smrt-radius-small, 4px);
159
- border-left: 3px solid var(--smrt-color-tertiary, #7d5260);
158
+ background: var(--smrt-color-tertiary-container);
159
+ color: var(--smrt-color-on-tertiary-container);
160
+ border-bottom-left-radius: var(--smrt-radius-small);
161
+ border-left: 3px solid var(--smrt-color-tertiary);
160
162
  }
161
163
  .bubble--agent.bubble--own {
162
164
  border-left: none;
163
- border-right: 3px solid var(--smrt-color-tertiary, #7d5260);
164
- border-bottom-right-radius: var(--smrt-radius-small, 4px);
165
- border-bottom-left-radius: var(--smrt-radius-large, 12px);
165
+ border-right: 3px solid var(--smrt-color-tertiary);
166
+ border-bottom-right-radius: var(--smrt-radius-small);
167
+ border-bottom-left-radius: var(--smrt-radius-large);
166
168
  }
167
169
 
168
170
  /* system — centered notice. */
169
171
  .bubble--system {
170
172
  max-width: 100%;
171
173
  background: transparent;
172
- color: var(--smrt-color-on-surface-variant, #43474e);
174
+ color: var(--smrt-color-on-surface-variant);
173
175
  text-align: center;
174
176
  font-size: var(--smrt-typography-body-small-size, 0.75rem);
175
- padding: var(--smrt-spacing-2, 6px) var(--smrt-spacing-4, 16px);
177
+ padding: var(--smrt-spacing-2) var(--smrt-spacing-4);
176
178
  border-radius: 0;
177
179
  align-self: center;
178
180
  }
@@ -186,7 +188,7 @@ const timeText = $derived(
186
188
  .bubble__header {
187
189
  display: flex;
188
190
  align-items: baseline;
189
- gap: var(--smrt-spacing-2, 8px);
191
+ gap: var(--smrt-spacing-2);
190
192
  }
191
193
  .bubble__author {
192
194
  font-weight: var(--smrt-typography-weight-semibold, 600);
@@ -194,7 +196,7 @@ const timeText = $derived(
194
196
  }
195
197
  .bubble__time {
196
198
  font-size: var(--smrt-typography-label-small-size, 0.6875rem);
197
- color: var(--smrt-color-on-surface-variant, #49454f);
199
+ color: var(--smrt-color-on-surface-variant);
198
200
  opacity: 0.8;
199
201
  }
200
202
 
@@ -211,6 +213,7 @@ const timeText = $derived(
211
213
  .bubble__actions {
212
214
  display: flex;
213
215
  flex-wrap: wrap;
214
- gap: var(--smrt-spacing-1, 4px);
216
+ gap: var(--smrt-spacing-1);
215
217
  }
218
+ }
216
219
  </style>
@@ -61,7 +61,7 @@ function nameFor(emoji: string): string {
61
61
  </script>
62
62
 
63
63
  {#if isOpen}
64
- <div class="reactions" role="group" aria-label={groupLabel}>
64
+ <div class="reactions" role="group" aria-label={groupLabel} data-smrt-component="ReactionPicker">
65
65
  {#each emojis as emoji (emoji)}
66
66
  <button
67
67
  type="button"
@@ -76,14 +76,16 @@ function nameFor(emoji: string): string {
76
76
  {/if}
77
77
 
78
78
  <style>
79
+ @layer smrt.reset, smrt.structure, smrt.theme;
80
+ @layer smrt.theme {
79
81
  .reactions {
80
82
  display: inline-flex;
81
83
  flex-wrap: wrap;
82
- gap: var(--smrt-spacing-1, 4px);
83
- padding: var(--smrt-spacing-1, 4px);
84
+ gap: var(--smrt-spacing-1);
85
+ padding: var(--smrt-spacing-1);
84
86
  max-width: 16rem;
85
- border-radius: var(--smrt-radius-large, 12px);
86
- background: var(--smrt-color-surface-container, #f3edf7);
87
+ border-radius: var(--smrt-radius-large);
88
+ background: var(--smrt-color-surface-container);
87
89
  }
88
90
 
89
91
  .reactions__btn {
@@ -94,7 +96,7 @@ function nameFor(emoji: string): string {
94
96
  width: 2rem;
95
97
  height: 2rem;
96
98
  border: none;
97
- border-radius: var(--smrt-radius-full, 9999px);
99
+ border-radius: var(--smrt-radius-full);
98
100
  background: none;
99
101
  font-size: var(--smrt-typography-title-medium-size, 1.1rem);
100
102
  line-height: 1;
@@ -102,7 +104,7 @@ function nameFor(emoji: string): string {
102
104
  transition: transform 0.1s ease, background 0.1s ease;
103
105
  }
104
106
  .reactions__btn:hover {
105
- background: var(--smrt-color-surface-container-highest, #e6e0e9);
107
+ background: var(--smrt-color-surface-container-highest);
106
108
  transform: scale(1.15);
107
109
  }
108
110
  .reactions__btn:focus-visible {
@@ -118,4 +120,5 @@ function nameFor(emoji: string): string {
118
120
  transform: none;
119
121
  }
120
122
  }
123
+ }
121
124
  </style>
@@ -39,7 +39,7 @@ const text = $derived.by(() => {
39
39
  </script>
40
40
 
41
41
  {#if show}
42
- <div class="typing" role="status" aria-live="polite">
42
+ <div class="typing" role="status" aria-live="polite" data-smrt-component="TypingIndicator">
43
43
  <span class="typing__text">{text}</span>
44
44
  <span class="typing__dots" aria-hidden="true">
45
45
  <span class="typing__dot"></span>
@@ -50,32 +50,34 @@ const text = $derived.by(() => {
50
50
  {/if}
51
51
 
52
52
  <style>
53
+ @layer smrt.reset, smrt.structure, smrt.theme;
54
+ @layer smrt.theme {
53
55
  .typing {
54
56
  display: inline-flex;
55
57
  align-items: center;
56
- gap: var(--smrt-spacing-2, 8px);
57
- padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-3, 12px);
58
- border-radius: var(--smrt-radius-large, 12px);
59
- background: var(--smrt-color-surface-container, #f3edf7);
58
+ gap: var(--smrt-spacing-2);
59
+ padding: var(--smrt-spacing-2) var(--smrt-spacing-3);
60
+ border-radius: var(--smrt-radius-large);
61
+ background: var(--smrt-color-surface-container);
60
62
  width: fit-content;
61
63
  }
62
64
 
63
65
  .typing__text {
64
66
  font-size: var(--smrt-typography-body-small-size, 0.75rem);
65
- color: var(--smrt-color-on-surface-variant, #49454f);
67
+ color: var(--smrt-color-on-surface-variant);
66
68
  white-space: nowrap;
67
69
  }
68
70
 
69
71
  .typing__dots {
70
72
  display: inline-flex;
71
- gap: var(--smrt-spacing-1, 4px);
73
+ gap: var(--smrt-spacing-1);
72
74
  }
73
75
 
74
76
  .typing__dot {
75
77
  width: 0.5rem;
76
78
  height: 0.5rem;
77
- border-radius: var(--smrt-radius-full, 9999px);
78
- background: var(--smrt-color-on-surface-variant, #49454f);
79
+ border-radius: var(--smrt-radius-full);
80
+ background: var(--smrt-color-on-surface-variant);
79
81
  opacity: 0.5;
80
82
  animation: smrt-typing-bounce 1.2s ease-in-out infinite;
81
83
  }
@@ -104,4 +106,5 @@ const text = $derived.by(() => {
104
106
  animation: none;
105
107
  }
106
108
  }
109
+ }
107
110
  </style>
@@ -81,11 +81,11 @@ function toggle(key: string | number) {
81
81
  </script>
82
82
 
83
83
  {#if loading}
84
- <div class="loading" role="status"><span class="spinner" aria-hidden="true"></span>Loading…</div>
84
+ <div class="loading" role="status" data-smrt-component="CollectionList"><span class="spinner" aria-hidden="true"></span>Loading…</div>
85
85
  {:else if items.length === 0}
86
- <div class="empty">{#if empty}{@render empty()}{:else}No items available{/if}</div>
86
+ <div class="empty" data-smrt-component="CollectionList">{#if empty}{@render empty()}{:else}No items available{/if}</div>
87
87
  {:else}
88
- <ul class="collection collection--{layout} {className}">
88
+ <ul class="collection collection--{layout} {className}" data-smrt-component="CollectionList">
89
89
  {#each items as entry, index (keyOf(entry, index))}
90
90
  {@const key = keyOf(entry, index)}
91
91
  {@const isSelected = selected.has(key)}
@@ -108,6 +108,8 @@ function toggle(key: string | number) {
108
108
  {/if}
109
109
 
110
110
  <style>
111
+ @layer smrt.reset, smrt.structure, smrt.theme;
112
+ @layer smrt.theme {
111
113
  .collection { display: grid; gap: var(--smrt-spacing-2); margin: 0; padding: 0; list-style: none; }
112
114
  .collection--grid { grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr)); }
113
115
  li { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--smrt-spacing-3); min-width: 0; padding: var(--smrt-spacing-3); border: var(--smrt-card-border, 1px solid var(--smrt-color-outline-variant)); border-radius: var(--smrt-radius-medium); background: var(--smrt-card-background, var(--smrt-color-surface)); color: var(--smrt-color-on-surface); }
@@ -121,18 +123,19 @@ function toggle(key: string | number) {
121
123
  .main strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--smrt-typography-title-small-font); }
122
124
  .main span { color: var(--smrt-color-on-surface-variant); }
123
125
  .actions { position: relative; z-index: 1; display: flex; gap: var(--smrt-spacing-1); }
124
- .collection--divided { --collection-divider: color-mix(in srgb, var(--smrt-color-outline-variant) 55%, transparent); gap: 0; }
126
+ .collection--divided { --smrt-collection-list-divider: color-mix(in srgb, var(--smrt-color-outline-variant) 55%, transparent); gap: 0; }
125
127
  .collection--divided li { padding-inline: 0; border: none; border-radius: 0; background: transparent; }
126
- .collection--divided li + li { border-block-start: 1px solid var(--collection-divider); }
127
- .collection--divided li.selected { border-color: var(--collection-divider); background: transparent; }
128
+ .collection--divided li + li { border-block-start: 1px solid var(--smrt-collection-list-divider); }
129
+ .collection--divided li.selected { border-color: var(--smrt-collection-list-divider); background: transparent; }
128
130
  .collection--gallery { grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr)); }
129
131
  .collection--gallery li { display: block; padding: 0; }
130
132
  .collection--gallery .main { gap: 0; }
131
- .collection--gallery .select, .collection--gallery .actions { position: absolute; top: var(--smrt-spacing-1); z-index: 2; min-width: 2.75rem; min-height: 2.75rem; align-items: center; justify-content: center; border-radius: var(--smrt-radius-full, 999px); background: color-mix(in srgb, var(--smrt-color-surface) 82%, transparent); }
133
+ .collection--gallery .select, .collection--gallery .actions { position: absolute; top: var(--smrt-spacing-1); z-index: 2; min-width: 2.75rem; min-height: 2.75rem; align-items: center; justify-content: center; border-radius: var(--smrt-radius-full); background: color-mix(in srgb, var(--smrt-color-surface) 82%, transparent); }
132
134
  .collection--gallery .select { left: var(--smrt-spacing-1); }
133
135
  .collection--gallery .actions { right: var(--smrt-spacing-1); }
134
136
  .loading, .empty { display: flex; min-height: 8rem; align-items: center; justify-content: center; gap: var(--smrt-spacing-2); color: var(--smrt-color-on-surface-variant); }
135
137
  .spinner { width: 1rem; height: 1rem; border: 2px solid var(--smrt-color-outline-variant); border-top-color: var(--smrt-color-primary); border-radius: 50%; animation: spin .8s linear infinite; }
136
138
  @keyframes spin { to { transform: rotate(360deg); } }
137
139
  @media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 1.6s; } }
140
+ }
138
141
  </style>
@@ -259,7 +259,7 @@ onDestroy(() => surfaceRegistration?.cleanup());
259
259
  class="toolbar {className}"
260
260
  class:toolbar--highlighted={surfaceHighlighted}
261
261
  role="search"
262
- tabindex="-1"
262
+ tabindex="-1" data-smrt-component="CollectionToolbar"
263
263
  >
264
264
  <div class="search">
265
265
  <Input type="search" name="collection-search" aria-label={searchLabel} placeholder={searchPlaceholder} value={controllerState?.search ?? search} oninput={(event) => changeSearch(event.currentTarget.value)} />
@@ -275,11 +275,14 @@ onDestroy(() => surfaceRegistration?.cleanup());
275
275
  </div>
276
276
 
277
277
  <style>
278
+ @layer smrt.reset, smrt.structure, smrt.theme;
279
+ @layer smrt.theme {
278
280
  .toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--smrt-spacing-2); padding: var(--smrt-spacing-2) 0; color: var(--smrt-color-on-surface); }
279
- .toolbar--highlighted { outline: 2px solid var(--smrt-color-primary, #2563eb); outline-offset: 3px; }
281
+ .toolbar--highlighted { outline: 2px solid var(--smrt-color-primary); outline-offset: 3px; }
280
282
  .search { flex: 1 1 14rem; max-width: 24rem; }
281
283
  .filters, .actions, .bulk { display: flex; align-items: center; gap: var(--smrt-spacing-2); }
282
284
  .bulk { padding: var(--smrt-spacing-1) var(--smrt-spacing-2); border-radius: var(--smrt-radius-small); background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); }
283
285
  .count { color: var(--smrt-color-on-surface-variant); font: var(--smrt-typography-label-medium-font); }
284
286
  .spacer { flex: 1; }
287
+ }
285
288
  </style>
@@ -1444,7 +1444,7 @@ $effect(() => {
1444
1444
  });
1445
1445
  </script>
1446
1446
 
1447
- {#if toolbar}<div class="data-table-toolbar">{@render toolbar()}</div>{/if}
1447
+ {#if toolbar}<div class="data-table-toolbar" data-smrt-component="DataTable">{@render toolbar()}</div>{/if}
1448
1448
  <!-- svelte-ignore a11y_no_noninteractive_tabindex: the region provides horizontal or virtual keyboard scrolling. -->
1449
1449
  <div
1450
1450
  bind:this={tableContainer}
@@ -1473,7 +1473,7 @@ $effect(() => {
1473
1473
  onkeydown={(event) => {
1474
1474
  handleVirtualizationKeydown(event);
1475
1475
  if (!event.defaultPrevented) handleOverflowKeydown(event);
1476
- }}
1476
+ }} data-smrt-component="DataTable"
1477
1477
  >
1478
1478
  <table role={cardsRole('table')}
1479
1479
  class="data-table {sizeClasses[size]}"
@@ -1486,7 +1486,7 @@ $effect(() => {
1486
1486
  aria-rowcount={virtualizationWindow.enabled
1487
1487
  ? virtualRowCount + headerRowCount + structuralRowCount
1488
1488
  : undefined}
1489
- style={`--data-table-caption-height: ${virtualCaptionHeight}px`}
1489
+ style={`--smrt-data-table-caption-height: ${virtualCaptionHeight}px`}
1490
1490
  >
1491
1491
  {#if caption}
1492
1492
  <caption bind:this={tableCaption} class="data-table__caption">{caption}</caption>
@@ -1913,7 +1913,7 @@ $effect(() => {
1913
1913
  {/if}
1914
1914
  </div>
1915
1915
  {#if hasHorizontalOverflow}
1916
- <div class="data-table__overflow-cue" aria-hidden="true">
1916
+ <div class="data-table__overflow-cue" aria-hidden="true" data-smrt-component="DataTable">
1917
1917
  {#if canScrollLeft}<span>← {t(M['ui.data_table.more_columns'])}</span>{/if}
1918
1918
  {#if canScrollRight}<span>{t(M['ui.data_table.more_columns'])} →</span>{/if}
1919
1919
  </div>
@@ -1921,6 +1921,8 @@ $effect(() => {
1921
1921
  {#if tableState.pageSize && totalPages && totalPages > 1}<Pagination currentPage={tableState.page} {totalPages} onPageChange={handlePageChange} aria-label={t(M['ui.data_table.pagination'])} />{/if}
1922
1922
 
1923
1923
  <style>
1924
+ @layer smrt.reset, smrt.structure, smrt.theme;
1925
+ @layer smrt.theme {
1924
1926
  .data-table-container {
1925
1927
  position: relative;
1926
1928
  width: 100%;
@@ -1928,12 +1930,12 @@ $effect(() => {
1928
1930
  }
1929
1931
 
1930
1932
  .data-table-container--overflowing:focus-visible {
1931
- outline: 2px solid var(--smrt-color-primary, #3b82f6);
1933
+ outline: 2px solid var(--smrt-color-primary);
1932
1934
  outline-offset: 2px;
1933
1935
  }
1934
1936
 
1935
1937
  .data-table-container--highlighted {
1936
- outline: 2px solid var(--smrt-color-primary, #2563eb);
1938
+ outline: 2px solid var(--smrt-color-primary);
1937
1939
  outline-offset: 3px;
1938
1940
  }
1939
1941
 
@@ -1941,9 +1943,9 @@ $effect(() => {
1941
1943
  display: flex;
1942
1944
  justify-content: space-between;
1943
1945
  padding: var(--smrt-spacing-2, 0.5rem) var(--smrt-spacing-3, 0.75rem);
1944
- border-top: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
1945
- background: var(--smrt-color-surface-container-low, #f9fafb);
1946
- color: var(--smrt-color-on-surface-variant, #6b7280);
1946
+ border-top: 1px solid var(--smrt-color-outline-variant);
1947
+ background: var(--smrt-color-surface-container-low);
1948
+ color: var(--smrt-color-on-surface-variant);
1947
1949
  font-size: var(--smrt-typography-label-small-size, 0.75rem);
1948
1950
  font-weight: var(--smrt-typography-weight-medium, 500);
1949
1951
  pointer-events: none;
@@ -1971,7 +1973,7 @@ $effect(() => {
1971
1973
 
1972
1974
  .data-table-container--sticky.data-table-container--virtualized .data-table__head {
1973
1975
  position: sticky;
1974
- top: var(--data-table-caption-height, 0px);
1976
+ top: var(--smrt-data-table-caption-height, 0px);
1975
1977
  z-index: 1;
1976
1978
  }
1977
1979
 
@@ -1981,21 +1983,21 @@ $effect(() => {
1981
1983
  border-spacing: 0;
1982
1984
  font-family: var(--smrt-font-family, inherit);
1983
1985
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
1984
- color: var(--smrt-color-on-surface, #111827);
1985
- background: var(--smrt-color-surface, #ffffff);
1986
+ color: var(--smrt-color-on-surface);
1987
+ background: var(--smrt-color-surface);
1986
1988
  }
1987
1989
 
1988
1990
  .data-table__caption {
1989
1991
  padding: var(--smrt-spacing-3, 0.75rem);
1990
1992
  font-weight: var(--smrt-typography-weight-medium, 500);
1991
1993
  text-align: left;
1992
- color: var(--smrt-color-on-surface-variant, #6b7280);
1994
+ color: var(--smrt-color-on-surface-variant);
1993
1995
  caption-side: top;
1994
1996
  }
1995
1997
 
1996
1998
  /* Header */
1997
1999
  .data-table__head {
1998
- background: var(--smrt-color-surface-container, #f3f4f6);
2000
+ background: var(--smrt-color-surface-container);
1999
2001
  }
2000
2002
 
2001
2003
  .data-table-container--sticky .data-table__head {
@@ -2005,7 +2007,7 @@ $effect(() => {
2005
2007
  }
2006
2008
 
2007
2009
  .data-table__row--header {
2008
- border-bottom: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
2010
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
2009
2011
  }
2010
2012
 
2011
2013
  .data-table__cell--header {
@@ -2014,7 +2016,7 @@ $effect(() => {
2014
2016
  font-weight: var(--smrt-typography-weight-semibold, 600);
2015
2017
  text-align: left;
2016
2018
  white-space: nowrap;
2017
- color: var(--smrt-color-on-surface, #111827);
2019
+ color: var(--smrt-color-on-surface);
2018
2020
  }
2019
2021
 
2020
2022
  .data-table__cell--sortable {
@@ -2042,7 +2044,7 @@ $effect(() => {
2042
2044
  }
2043
2045
 
2044
2046
  .data-table__cell--header-group {
2045
- color: var(--smrt-color-on-surface-variant, #6b7280);
2047
+ color: var(--smrt-color-on-surface-variant);
2046
2048
  font: var(--smrt-typography-label-medium-font);
2047
2049
  letter-spacing: 0.02em;
2048
2050
  }
@@ -2065,17 +2067,17 @@ $effect(() => {
2065
2067
  right: 0.3rem;
2066
2068
  width: 1px;
2067
2069
  height: 60%;
2068
- background: var(--smrt-color-outline, #9ca3af);
2070
+ background: var(--smrt-color-outline);
2069
2071
  content: '';
2070
2072
  }
2071
2073
 
2072
2074
  .data-table__resize-handle:focus-visible {
2073
- outline: 2px solid var(--smrt-color-primary, #3b82f6);
2075
+ outline: 2px solid var(--smrt-color-primary);
2074
2076
  outline-offset: -2px;
2075
2077
  }
2076
2078
 
2077
2079
  .data-table__sort-button:hover {
2078
- color: var(--smrt-color-primary, #3b82f6);
2080
+ color: var(--smrt-color-primary);
2079
2081
  }
2080
2082
 
2081
2083
  .data-table__sort-icon {
@@ -2085,16 +2087,16 @@ $effect(() => {
2085
2087
 
2086
2088
  .data-table__cell--sorted .data-table__sort-icon {
2087
2089
  opacity: 1;
2088
- color: var(--smrt-color-primary, #3b82f6);
2090
+ color: var(--smrt-color-primary);
2089
2091
  }
2090
2092
 
2091
2093
  /* Body */
2092
2094
  .data-table__body {
2093
- background: var(--smrt-color-surface, #ffffff);
2095
+ background: var(--smrt-color-surface);
2094
2096
  }
2095
2097
 
2096
2098
  .data-table__row {
2097
- border-bottom: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
2099
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
2098
2100
  transition: background-color var(--smrt-duration-fast, 150ms) var(--smrt-easing-standard, ease);
2099
2101
  }
2100
2102
 
@@ -2103,17 +2105,17 @@ $effect(() => {
2103
2105
  border: 0;
2104
2106
  }
2105
2107
 
2106
- .data-table--hoverable .data-table__row:hover:not(.data-table__row--loading):not(.data-table__row--empty) {
2107
- background: var(--smrt-color-surface-container-low, #f9fafb);
2108
+ .data-table--hoverable .data-table__row:hover:not(.data-table__row--loading):not(.data-table__row--empty):not(.data-table__row--selected) {
2109
+ background: var(--smrt-color-surface-container-low);
2108
2110
  }
2109
2111
 
2110
2112
  .data-table__row--selected {
2111
- background: var(--smrt-color-primary-container, #dbeafe) !important;
2113
+ background: var(--smrt-color-primary-container);
2112
2114
  }
2113
2115
 
2114
- .data-table--striped:not(.data-table--virtualized) .data-table__row:nth-child(even),
2115
- .data-table__row--striped {
2116
- background: var(--smrt-color-surface-container-lowest, #fafafa);
2116
+ .data-table--striped:not(.data-table--virtualized) .data-table__row:nth-child(even):not(.data-table__row--selected),
2117
+ .data-table__row--striped:not(.data-table__row--selected) {
2118
+ background: var(--smrt-color-surface-container-lowest);
2117
2119
  }
2118
2120
 
2119
2121
  .data-table__row--interactive {
@@ -2121,12 +2123,12 @@ $effect(() => {
2121
2123
  }
2122
2124
 
2123
2125
  .data-table__row--interactive:focus-visible {
2124
- outline: 2px solid var(--smrt-color-primary, #3b82f6);
2126
+ outline: 2px solid var(--smrt-color-primary);
2125
2127
  outline-offset: -2px;
2126
2128
  }
2127
2129
 
2128
2130
  .data-table-container--virtualized .data-table__row:focus-visible {
2129
- outline: 2px solid var(--smrt-color-primary, #3b82f6);
2131
+ outline: 2px solid var(--smrt-color-primary);
2130
2132
  outline-offset: -2px;
2131
2133
  }
2132
2134
 
@@ -2139,18 +2141,18 @@ $effect(() => {
2139
2141
  .data-table__cell--pinned-end {
2140
2142
  position: sticky;
2141
2143
  z-index: 1;
2142
- background: var(--smrt-color-surface, #ffffff);
2144
+ background: var(--smrt-color-surface);
2143
2145
  }
2144
2146
 
2145
2147
  .data-table__cell--header.data-table__cell--pinned-start,
2146
2148
  .data-table__cell--header.data-table__cell--pinned-end {
2147
2149
  z-index: 3;
2148
- background: var(--smrt-color-surface-container, #f3f4f6);
2150
+ background: var(--smrt-color-surface-container);
2149
2151
  }
2150
2152
 
2151
2153
  .data-table__row--selected .data-table__cell--pinned-start,
2152
2154
  .data-table__row--selected .data-table__cell--pinned-end {
2153
- background: var(--smrt-color-primary-container, #dbeafe);
2155
+ background: var(--smrt-color-primary-container);
2154
2156
  }
2155
2157
 
2156
2158
  .data-table__cell--checkbox {
@@ -2163,7 +2165,7 @@ $effect(() => {
2163
2165
  .data-table__expand-button:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 2px; }
2164
2166
  .data-table__cell--expanded { padding: var(--smrt-spacing-4); background: var(--smrt-color-surface-container-low); }
2165
2167
  .data-table__footer { border-top: 2px solid var(--smrt-color-outline-variant); font-weight: var(--smrt-typography-weight-medium); }
2166
- .data-table__row--structural { background: var(--smrt-color-surface-container-low, #f9fafb); }
2168
+ .data-table__row--structural { background: var(--smrt-color-surface-container-low); }
2167
2169
  .data-table__row--footer { border-top: 2px solid var(--smrt-color-outline-variant); }
2168
2170
  .data-table__cell--structural-label { font-weight: var(--smrt-typography-weight-semibold, 600); }
2169
2171
 
@@ -2171,7 +2173,7 @@ $effect(() => {
2171
2173
  width: 18px;
2172
2174
  height: 18px;
2173
2175
  cursor: pointer;
2174
- accent-color: var(--smrt-color-primary, #3b82f6);
2176
+ accent-color: var(--smrt-color-primary);
2175
2177
  }
2176
2178
 
2177
2179
  /* Loading */
@@ -2187,15 +2189,15 @@ $effect(() => {
2187
2189
  align-items: center;
2188
2190
  justify-content: center;
2189
2191
  gap: var(--smrt-spacing-2, 0.5rem);
2190
- color: var(--smrt-color-on-surface-variant, #6b7280);
2192
+ color: var(--smrt-color-on-surface-variant);
2191
2193
  }
2192
2194
 
2193
2195
  .data-table__spinner {
2194
2196
  width: 20px;
2195
2197
  height: 20px;
2196
- border: 2px solid var(--smrt-color-outline-variant, #e5e7eb);
2197
- border-top-color: var(--smrt-color-primary, #3b82f6);
2198
- border-radius: var(--smrt-radius-full, 9999px);
2198
+ border: 2px solid var(--smrt-color-outline-variant);
2199
+ border-top-color: var(--smrt-color-primary);
2200
+ border-radius: var(--smrt-radius-full);
2199
2201
  animation: spin 0.8s linear infinite;
2200
2202
  }
2201
2203
 
@@ -2206,7 +2208,7 @@ $effect(() => {
2206
2208
  }
2207
2209
 
2208
2210
  .data-table__empty-state {
2209
- color: var(--smrt-color-on-surface-variant, #6b7280);
2211
+ color: var(--smrt-color-on-surface-variant);
2210
2212
  }
2211
2213
 
2212
2214
  .data-table__error-state,
@@ -2216,17 +2218,17 @@ $effect(() => {
2216
2218
  justify-content: center;
2217
2219
  flex-wrap: wrap;
2218
2220
  gap: var(--smrt-spacing-3, 0.75rem);
2219
- color: var(--smrt-color-on-surface-variant, #6b7280);
2221
+ color: var(--smrt-color-on-surface-variant);
2220
2222
  }
2221
2223
 
2222
2224
  .data-table__error-state,
2223
2225
  .data-table__async-status--error {
2224
- color: var(--smrt-color-error, #b3261e);
2226
+ color: var(--smrt-color-error);
2225
2227
  }
2226
2228
 
2227
2229
  .data-table__async-status {
2228
2230
  padding: var(--smrt-spacing-3, 0.75rem);
2229
- border-top: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
2231
+ border-top: 1px solid var(--smrt-color-outline-variant);
2230
2232
  font: var(--smrt-typography-body-small-font);
2231
2233
  }
2232
2234
 
@@ -2241,7 +2243,7 @@ $effect(() => {
2241
2243
  }
2242
2244
 
2243
2245
  .data-table__retry-button:focus-visible {
2244
- outline: 2px solid var(--smrt-color-primary, #3b82f6);
2246
+ outline: 2px solid var(--smrt-color-primary);
2245
2247
  outline-offset: 2px;
2246
2248
  }
2247
2249
 
@@ -2308,13 +2310,13 @@ $effect(() => {
2308
2310
  display: block;
2309
2311
  font-size: var(--smrt-typography-label-small-size, 0.75rem);
2310
2312
  font-weight: 600;
2311
- color: var(--smrt-color-on-surface-variant, #4b5563);
2313
+ color: var(--smrt-color-on-surface-variant);
2312
2314
  }
2313
2315
  .data-table-container--phone-cards .data-table__row {
2314
2316
  display: grid;
2315
2317
  gap: var(--smrt-spacing-1, 0.35rem);
2316
2318
  padding: var(--smrt-spacing-3, 0.85rem) var(--smrt-spacing-4, 1rem);
2317
- border-bottom: 1px solid var(--smrt-color-outline-variant, #e5e7eb);
2319
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
2318
2320
  }
2319
2321
  .data-table-container--phone-cards .data-table__cell {
2320
2322
  display: block;
@@ -2331,10 +2333,11 @@ $effect(() => {
2331
2333
  animation: none;
2332
2334
  }
2333
2335
  }
2334
- .data-table-container[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min, 48px); }
2336
+ .data-table-container[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
2335
2337
  .data-table-container[data-density='comfortable'] { --smrt-control-target-min: 0px; }
2336
2338
  .data-table__sort-button { min-height: var(--smrt-control-target-min, 0px); min-width: var(--smrt-control-target-min, 0px); }
2337
2339
  .data-table-container--narrow .data-table { table-layout: fixed; }
2338
2340
  .data-table-container--narrow .data-table__cell { white-space: normal; overflow-wrap: anywhere; }
2339
2341
  .data-table-container--narrow .data-table__sort-button { max-width: 100%; text-align: left; white-space: normal; overflow-wrap: anywhere; }
2342
+ }
2340
2343
  </style>
@@ -84,7 +84,7 @@ function handleChange(event: Event) {
84
84
  }
85
85
  </script>
86
86
 
87
- <div class={`list-sort-select ${className}`}>
87
+ <div class={`list-sort-select ${className}`} data-smrt-component="ListSortSelect">
88
88
  <label class="list-sort-select__label" for={id}>{label}</label>
89
89
  <select
90
90
  {id}
@@ -99,6 +99,8 @@ function handleChange(event: Event) {
99
99
  </div>
100
100
 
101
101
  <style>
102
+ @layer smrt.reset, smrt.structure, smrt.theme;
103
+ @layer smrt.theme {
102
104
  .list-sort-select {
103
105
  display: inline-flex;
104
106
  align-items: center;
@@ -106,16 +108,17 @@ function handleChange(event: Event) {
106
108
  }
107
109
  .list-sort-select__label {
108
110
  font-size: 0.875rem;
109
- color: var(--color-text-secondary, inherit);
111
+ color: var(--smrt-color-on-surface-variant, inherit);
110
112
  white-space: nowrap;
111
113
  }
112
114
  .list-sort-select__control {
113
115
  min-height: 2.75rem;
114
116
  padding: 0.25rem 0.5rem;
115
- border: 1px solid var(--color-border, currentColor);
116
- border-radius: var(--radius-md, 0.375rem);
117
- background: var(--color-surface, transparent);
117
+ border: 1px solid var(--smrt-color-outline-variant, currentColor);
118
+ border-radius: var(--smrt-radius-md, 0.375rem);
119
+ background: var(--smrt-color-surface, transparent);
118
120
  color: inherit;
119
121
  font: inherit;
120
122
  }
123
+ }
121
124
  </style>