@happyvertical/smrt-ui 0.55.16 → 0.55.18

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 (166) hide show
  1. package/AGENTS.md +14 -0
  2. package/README.md +75 -0
  3. package/dist/components/calendar/Calendar.svelte +59 -56
  4. package/dist/components/calendar/CalendarView.svelte +80 -77
  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 +12 -9
  8. package/dist/components/chat/TypingIndicator.svelte +12 -9
  9. package/dist/components/data/CollectionList.svelte +11 -8
  10. package/dist/components/data/CollectionToolbar.svelte +5 -2
  11. package/dist/components/data/DataTable.svelte +74 -59
  12. package/dist/components/data/ListSortSelect.svelte +8 -5
  13. package/dist/components/data/SortableHeader.svelte +10 -7
  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 +12 -8
  20. package/dist/components/feedback/ConfirmDialog.svelte +13 -10
  21. package/dist/components/feedback/LoadingOverlay.svelte +37 -34
  22. package/dist/components/feedback/Meter.svelte +4 -1
  23. package/dist/components/feedback/Modal.svelte +26 -21
  24. package/dist/components/feedback/PhoneSheet.svelte +6 -3
  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 +18 -15
  29. package/dist/components/feedback/WorkingStrip.svelte +6 -3
  30. package/dist/components/forms/CameraCapture.svelte +8 -5
  31. package/dist/components/forms/Checkbox.svelte +11 -8
  32. package/dist/components/forms/Combobox.svelte +5 -2
  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 +5 -2
  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 +22 -15
  44. package/dist/components/forms/InputGroup.svelte +6 -3
  45. package/dist/components/forms/Listbox.svelte +5 -2
  46. package/dist/components/forms/MultiSelect.svelte +4 -1
  47. package/dist/components/forms/Radio.svelte +9 -6
  48. package/dist/components/forms/RadioGroup.svelte +5 -2
  49. package/dist/components/forms/RangeSlider.svelte +5 -2
  50. package/dist/components/forms/RelationInput.svelte +7 -4
  51. package/dist/components/forms/SearchInput.svelte +7 -4
  52. package/dist/components/forms/SegmentedControl.svelte +6 -3
  53. package/dist/components/forms/Select.svelte +20 -13
  54. package/dist/components/forms/SignaturePad.svelte +8 -5
  55. package/dist/components/forms/Slider.svelte +5 -2
  56. package/dist/components/forms/StagedControlReview.svelte +15 -12
  57. package/dist/components/forms/Switch.svelte +8 -5
  58. package/dist/components/forms/TagsInput.svelte +5 -2
  59. package/dist/components/forms/Textarea.svelte +20 -13
  60. package/dist/components/forms/TimePicker.svelte +7 -2
  61. package/dist/components/forms/Toggle.svelte +14 -11
  62. package/dist/components/forms/ToggleButton.svelte +5 -2
  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 +12 -9
  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 +75 -41
  77. package/dist/components/permissions/PermissionPicker.svelte +5 -2
  78. package/dist/components/roles/RoleBadge.svelte +8 -5
  79. package/dist/components/roles/RoleSelector.svelte +22 -19
  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 +5 -2
  83. package/dist/components/ui/Avatar.svelte +10 -7
  84. package/dist/components/ui/Badge.svelte +6 -2
  85. package/dist/components/ui/Button.svelte +49 -37
  86. package/dist/components/ui/Card.svelte +18 -14
  87. package/dist/components/ui/Chip.svelte +41 -14
  88. package/dist/components/ui/Disclosure.svelte +5 -2
  89. package/dist/components/ui/Dropdown.svelte +33 -25
  90. package/dist/components/ui/IconToggle.svelte +12 -9
  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 +9 -6
  96. package/dist/components/ui/Skeleton.svelte +10 -7
  97. package/dist/components/ui/Tooltip.svelte +13 -9
  98. package/dist/components/ui/Tree.svelte +12 -9
  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 +40 -0
  121. package/dist/themes/README.md +151 -0
  122. package/dist/themes/ThemeProvider.svelte +181 -12
  123. package/dist/themes/ThemeProvider.svelte.d.ts +7 -2
  124. package/dist/themes/ThemeProvider.svelte.d.ts.map +1 -1
  125. package/dist/themes/components/ColorSchemeToggle.svelte +17 -14
  126. package/dist/themes/components/ThemeSwitcher.svelte +14 -11
  127. package/dist/themes/create-theme.d.ts +22 -1
  128. package/dist/themes/create-theme.d.ts.map +1 -1
  129. package/dist/themes/create-theme.js +100 -9
  130. package/dist/themes/css-generator.d.ts.map +1 -1
  131. package/dist/themes/css-generator.js +20 -20
  132. package/dist/themes/derive.d.ts +31 -0
  133. package/dist/themes/derive.d.ts.map +1 -0
  134. package/dist/themes/derive.js +183 -0
  135. package/dist/themes/glass/index.d.ts.map +1 -1
  136. package/dist/themes/glass/index.js +127 -14
  137. package/dist/themes/happyvertical/index.d.ts.map +1 -1
  138. package/dist/themes/happyvertical/index.js +101 -20
  139. package/dist/themes/index.d.ts +2 -2
  140. package/dist/themes/index.d.ts.map +1 -1
  141. package/dist/themes/index.js +1 -1
  142. package/dist/themes/material/index.d.ts.map +1 -1
  143. package/dist/themes/material/index.js +129 -28
  144. package/dist/themes/required-tokens.generated.json +201 -0
  145. package/dist/themes/shared.d.ts +35 -0
  146. package/dist/themes/shared.d.ts.map +1 -1
  147. package/dist/themes/shared.js +32 -0
  148. package/dist/themes/smrt/index.d.ts +3 -0
  149. package/dist/themes/smrt/index.d.ts.map +1 -1
  150. package/dist/themes/smrt/index.js +108 -26
  151. package/dist/themes/studio/index.d.ts.map +1 -1
  152. package/dist/themes/studio/index.js +116 -40
  153. package/dist/themes/styles/base.css +229 -1
  154. package/dist/themes/styles/glass.css +107 -20
  155. package/dist/themes/styles/happyvertical.css +111 -15
  156. package/dist/themes/styles/material.css +127 -35
  157. package/dist/themes/styles/smrt.css +126 -31
  158. package/dist/themes/styles/studio.css +132 -37
  159. package/dist/themes/theme-script.d.ts +3 -1
  160. package/dist/themes/theme-script.d.ts.map +1 -1
  161. package/dist/themes/theme-script.js +7 -2
  162. package/dist/themes/types.d.ts +118 -6
  163. package/dist/themes/types.d.ts.map +1 -1
  164. package/dist/utils/theme/typography.d.ts +21 -21
  165. package/dist/utils/theme/typography.js +21 -21
  166. package/package.json +8 -2
@@ -148,12 +148,14 @@ export function getElement(): HTMLSelectElement | null {
148
148
  data-smrt-form={controlInteraction?.formId}
149
149
  data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
150
150
  data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id}
151
- {...rest}
151
+ {...rest} data-smrt-component="Select"
152
152
  >
153
153
  {@render children()}
154
154
  </select>
155
155
 
156
156
  <style>
157
+ @layer smrt.reset, smrt.structure, smrt.theme;
158
+ @layer smrt.theme {
157
159
  .select {
158
160
  box-sizing: border-box;
159
161
  display: block;
@@ -161,14 +163,15 @@ export function getElement(): HTMLSelectElement | null {
161
163
  padding: 0.5rem 2rem 0.5rem 0.75rem;
162
164
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
163
165
  line-height: var(--smrt-typography-body-medium-line-height, 1.5);
164
- color: var(--smrt-color-on-surface, #1f2937);
165
- background-color: var(--smrt-color-surface, #fff);
166
+ color: var(--smrt-color-on-surface);
167
+ background-color: var(--smrt-surface-control);
168
+ font-weight: var(--smrt-control-weight);
166
169
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2379747e' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
167
170
  background-position: right 0.5rem center;
168
171
  background-repeat: no-repeat;
169
172
  background-size: 1.5em 1.5em;
170
- border: 1px solid var(--smrt-color-outline, #6b7280);
171
- border-radius: 0.375rem;
173
+ border: var(--smrt-hairline-strong);
174
+ border-radius: var(--smrt-control-radius);
172
175
  appearance: none;
173
176
  cursor: pointer;
174
177
  transition:
@@ -177,20 +180,23 @@ export function getElement(): HTMLSelectElement | null {
177
180
  }
178
181
 
179
182
  .select:focus {
180
- outline: none;
181
- border-color: var(--smrt-color-primary, #005ac1);
182
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
183
+ border-color: var(--smrt-color-primary);
184
+ }
185
+
186
+ .select:focus-visible {
187
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
188
+ outline-offset: var(--smrt-focus-ring-offset);
183
189
  }
184
190
 
185
191
  .select[data-smrt-highlighted='true'] {
186
- outline: 3px solid var(--smrt-color-tertiary, #7d5260);
192
+ outline: 3px solid var(--smrt-color-tertiary);
187
193
  outline-offset: 3px;
188
194
  }
189
195
 
190
196
  .select:disabled {
191
- background-color: var(--smrt-color-surface-container-high, #f3f4f6);
197
+ background-color: var(--smrt-color-surface-container-high);
192
198
  cursor: not-allowed;
193
- opacity: 0.7;
199
+ opacity: var(--smrt-state-disabled);
194
200
  }
195
201
 
196
202
  /* Phones: 16px text so iOS Safari doesn't zoom the page when the field
@@ -208,7 +214,8 @@ export function getElement(): HTMLSelectElement | null {
208
214
  }
209
215
  }
210
216
 
211
- .select[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min, 48px); }
217
+ .select[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
212
218
  .select[data-density='comfortable'] { --smrt-control-target-min: 0px; }
213
- .select { min-height: var(--smrt-control-target-min, 0px); }
219
+ .select { min-height: max(var(--smrt-control-height), var(--smrt-control-target-min, 0px)); }
220
+ }
214
221
  </style>
@@ -313,7 +313,7 @@ useControlRegistration(() => {
313
313
  data-smrt-control={controlId}
314
314
  data-smrt-form={interactionContext?.formId}
315
315
  data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
316
- data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}
316
+ data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id} data-smrt-component="SignaturePad"
317
317
  >
318
318
  <canvas
319
319
  bind:this={canvasEl}
@@ -358,6 +358,8 @@ useControlRegistration(() => {
358
358
  </div>
359
359
 
360
360
  <style>
361
+ @layer smrt.reset, smrt.structure, smrt.theme;
362
+ @layer smrt.theme {
361
363
  .signature-pad {
362
364
  display: grid;
363
365
  gap: var(--smrt-spacing-3);
@@ -405,8 +407,8 @@ useControlRegistration(() => {
405
407
  flex: 1 1 auto;
406
408
  /* Capture is a touch flow: its actions are touch targets at every
407
409
  density, on the shared scale (smrt#3252). */
408
- min-width: var(--smrt-touch-target-min, 48px);
409
- min-height: var(--smrt-touch-target-min, 48px);
410
+ min-width: var(--smrt-touch-target-min);
411
+ min-height: var(--smrt-touch-target-min);
410
412
  padding: 0 var(--smrt-spacing-4);
411
413
  border: 1px solid var(--smrt-color-outline);
412
414
  border-radius: var(--smrt-radius-small);
@@ -422,8 +424,8 @@ useControlRegistration(() => {
422
424
  color: var(--smrt-color-on-primary);
423
425
  }
424
426
  .action:focus-visible {
425
- outline: 2px solid var(--smrt-color-primary);
426
- outline-offset: 2px;
427
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
428
+ outline-offset: var(--smrt-focus-ring-offset);
427
429
  }
428
430
  .action:disabled {
429
431
  opacity: 0.5;
@@ -433,4 +435,5 @@ useControlRegistration(() => {
433
435
  outline: 3px solid var(--smrt-color-tertiary);
434
436
  outline-offset: 4px;
435
437
  }
438
+ }
436
439
  </style>
@@ -139,7 +139,7 @@ useControlRegistration(() => {
139
139
  </script>
140
140
  <div class="slider {className}" data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
141
141
  data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
142
- data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id}>
142
+ data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id} data-smrt-component="Slider">
143
143
  {#if label}<div class="slider__header"><label for={resolvedId}>{label}</label><output for={resolvedId}>{formatValue(value)}</output></div>{/if}
144
144
  <div class="slider__controls">
145
145
  <input bind:this={rangeEl} id={resolvedId} type="range" {name} {min} {max} {step} {disabled} value={value}
@@ -150,12 +150,15 @@ useControlRegistration(() => {
150
150
  </div>
151
151
  </div>
152
152
  <style>
153
+ @layer smrt.reset, smrt.structure, smrt.theme;
154
+ @layer smrt.theme {
153
155
  .slider { display: grid; gap: var(--smrt-spacing-2); color: var(--smrt-color-on-surface); }
154
156
  .slider__header, .slider__controls { display: flex; align-items: center; gap: var(--smrt-spacing-3); }
155
157
  .slider__header { justify-content: space-between; font: var(--smrt-typography-label-large-font); }
156
158
  output { color: var(--smrt-color-primary); font-variant-numeric: tabular-nums; }
157
159
  input[type='range'] { flex: 1; min-width: 8rem; accent-color: var(--smrt-color-primary); cursor: pointer; }
158
160
  .slider__number { width: 5.5rem; padding: var(--smrt-spacing-2); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); }
159
- input:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 3px; }
161
+ input:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
160
162
  .slider[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-small); }
163
+ }
161
164
  </style>
@@ -536,7 +536,7 @@ async function discardAll(event: MouseEvent): Promise<void> {
536
536
  bind:this={reviewElement}
537
537
  class="staged-review"
538
538
  data-staged-control-review
539
- aria-label={text.region}
539
+ aria-label={text.region} data-smrt-component="StagedControlReview"
540
540
  >
541
541
  <header>
542
542
  <div>
@@ -623,31 +623,34 @@ async function discardAll(event: MouseEvent): Promise<void> {
623
623
  {/if}
624
624
 
625
625
  {#if summary && reviewActivated}
626
- <p class="status visually-hidden" role="status" aria-live="polite" aria-atomic="true">{status}</p>
626
+ <p class="status visually-hidden" role="status" aria-live="polite" aria-atomic="true" data-smrt-component="StagedControlReview">{status}</p>
627
627
  {/if}
628
628
 
629
629
  <style>
630
- .staged-review { margin-block-start: var(--smrt-spacing-5, 1.25rem); padding: var(--smrt-spacing-4, 1rem); color: var(--smrt-color-on-surface, #1f2937); background: var(--smrt-color-surface-container-low, #f8fafc); border: 1px solid var(--smrt-color-outline-variant, #cbd5e1); border-inline-start: 4px solid var(--smrt-color-tertiary, #7d5260); border-radius: var(--smrt-radius-medium, .5rem); }
630
+ @layer smrt.reset, smrt.structure, smrt.theme;
631
+ @layer smrt.theme {
632
+ .staged-review { margin-block-start: var(--smrt-spacing-5, 1.25rem); padding: var(--smrt-spacing-4, 1rem); color: var(--smrt-color-on-surface); background: var(--smrt-color-surface-container-low); border: 1px solid var(--smrt-color-outline-variant); border-inline-start: 4px solid var(--smrt-color-tertiary); border-radius: var(--smrt-radius-medium, .5rem); }
631
633
  header, .proposal-heading, .batch-actions, .item-actions { display: flex; align-items: center; gap: var(--smrt-spacing-2, .5rem); }
632
634
  header { justify-content: space-between; align-items: flex-start; gap: var(--smrt-spacing-4, 1rem); }
633
635
  h2, p { margin: 0; } h2 { font: var(--smrt-typography-title-medium-font, 600 1rem/1.4 system-ui); }
634
- header p, .proposal-heading span, dt { color: var(--smrt-color-on-surface-variant, #475569); font-size: .875rem; }
636
+ header p, .proposal-heading span, dt { color: var(--smrt-color-on-surface-variant); font-size: .875rem; }
635
637
  .proposal-heading strong, .proposal-heading .subject { display: block; }
636
638
  ul { display: grid; gap: var(--smrt-spacing-3, .75rem); padding: 0; list-style: none; }
637
- li { padding: var(--smrt-spacing-3, .75rem); background: var(--smrt-color-surface, #fff); border: 1px solid var(--smrt-color-outline-variant, #cbd5e1); border-radius: var(--smrt-radius-small, .375rem); }
638
- li.stale, li.invalid { border-color: var(--smrt-color-error, #b3261e); }
639
+ li { padding: var(--smrt-spacing-3, .75rem); background: var(--smrt-color-surface); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-small, .375rem); }
640
+ li.stale, li.invalid { border-color: var(--smrt-color-error); }
639
641
  .proposal-heading { justify-content: space-between; }
640
642
  dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--smrt-spacing-3, .75rem); }
641
643
  dt { font-weight: 600; } dd { margin: .25rem 0 0; overflow-wrap: anywhere; }
642
- input, textarea { width: 100%; box-sizing: border-box; padding: .4rem .5rem; color: inherit; background: var(--smrt-color-surface, #fff); border: 1px solid var(--smrt-color-outline, #64748b); border-radius: var(--smrt-radius-small, .375rem); }
644
+ input, textarea { width: 100%; box-sizing: border-box; padding: .4rem .5rem; color: inherit; background: var(--smrt-color-surface); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small, .375rem); }
643
645
  input[type="checkbox"] { width: auto; }
644
- button { min-height: 2.25rem; padding: .4rem .75rem; color: var(--smrt-color-on-primary, #fff); background: var(--smrt-color-primary, #005ac1); border: 1px solid transparent; border-radius: var(--smrt-radius-small, .375rem); cursor: pointer; }
645
- button.secondary { color: var(--smrt-color-primary, #005ac1); background: transparent; border-color: var(--smrt-color-outline, #64748b); }
646
- button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 2px solid var(--smrt-color-primary, #005ac1); outline-offset: 2px; }
646
+ button { min-height: 2.25rem; padding: .4rem .75rem; color: var(--smrt-color-on-primary); background: var(--smrt-color-primary); border: 1px solid transparent; border-radius: var(--smrt-radius-small, .375rem); cursor: pointer; }
647
+ button.secondary { color: var(--smrt-color-primary); background: transparent; border-color: var(--smrt-color-outline); }
648
+ button:focus-visible, input:focus-visible, textarea:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
647
649
  button:disabled { cursor: not-allowed; opacity: .55; }
648
650
  .item-actions { margin-block-start: var(--smrt-spacing-3, .75rem); }
649
- .problem { margin-block-start: var(--smrt-spacing-2, .5rem); color: var(--smrt-color-error, #b3261e); }
651
+ .problem { margin-block-start: var(--smrt-spacing-2, .5rem); color: var(--smrt-color-error); }
650
652
  .visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
651
- :global([data-smrt-staged='true']) { outline: 3px solid var(--smrt-color-tertiary, #7d5260); outline-offset: 3px; }
653
+ :global([data-smrt-staged='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 3px; }
652
654
  @media (max-width: 40rem) { header, .proposal-heading { align-items: stretch; flex-direction: column; } dl { grid-template-columns: 1fr; } }
655
+ }
653
656
  </style>
@@ -118,7 +118,7 @@ useControlRegistration(() => {
118
118
 
119
119
  <label data-density={density} class="switch switch--{size} {className}" class:switch--disabled={disabled} data-smrt-hit-target data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
120
120
  data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
121
- data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id}>
121
+ data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id} data-smrt-component="Switch">
122
122
  {#if label && labelPosition === 'left'}<span class="switch__label">{label}</span>{/if}
123
123
  <span class="switch__control">
124
124
  <input bind:this={inputEl} id={resolvedId} type="checkbox" role="switch" {name} {value} {disabled} {required} checked={checked}
@@ -130,27 +130,30 @@ useControlRegistration(() => {
130
130
  </label>
131
131
 
132
132
  <style>
133
+ @layer smrt.reset, smrt.structure, smrt.theme;
134
+ @layer smrt.theme {
133
135
  .switch { display: inline-flex; align-items: center; gap: var(--smrt-spacing-2, .5rem); cursor: pointer; color: var(--smrt-color-on-surface); }
134
136
  .switch--disabled { opacity: .5; cursor: not-allowed; }
135
137
  /* Phones: the whole row (track and label) is at least a 44px touch target. */
136
138
  @media (max-width: 48rem) { .switch { min-block-size: 2.75rem; } }
137
139
  /* The 2.75rem-wide track gets a transparent 44px-tall ::before hit area (see Checkbox); the
138
140
  track and label sit above every hit area. --smrt-control-hit-size resizes it (0px = off). */
139
- .switch__control { --_hit: max(var(--smrt-control-hit-size, 2.75rem), 1.5rem); position: relative; display: inline-flex; }
140
- .switch__control::before { content: ''; position: absolute; z-index: 0; inset-block-start: 50%; inset-inline: calc((100% - var(--_hit)) / 2); block-size: var(--_hit); margin-block-start: calc(var(--_hit) / -2); }
141
+ .switch__control { --smrt-switch-hit: max(var(--smrt-control-hit-size, 2.75rem), 1.5rem); position: relative; display: inline-flex; }
142
+ .switch__control::before { content: ''; position: absolute; z-index: 0; inset-block-start: 50%; inset-inline: calc((100% - var(--smrt-switch-hit)) / 2); block-size: var(--smrt-switch-hit); margin-block-start: calc(var(--smrt-switch-hit) / -2); }
141
143
  .switch__label { position: relative; z-index: 1; }
142
144
  input { position: absolute; width: 1px; height: 1px; opacity: 0; }
143
145
  .switch__track { position: relative; z-index: 1; width: 2.75rem; height: 1.5rem; padding: 2px; border-radius: var(--smrt-radius-full); background: var(--smrt-color-surface-container-highest); border: 1px solid var(--smrt-color-outline); transition: background var(--smrt-duration-short2); }
144
146
  .switch__thumb { display: block; width: 1.125rem; height: 1.125rem; border-radius: 50%; background: var(--smrt-color-outline); transition: transform var(--smrt-duration-short2), background var(--smrt-duration-short2); }
145
147
  input:checked + .switch__track { background: var(--smrt-color-primary); border-color: var(--smrt-color-primary); }
146
148
  input:checked + .switch__track .switch__thumb { transform: translateX(1.25rem); background: var(--smrt-color-on-primary); }
147
- input:focus-visible + .switch__track { outline: 2px solid var(--smrt-color-primary); outline-offset: 3px; }
149
+ input:focus-visible + .switch__track { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
148
150
  .switch--sm { font-size: .8rem; transform-origin: left center; }
149
151
  .switch--lg .switch__track { transform: scale(1.15); margin-inline: .2rem; }
150
152
  .switch[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-full); }
151
153
  @media (prefers-reduced-motion: reduce) { .switch__track, .switch__thumb { transition: none; } }
152
154
 
153
- .switch[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min, 48px); }
155
+ .switch[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
154
156
  .switch[data-density='comfortable'] { --smrt-control-target-min: 0px; }
155
157
  .switch { min-height: var(--smrt-control-target-min, 0px); min-width: var(--smrt-control-target-min, 0px); }
158
+ }
156
159
  </style>
@@ -129,13 +129,15 @@ useControlRegistration(() => {
129
129
  };
130
130
  });
131
131
  </script>
132
- <div class="tags-field {className}"><label for={inputId}>{label}</label><div bind:this={rootEl} class="tags" data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
132
+ <div class="tags-field {className}" data-smrt-component="TagsInput"><label for={inputId}>{label}</label><div bind:this={rootEl} class="tags" data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
133
133
  data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
134
134
  data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}>
135
135
  {#each values as tag, index}<span class="tag">{tag}<button type="button" disabled={disabled} aria-label={`Remove ${tag}`} onclick={() => remove(index)}>×</button><input type="hidden" name={name ? `${name}[]` : undefined} value={tag} /></span>{/each}
136
136
  <input bind:this={inputEl} id={inputId} {placeholder} {disabled} bind:value={draft} onkeydown={handleKeydown} onblur={() => commit(draft)} />
137
137
  </div></div>
138
138
  <style>
139
+ @layer smrt.reset, smrt.structure, smrt.theme;
140
+ @layer smrt.theme {
139
141
  .tags-field { display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); } label { font: var(--smrt-typography-label-large-font); }
140
142
  .tags { display: flex; flex-wrap: wrap; gap: var(--smrt-spacing-1); min-height: 2.5rem; padding: var(--smrt-spacing-1); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); }
141
143
  .tag { display: inline-flex; align-items: center; gap: var(--smrt-spacing-1); padding: var(--smrt-spacing-1) var(--smrt-spacing-2); border-radius: var(--smrt-radius-full); background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); }
@@ -145,7 +147,8 @@ useControlRegistration(() => {
145
147
  .tag { padding-inline-end: 0; }
146
148
  .tag button { min-inline-size: 2.75rem; min-block-size: 2.75rem; font-size: 1.25rem; }
147
149
  }
148
- .tag button:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: -2px; border-radius: var(--smrt-radius-full); }
150
+ .tag button:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: calc(var(--smrt-focus-ring-width) * -1); border-radius: var(--smrt-radius-full); }
149
151
  .tags > input { flex: 1; min-width: 8rem; border: 0; outline: 0; background: transparent; color: inherit; }
150
152
  :global(.tags[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
153
+ }
151
154
  </style>
@@ -141,10 +141,12 @@ export function getElement(): HTMLTextAreaElement | null {
141
141
  data-smrt-form={controlInteraction?.formId}
142
142
  data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
143
143
  data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id}
144
- {...rest}
144
+ {...rest} data-smrt-component="Textarea"
145
145
  ></textarea>
146
146
 
147
147
  <style>
148
+ @layer smrt.reset, smrt.structure, smrt.theme;
149
+ @layer smrt.theme {
148
150
  .textarea {
149
151
  box-sizing: border-box;
150
152
  display: block;
@@ -152,10 +154,11 @@ export function getElement(): HTMLTextAreaElement | null {
152
154
  padding: 0.5rem 0.75rem;
153
155
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
154
156
  line-height: var(--smrt-typography-body-medium-line-height, 1.5);
155
- color: var(--smrt-color-on-surface, #1f2937);
156
- background-color: var(--smrt-color-surface, #fff);
157
- border: 1px solid var(--smrt-color-outline, #6b7280);
158
- border-radius: 0.375rem;
157
+ color: var(--smrt-color-on-surface);
158
+ background-color: var(--smrt-surface-control);
159
+ font-weight: var(--smrt-control-weight);
160
+ border: var(--smrt-hairline-strong);
161
+ border-radius: var(--smrt-control-radius);
159
162
  resize: vertical;
160
163
  min-height: 80px;
161
164
  transition:
@@ -164,24 +167,27 @@ export function getElement(): HTMLTextAreaElement | null {
164
167
  }
165
168
 
166
169
  .textarea:focus {
167
- outline: none;
168
- border-color: var(--smrt-color-primary, #005ac1);
169
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--smrt-color-primary, #005ac1) 10%, transparent);
170
+ border-color: var(--smrt-color-primary);
171
+ }
172
+
173
+ .textarea:focus-visible {
174
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
175
+ outline-offset: var(--smrt-focus-ring-offset);
170
176
  }
171
177
 
172
178
  .textarea[data-smrt-highlighted='true'] {
173
- outline: 3px solid var(--smrt-color-tertiary, #7d5260);
179
+ outline: 3px solid var(--smrt-color-tertiary);
174
180
  outline-offset: 3px;
175
181
  }
176
182
 
177
183
  .textarea:disabled {
178
- background-color: var(--smrt-color-surface-container-high, #f3f4f6);
184
+ background-color: var(--smrt-color-surface-container-high);
179
185
  cursor: not-allowed;
180
- opacity: 0.7;
186
+ opacity: var(--smrt-state-disabled);
181
187
  }
182
188
 
183
189
  .textarea::placeholder {
184
- color: var(--smrt-color-on-surface-variant, #9ca3af);
190
+ color: var(--smrt-color-on-surface-variant);
185
191
  }
186
192
 
187
193
  /* Phones: 16px text so iOS Safari doesn't zoom the page when the field
@@ -198,7 +204,8 @@ export function getElement(): HTMLTextAreaElement | null {
198
204
  }
199
205
  }
200
206
 
201
- .textarea[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min, 48px); }
207
+ .textarea[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
202
208
  .textarea[data-density='comfortable'] { --smrt-control-target-min: 0px; }
203
209
  .textarea { min-height: max(80px, var(--smrt-control-target-min, 0px)); }
210
+ }
204
211
  </style>
@@ -25,5 +25,10 @@ let {
25
25
  const instanceId = $props.id();
26
26
  const resolvedId = $derived(id ?? `smrt-time-${instanceId}`);
27
27
  </script>
28
- <label class="picker {className}" for={resolvedId}><span>{label}</span><Input id={resolvedId} {name} type="time" aria-label={label} {interaction} bind:value {...rest} /></label>
29
- <style>.picker { display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); font: var(--smrt-typography-label-large-font); }</style>
28
+ <label class="picker {className}" for={resolvedId} data-smrt-component="TimePicker"><span>{label}</span><Input id={resolvedId} {name} type="time" aria-label={label} {interaction} bind:value {...rest} /></label>
29
+ <style>
30
+ @layer smrt.reset, smrt.structure, smrt.theme;
31
+ @layer smrt.theme {
32
+ .picker { display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); font: var(--smrt-typography-label-large-font); }
33
+ }
34
+ </style>
@@ -60,7 +60,7 @@ const sizeClasses = {
60
60
  };
61
61
  </script>
62
62
 
63
- <label class="toggle {sizeClasses[size]}" class:toggle--disabled={disabled}>
63
+ <label class="toggle {sizeClasses[size]}" class:toggle--disabled={disabled} data-smrt-component="Toggle">
64
64
  {#if label && labelPosition === 'left'}
65
65
  <span class="toggle__label toggle__label--left">{label}</span>
66
66
  {/if}
@@ -86,6 +86,8 @@ const sizeClasses = {
86
86
  </label>
87
87
 
88
88
  <style>
89
+ @layer smrt.reset, smrt.structure, smrt.theme;
90
+ @layer smrt.theme {
89
91
  .toggle {
90
92
  display: inline-flex;
91
93
  align-items: center;
@@ -101,7 +103,7 @@ const sizeClasses = {
101
103
 
102
104
  .toggle__label {
103
105
  font-size: var(--smrt-typography-body-medium-size, 0.875rem);
104
- color: var(--smrt-color-on-surface, #111827);
106
+ color: var(--smrt-color-on-surface);
105
107
  line-height: 1.5;
106
108
  }
107
109
 
@@ -126,38 +128,38 @@ const sizeClasses = {
126
128
 
127
129
  .toggle__thumb {
128
130
  position: relative;
129
- background: var(--smrt-color-surface-container-highest, #e5e7eb);
130
- border-radius: var(--smrt-radius-full, 9999px);
131
+ background: var(--smrt-color-surface-container-highest);
132
+ border-radius: var(--smrt-radius-full);
131
133
  transition: background-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
132
134
  }
133
135
 
134
136
  .toggle__thumb::after {
135
137
  content: '';
136
138
  position: absolute;
137
- background: var(--smrt-color-surface, #ffffff);
138
- border-radius: var(--smrt-radius-full, 9999px);
139
+ background: var(--smrt-color-surface);
140
+ border-radius: var(--smrt-radius-full);
139
141
  box-shadow: var(--smrt-elevation-1, 0 1px 3px color-mix(in srgb, var(--smrt-color-shadow) 20%, transparent));
140
142
  transition: transform var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease);
141
143
  }
142
144
 
143
145
  /* Checked state */
144
146
  .toggle__input:checked + .toggle__thumb {
145
- background: var(--smrt-color-primary, #005ac1);
147
+ background: var(--smrt-color-primary);
146
148
  }
147
149
 
148
150
  /* Focus state */
149
151
  .toggle__input:focus-visible + .toggle__thumb {
150
- outline: 2px solid var(--smrt-color-primary, #005ac1);
151
- outline-offset: 2px;
152
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
153
+ outline-offset: var(--smrt-focus-ring-offset);
152
154
  }
153
155
 
154
156
  /* Hover state */
155
157
  .toggle:not(.toggle--disabled):hover .toggle__thumb {
156
- background: var(--smrt-color-surface-container-high, #d1d5db);
158
+ background: var(--smrt-color-surface-container-high);
157
159
  }
158
160
 
159
161
  .toggle:not(.toggle--disabled):hover .toggle__input:checked + .toggle__thumb {
160
- background: var(--smrt-color-primary, #2563eb);
162
+ background: var(--smrt-color-primary);
161
163
  }
162
164
 
163
165
  /* Size: Small */
@@ -221,4 +223,5 @@ const sizeClasses = {
221
223
  transition: none;
222
224
  }
223
225
  }
226
+ }
224
227
  </style>
@@ -90,11 +90,14 @@ useControlRegistration(() => {
90
90
  aria-pressed={pressed} aria-label={ariaLabel} data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
91
91
  data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
92
92
  data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}
93
- onclick={handleClick} {...rest}>{@render children?.()}</button>
93
+ onclick={handleClick} {...rest} data-smrt-component="ToggleButton">{@render children?.()}</button>
94
94
  <style>
95
+ @layer smrt.reset, smrt.structure, smrt.theme;
96
+ @layer smrt.theme {
95
97
  .toggle-button { display: inline-flex; align-items: center; justify-content: center; min-height: 2.5rem; padding: 0 var(--smrt-spacing-4); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-full); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); cursor: pointer; }
96
98
  .toggle-button.pressed { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); border-color: var(--smrt-color-secondary); }
97
- .toggle-button:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 2px; }
99
+ .toggle-button:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
98
100
  .toggle-button:disabled { opacity: .5; cursor: not-allowed; }
99
101
  .toggle-button[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
102
+ }
100
103
  </style>
@@ -25,11 +25,13 @@ const {
25
25
  }: Props = $props();
26
26
  </script>
27
27
 
28
- <div class="action-group gap-{gap} justify-{justify} {className}" {...rest}>
28
+ <div class="action-group gap-{gap} justify-{justify} {className}" {...rest} data-smrt-component="ActionGroup">
29
29
  {@render children()}
30
30
  </div>
31
31
 
32
32
  <style>
33
+ @layer smrt.reset, smrt.structure, smrt.theme;
34
+ @layer smrt.theme {
33
35
  .action-group {
34
36
  display: flex;
35
37
  flex-wrap: wrap;
@@ -52,4 +54,5 @@ const {
52
54
  .justify-end {
53
55
  justify-content: flex-end;
54
56
  }
57
+ }
55
58
  </style>
@@ -14,11 +14,13 @@ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'class'> {
14
14
  const { maxWidth = 'lg', children, ...rest }: Props = $props();
15
15
  </script>
16
16
 
17
- <div class="container max-w-{maxWidth}" {...rest}>
17
+ <div class="container max-w-{maxWidth}" {...rest} data-smrt-component="Container">
18
18
  {@render children?.()}
19
19
  </div>
20
20
 
21
21
  <style>
22
+ @layer smrt.reset, smrt.structure, smrt.theme;
23
+ @layer smrt.theme {
22
24
  .container {
23
25
  box-sizing: border-box;
24
26
  width: 100%;
@@ -53,4 +55,5 @@ const { maxWidth = 'lg', children, ...rest }: Props = $props();
53
55
  padding-right: var(--smrt-spacing-6);
54
56
  }
55
57
  }
58
+ }
56
59
  </style>
@@ -61,7 +61,7 @@ const icons = {
61
61
  };
62
62
  </script>
63
63
 
64
- <div class="empty-state" class:sm={size === 'sm'} class:lg={size === 'lg'}>
64
+ <div class="empty-state" class:sm={size === 'sm'} class:lg={size === 'lg'} data-smrt-component="EmptyState">
65
65
  <div class="icon-container">
66
66
  {#if typeof icon === 'string'}
67
67
  {@html icons[icon] ?? icons.inbox}
@@ -90,6 +90,8 @@ const icons = {
90
90
  </div>
91
91
 
92
92
  <style>
93
+ @layer smrt.reset, smrt.structure, smrt.theme;
94
+ @layer smrt.theme {
93
95
  .empty-state {
94
96
  display: flex;
95
97
  flex-direction: column;
@@ -117,15 +119,15 @@ const icons = {
117
119
  background-color: var(--smrt-color-secondary-container);
118
120
  color: var(--smrt-color-on-secondary-container);
119
121
  border-radius: var(--smrt-radius-3xl, 32px); /* M3 extra large shape */
120
- padding: var(--smrt-spacing-6, 24px);
122
+ padding: var(--smrt-spacing-6);
121
123
  }
122
124
 
123
125
  .sm .icon-container {
124
126
  width: 64px;
125
127
  height: 64px;
126
128
  margin-bottom: 1.5rem;
127
- border-radius: var(--smrt-radius-xl, 16px);
128
- padding: var(--smrt-spacing-4, 16px);
129
+ border-radius: var(--smrt-radius-xl);
130
+ padding: var(--smrt-spacing-4);
129
131
  }
130
132
 
131
133
  .lg .icon-container {
@@ -133,7 +135,7 @@ const icons = {
133
135
  height: 120px;
134
136
  margin-bottom: 2.5rem;
135
137
  border-radius: var(--smrt-radius-3xl, 32px);
136
- padding: var(--smrt-spacing-8, 32px);
138
+ padding: var(--smrt-spacing-8);
137
139
  }
138
140
 
139
141
  .empty-title {
@@ -163,15 +165,15 @@ const icons = {
163
165
  display: inline-flex;
164
166
  align-items: center;
165
167
  justify-content: center;
166
- gap: var(--smrt-spacing-2, 8px);
167
- padding: 0 var(--smrt-spacing-6, 24px);
168
+ gap: var(--smrt-spacing-2);
169
+ padding: 0 var(--smrt-spacing-6);
168
170
  height: 40px;
169
171
  font: var(--smrt-typography-label-large-font);
170
172
  font-weight: var(--smrt-typography-weight-medium, 500);
171
173
  color: var(--smrt-color-on-primary);
172
174
  background-color: var(--smrt-color-primary);
173
175
  border: none;
174
- border-radius: var(--smrt-radius-2xl, 24px);
176
+ border-radius: var(--smrt-radius-2xl);
175
177
  text-decoration: none;
176
178
  cursor: pointer;
177
179
  transition: box-shadow 200ms, background-color 200ms;
@@ -184,4 +186,5 @@ const icons = {
184
186
  background-color: var(--smrt-color-primary);
185
187
  box-shadow: var(--smrt-elevation-2);
186
188
  }
189
+ }
187
190
  </style>
@@ -16,7 +16,7 @@ const { children }: Props = $props();
16
16
  const currentYear = new Date().getFullYear();
17
17
  </script>
18
18
 
19
- <footer class="site-footer">
19
+ <footer class="site-footer" data-smrt-component="Footer">
20
20
  <Container>
21
21
  <div class="footer-content">
22
22
  <p class="copyright">&copy; {currentYear} {t(M['ui.footer.all_rights_reserved'])}</p>
@@ -31,6 +31,8 @@ const currentYear = new Date().getFullYear();
31
31
  </footer>
32
32
 
33
33
  <style>
34
+ @layer smrt.reset, smrt.structure, smrt.theme;
35
+ @layer smrt.theme {
34
36
  .site-footer {
35
37
  background: var(--smrt-color-surface-container-low);
36
38
  border-top: 1px solid var(--smrt-color-outline-variant);
@@ -61,4 +63,5 @@ const currentYear = new Date().getFullYear();
61
63
  .footer-links :global(a:hover) {
62
64
  text-decoration: underline;
63
65
  }
66
+ }
64
67
  </style>