@happyvertical/smrt-ui 0.55.21 → 0.55.22

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 (56) hide show
  1. package/dist/components/calendar/DayView.svelte +1 -1
  2. package/dist/components/data/CollectionList.svelte +1 -1
  3. package/dist/components/data/ListSortSelect.svelte +1 -1
  4. package/dist/components/feedback/Alert.svelte +83 -22
  5. package/dist/components/feedback/LoadingOverlay.svelte +2 -2
  6. package/dist/components/feedback/PhoneSheet.svelte +1 -1
  7. package/dist/components/feedback/ToastViewport.svelte +1 -1
  8. package/dist/components/feedback/WorkingStrip.svelte +4 -4
  9. package/dist/components/forms/CameraCapture.svelte +1 -1
  10. package/dist/components/forms/Checkbox.svelte +130 -36
  11. package/dist/components/forms/Combobox.svelte +2 -2
  12. package/dist/components/forms/Fieldset.svelte +1 -1
  13. package/dist/components/forms/FilePicker.svelte +1 -1
  14. package/dist/components/forms/FormActionBar.svelte +2 -2
  15. package/dist/components/forms/Input.svelte +66 -61
  16. package/dist/components/forms/InputGroup.svelte +1 -1
  17. package/dist/components/forms/Listbox.svelte +1 -1
  18. package/dist/components/forms/MultiSelect.svelte +2 -2
  19. package/dist/components/forms/RangeSlider.svelte +1 -1
  20. package/dist/components/forms/SegmentedControl.svelte +2 -2
  21. package/dist/components/forms/Select.svelte +67 -61
  22. package/dist/components/forms/SignaturePad.svelte +1 -1
  23. package/dist/components/forms/Slider.svelte +1 -1
  24. package/dist/components/forms/StagedControlReview.svelte +4 -4
  25. package/dist/components/forms/Switch.svelte +127 -35
  26. package/dist/components/forms/TagsInput.svelte +1 -1
  27. package/dist/components/forms/ToggleButton.svelte +1 -1
  28. package/dist/components/layout/Footer.svelte +1 -1
  29. package/dist/components/layout/Masthead.svelte +1 -1
  30. package/dist/components/memberships/MembershipCard.svelte +3 -3
  31. package/dist/components/nav/FilterChips.svelte +1 -1
  32. package/dist/components/nav/Tabs.svelte +189 -190
  33. package/dist/components/nav/Tabs.svelte.d.ts.map +1 -1
  34. package/dist/components/permissions/PermissionPicker.svelte +4 -4
  35. package/dist/components/roles/RoleSelector.svelte +2 -2
  36. package/dist/components/ui/Accordion.svelte +1 -1
  37. package/dist/components/ui/AccordionItem.svelte +1 -1
  38. package/dist/components/ui/Badge.svelte +23 -25
  39. package/dist/components/ui/Button.svelte +101 -115
  40. package/dist/components/ui/Button.svelte.d.ts +1 -1
  41. package/dist/components/ui/Card.svelte +44 -57
  42. package/dist/components/ui/Chip.svelte +65 -60
  43. package/dist/components/ui/Disclosure.svelte +1 -1
  44. package/dist/components/ui/IconToggle.svelte +2 -2
  45. package/dist/styles/unstyled.css +2 -2
  46. package/dist/svelte/playground/BaseControlsPreview.svelte +2 -2
  47. package/dist/svelte/playground/CollectionsPreview.svelte +1 -1
  48. package/dist/svelte/playground/DataTablePreview.svelte +5 -5
  49. package/dist/svelte/playground/FeedbackPreview.svelte +1 -1
  50. package/dist/svelte/playground/InteractiveControlsPreview.svelte +1 -1
  51. package/dist/svelte/playground/StylelessPreview.svelte +35 -2
  52. package/dist/svelte/playground/StylelessPreview.svelte.d.ts.map +1 -1
  53. package/dist/themes/README.md +1 -1
  54. package/dist/themes/components/ColorSchemeToggle.svelte +3 -3
  55. package/dist/themes/components/ThemeSwitcher.svelte +3 -3
  56. package/package.json +2 -2
@@ -16,7 +16,7 @@ let { prefix, suffix, children, class: className = '' }: Props = $props();
16
16
  <style>
17
17
  @layer smrt.reset, smrt.structure, smrt.theme;
18
18
  @layer smrt.theme {
19
- .input-group { display: flex; align-items: stretch; width: 100%; border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); overflow: hidden; }
19
+ .input-group { display: flex; align-items: stretch; width: 100%; border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); overflow: hidden; }
20
20
  .adornment { display: inline-flex; align-items: center; padding: 0 var(--smrt-spacing-3); background: var(--smrt-color-surface-container-low); color: var(--smrt-color-on-surface-variant); }
21
21
  .control { flex: 1; min-width: 0; } .input-group .control :global(input), .input-group .control :global(select), .input-group .control :global(textarea) { border: 0; border-radius: 0; box-shadow: none; }
22
22
  .input-group:focus-within { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
@@ -165,7 +165,7 @@ useControlRegistration(() => {
165
165
  <style>
166
166
  @layer smrt.reset, smrt.structure, smrt.theme;
167
167
  @layer smrt.theme {
168
- .listbox { display: grid; padding: var(--smrt-spacing-1); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); }
168
+ .listbox { display: grid; padding: var(--smrt-spacing-1); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); }
169
169
  button { padding: var(--smrt-spacing-2) var(--smrt-spacing-3); border: 0; border-radius: var(--smrt-radius-extra-small); background: transparent; color: var(--smrt-color-on-surface); text-align: left; cursor: pointer; }
170
170
  button[aria-selected='true'] { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); } button:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
171
171
  button:disabled { opacity: .5; cursor: not-allowed; } :global(.listbox[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
@@ -225,8 +225,8 @@ useControlRegistration(() => {
225
225
  @layer smrt.reset, smrt.structure, smrt.theme;
226
226
  @layer smrt.theme {
227
227
  .multi-select { position: relative; display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); } .label { font: var(--smrt-typography-label-large-font); }
228
- .trigger { width: 100%; min-height: 2.5rem; padding: var(--smrt-spacing-2) var(--smrt-spacing-3); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: inherit; text-align: left; }
229
- .options { position: absolute; z-index: var(--smrt-z-index-dropdown); top: 100%; left: 0; right: 0; display: grid; padding: var(--smrt-spacing-1); border: 1px solid var(--smrt-color-outline-variant); background: var(--smrt-color-surface-container); box-shadow: var(--smrt-elevation-2); }
228
+ .trigger { width: 100%; min-height: 2.5rem; padding: var(--smrt-spacing-2) var(--smrt-spacing-3); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: inherit; text-align: left; }
229
+ .options { position: absolute; z-index: var(--smrt-z-index-dropdown); top: 100%; left: 0; right: 0; display: grid; padding: var(--smrt-spacing-1); border: var(--smrt-hairline); background: var(--smrt-color-surface-container); box-shadow: var(--smrt-elevation-2); }
230
230
  .options button { display: grid; grid-template-columns: 1.25rem 1fr; gap: var(--smrt-spacing-2); padding: var(--smrt-spacing-2); border: 0; background: transparent; color: inherit; text-align: left; } .options button[aria-selected='true'] { background: var(--smrt-color-secondary-container); }
231
231
  :global(.multi-select[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
232
232
  }
@@ -201,7 +201,7 @@ useControlRegistration(() => {
201
201
  .range-slider__track input::-moz-range-thumb { pointer-events: auto; }
202
202
  .range-slider__inputs { display: flex; gap: var(--smrt-spacing-3); }
203
203
  .range-slider__inputs label { display: grid; gap: var(--smrt-spacing-1); flex: 1; font: var(--smrt-typography-label-small-font); color: var(--smrt-color-on-surface-variant); }
204
- .range-slider__inputs input { width: 100%; 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); }
204
+ .range-slider__inputs input { width: 100%; padding: var(--smrt-spacing-2); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); }
205
205
  input:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
206
206
  :global(.range-slider[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-small); }
207
207
  }
@@ -252,9 +252,9 @@ useControlRegistration(() => {
252
252
  <style>
253
253
  @layer smrt.reset, smrt.structure, smrt.theme;
254
254
  @layer smrt.theme {
255
- .segmented { display: inline-flex; border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-full); overflow: hidden; }
255
+ .segmented { display: inline-flex; border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-full); overflow: hidden; }
256
256
  .segmented.full-width { display: flex; width: 100%; }
257
- label { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: 1; min-height: 2.5rem; padding: 0 var(--smrt-spacing-4); border: 0; border-right: 1px solid var(--smrt-color-outline); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); cursor: pointer; }
257
+ label { position: relative; display: inline-flex; align-items: center; justify-content: center; flex: 1; min-height: 2.5rem; padding: 0 var(--smrt-spacing-4); border: 0; border-right: var(--smrt-hairline-strong); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); cursor: pointer; }
258
258
  label:last-child { border-right: 0; } label.selected { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); }
259
259
  label:has(input:focus-visible) { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: calc(var(--smrt-focus-ring-width) * -1); } label.disabled, label:has(input:disabled) { opacity: .5; cursor: not-allowed; }
260
260
  :global(.segmented[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
@@ -143,7 +143,7 @@ export function getElement(): HTMLSelectElement | null {
143
143
  aria-label={ariaLabel}
144
144
  aria-describedby={resolvedDescribedBy}
145
145
  aria-invalid={resolvedInvalid}
146
- data-density={density} class="select {className}"
146
+ data-density={density} class="smrt-select__root {className}"
147
147
  data-smrt-control={resolvedControlId}
148
148
  data-smrt-form={controlInteraction?.formId}
149
149
  data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
@@ -155,67 +155,73 @@ export function getElement(): HTMLSelectElement | null {
155
155
 
156
156
  <style>
157
157
  @layer smrt.reset, smrt.structure, smrt.theme;
158
+ @layer smrt.structure {
159
+ .smrt-select__root {
160
+ box-sizing: border-box;
161
+ display: block;
162
+ width: 100%;
163
+ padding: 0.5rem 2rem 0.5rem 0.75rem;
164
+ cursor: pointer;
165
+ }
166
+ .smrt-select__root:disabled {
167
+ cursor: not-allowed;
168
+ }
169
+ @media (max-width: 48rem) {
170
+ .smrt-select__root {
171
+ min-height: 2.75rem;
172
+ }
173
+ }
174
+ .smrt-select__root[data-density='touch'] {
175
+ --smrt-select-target-min: var(--smrt-touch-target-min);
176
+ }
177
+ .smrt-select__root[data-density='comfortable'] {
178
+ --smrt-select-target-min: 0px;
179
+ }
180
+ .smrt-select__root {
181
+ min-height: max(var(--smrt-control-height), var(--smrt-select-target-min, var(--smrt-control-target-min)));
182
+ }
183
+ }
158
184
  @layer smrt.theme {
159
- .select {
160
- box-sizing: border-box;
161
- display: block;
162
- width: 100%;
163
- padding: 0.5rem 2rem 0.5rem 0.75rem;
164
- font-size: var(--smrt-typography-body-medium-size, 0.875rem);
165
- line-height: var(--smrt-typography-body-medium-line-height, 1.5);
166
- color: var(--smrt-color-on-surface);
167
- background-color: var(--smrt-surface-control);
168
- font-weight: var(--smrt-control-weight);
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");
170
- background-position: right 0.5rem center;
171
- background-repeat: no-repeat;
172
- background-size: 1.5em 1.5em;
173
- border: var(--smrt-hairline-strong);
174
- border-radius: var(--smrt-control-radius);
175
- appearance: none;
176
- cursor: pointer;
177
- transition:
178
- border-color 0.15s ease-in-out,
185
+ .smrt-select__root {
186
+ font-size: var(--smrt-typography-body-medium-size);
187
+ line-height: var(--smrt-typography-body-medium-line-height);
188
+ color: var(--smrt-color-on-surface);
189
+ background-color: var(--smrt-surface-control);
190
+ font-weight: var(--smrt-control-weight);
191
+ 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");
192
+ background-position: right 0.5rem center;
193
+ background-repeat: no-repeat;
194
+ background-size: 1.5em 1.5em;
195
+ border: var(--smrt-hairline-strong);
196
+ border-radius: var(--smrt-control-radius);
197
+ appearance: none;
198
+ transition: border-color 0.15s ease-in-out,
179
199
  box-shadow 0.15s ease-in-out;
180
- }
181
-
182
- .select:focus {
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);
189
- }
190
-
191
- .select[data-smrt-highlighted='true'] {
192
- outline: 3px solid var(--smrt-color-tertiary);
193
- outline-offset: 3px;
194
- }
195
-
196
- .select:disabled {
197
- background-color: var(--smrt-color-surface-container-high);
198
- cursor: not-allowed;
199
- opacity: var(--smrt-state-disabled);
200
- }
201
-
202
- /* Phones: 16px text so iOS Safari doesn't zoom the page when the field
203
- gets focus, and a 44px touch target. */
204
- @media (max-width: 48rem) {
205
- .select {
206
- font-size: max(var(--smrt-typography-body-medium-size, 0.875rem), 16px);
207
- min-height: 2.75rem;
208
- }
209
- }
210
-
211
- @media (prefers-reduced-motion: reduce) {
212
- .select {
213
- transition: none;
214
- }
215
- }
216
-
217
- .select[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
218
- .select[data-density='comfortable'] { --smrt-control-target-min: 0px; }
219
- .select { min-height: max(var(--smrt-control-height), var(--smrt-control-target-min, 0px)); }
200
+ }
201
+ .smrt-select__root:focus {
202
+ border-color: var(--smrt-color-primary);
203
+ }
204
+ .smrt-select__root:focus-visible {
205
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
206
+ outline-offset: var(--smrt-focus-ring-offset);
207
+ }
208
+ .smrt-select__root[data-smrt-highlighted='true'] {
209
+ outline: 3px solid var(--smrt-color-tertiary);
210
+ outline-offset: 3px;
211
+ }
212
+ .smrt-select__root:disabled {
213
+ background-color: var(--smrt-color-surface-container-high);
214
+ opacity: var(--smrt-state-disabled);
215
+ }
216
+ @media (max-width: 48rem) {
217
+ .smrt-select__root {
218
+ font-size: max(var(--smrt-typography-body-medium-size), 16px);
219
+ }
220
+ }
221
+ @media (prefers-reduced-motion: reduce) {
222
+ .smrt-select__root {
223
+ transition: none;
224
+ }
225
+ }
220
226
  }
221
227
  </style>
@@ -410,7 +410,7 @@ useControlRegistration(() => {
410
410
  min-width: var(--smrt-touch-target-min);
411
411
  min-height: var(--smrt-touch-target-min);
412
412
  padding: 0 var(--smrt-spacing-4);
413
- border: 1px solid var(--smrt-color-outline);
413
+ border: var(--smrt-hairline-strong);
414
414
  border-radius: var(--smrt-radius-small);
415
415
  background: var(--smrt-color-surface);
416
416
  color: var(--smrt-color-on-surface);
@@ -157,7 +157,7 @@ useControlRegistration(() => {
157
157
  .slider__header { justify-content: space-between; font: var(--smrt-typography-label-large-font); }
158
158
  output { color: var(--smrt-color-primary); font-variant-numeric: tabular-nums; }
159
159
  input[type='range'] { flex: 1; min-width: 8rem; accent-color: var(--smrt-color-primary); cursor: pointer; }
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); }
160
+ .slider__number { width: 5.5rem; padding: var(--smrt-spacing-2); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); }
161
161
  input:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
162
162
  .slider[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-small); }
163
163
  }
@@ -629,22 +629,22 @@ async function discardAll(event: MouseEvent): Promise<void> {
629
629
  <style>
630
630
  @layer smrt.reset, smrt.structure, smrt.theme;
631
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); }
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: var(--smrt-hairline); border-inline-start: 4px solid var(--smrt-color-tertiary); border-radius: var(--smrt-radius-medium, .5rem); }
633
633
  header, .proposal-heading, .batch-actions, .item-actions { display: flex; align-items: center; gap: var(--smrt-spacing-2, .5rem); }
634
634
  header { justify-content: space-between; align-items: flex-start; gap: var(--smrt-spacing-4, 1rem); }
635
635
  h2, p { margin: 0; } h2 { font: var(--smrt-typography-title-medium-font, 600 1rem/1.4 system-ui); }
636
636
  header p, .proposal-heading span, dt { color: var(--smrt-color-on-surface-variant); font-size: .875rem; }
637
637
  .proposal-heading strong, .proposal-heading .subject { display: block; }
638
638
  ul { display: grid; gap: var(--smrt-spacing-3, .75rem); padding: 0; list-style: none; }
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); }
639
+ li { padding: var(--smrt-spacing-3, .75rem); background: var(--smrt-color-surface); border: var(--smrt-hairline); border-radius: var(--smrt-radius-small, .375rem); }
640
640
  li.stale, li.invalid { border-color: var(--smrt-color-error); }
641
641
  .proposal-heading { justify-content: space-between; }
642
642
  dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--smrt-spacing-3, .75rem); }
643
643
  dt { font-weight: 600; } dd { margin: .25rem 0 0; overflow-wrap: anywhere; }
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); }
644
+ input, textarea { width: 100%; box-sizing: border-box; padding: .4rem .5rem; color: inherit; background: var(--smrt-color-surface); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small, .375rem); }
645
645
  input[type="checkbox"] { width: auto; }
646
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); }
647
+ button.secondary { color: var(--smrt-color-primary); background: transparent; border-color: var(--smrt-hairline-strong-color); }
648
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); }
649
649
  button:disabled { cursor: not-allowed; opacity: .55; }
650
650
  .item-actions { margin-block-start: var(--smrt-spacing-3, .75rem); }
@@ -116,54 +116,146 @@ useControlRegistration(() => {
116
116
  });
117
117
  </script>
118
118
 
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}
119
+ <label data-density={density} class="smrt-switch__root smrt-switch__{size} {className}" class:smrt-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
121
  data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id} data-smrt-component="Switch">
122
- {#if label && labelPosition === 'left'}<span class="switch__label">{label}</span>{/if}
123
- <span class="switch__control">
122
+ {#if label && labelPosition === 'left'}<span class="smrt-switch__label" data-smrt-part="label">{label}</span>{/if}
123
+ <span class="smrt-switch__control" data-smrt-part="control">
124
124
  <input bind:this={inputEl} id={resolvedId} type="checkbox" role="switch" {name} {value} {disabled} {required} checked={checked}
125
125
  aria-label={ariaLabel ?? label ?? formGroup?.().label} aria-describedby={formGroup?.().describedBy}
126
- aria-invalid={formGroup?.().invalid ? 'true' : undefined} onchange={handleChange} {...rest} />
127
- <span class="switch__track" aria-hidden="true"><span class="switch__thumb"></span></span>
126
+ aria-invalid={formGroup?.().invalid ? 'true' : undefined} onchange={handleChange} {...rest} data-smrt-part="input" />
127
+ <span class="smrt-switch__track" data-smrt-part="track" aria-hidden="true"><span class="smrt-switch__thumb" data-smrt-part="thumb"></span></span>
128
128
  </span>
129
- {#if label && labelPosition === 'right'}<span class="switch__label">{label}</span>{/if}
129
+ {#if label && labelPosition === 'right'}<span class="smrt-switch__label" data-smrt-part="label">{label}</span>{/if}
130
130
  </label>
131
131
 
132
132
  <style>
133
133
  @layer smrt.reset, smrt.structure, smrt.theme;
134
- @layer smrt.theme {
135
- .switch { display: inline-flex; align-items: center; gap: var(--smrt-spacing-2, .5rem); cursor: pointer; color: var(--smrt-color-on-surface); }
136
- .switch--disabled { opacity: .5; cursor: not-allowed; }
137
- /* Phones: the whole row (track and label) is at least a 44px touch target. */
138
- @media (max-width: 48rem) { .switch { min-block-size: 2.75rem; } }
134
+ @layer smrt.structure {
139
135
  /* The 2.75rem-wide track gets a transparent 44px-tall ::before hit area (see Checkbox); the
140
136
  track and label sit above every hit area. --smrt-control-hit-size resizes it (0px = off). */
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); }
143
- .switch__label { position: relative; z-index: 1; }
144
- input { position: absolute; width: 1px; height: 1px; opacity: 0; }
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); }
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); }
147
- input:checked + .switch__track { background: var(--smrt-color-primary); border-color: var(--smrt-color-primary); }
148
- input:checked + .switch__track .switch__thumb { transform: translateX(1.25rem); background: var(--smrt-color-on-primary); }
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); }
150
- .switch--sm { font-size: .8rem; transform-origin: left center; }
151
- .switch--lg .switch__track { transform: scale(1.15); margin-inline: .2rem; }
152
- .switch[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-full); }
153
- @media (prefers-reduced-motion: reduce) { .switch__track, .switch__thumb { transition: none; } }
154
-
155
- .switch[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
156
- .switch[data-density='comfortable'] { --smrt-control-target-min: 0px; }
157
- .switch { min-height: var(--smrt-control-target-min, 0px); min-width: var(--smrt-control-target-min, 0px); }
137
+ .smrt-switch__root {
138
+ display: inline-flex;
139
+ align-items: center;
140
+ gap: var(--smrt-spacing-2);
141
+ cursor: pointer;
142
+ }
143
+ .smrt-switch__disabled {
144
+ cursor: not-allowed;
145
+ }
146
+ @media (max-width: 48rem) {
147
+ .smrt-switch__root {
148
+ min-block-size: 2.75rem;
149
+ }
150
+ }
151
+ .smrt-switch__control {
152
+ --smrt-switch-hit: max(var(--smrt-control-hit-size, 2.75rem), 1.5rem);
153
+ position: relative;
154
+ display: inline-flex;
155
+ }
156
+ .smrt-switch__control::before {
157
+ content: '';
158
+ position: absolute;
159
+ z-index: 0;
160
+ inset-block-start: 50%;
161
+ inset-inline: calc((100% - var(--smrt-switch-hit)) / 2);
162
+ block-size: var(--smrt-switch-hit);
163
+ margin-block-start: calc(var(--smrt-switch-hit) / -2);
164
+ }
165
+ .smrt-switch__label {
166
+ position: relative;
167
+ z-index: 1;
168
+ }
169
+ input {
170
+ position: absolute;
171
+ width: 1px;
172
+ height: 1px;
173
+ opacity: 0;
174
+ }
175
+ .smrt-switch__track {
176
+ position: relative;
177
+ z-index: 1;
178
+ width: 2.75rem;
179
+ height: 1.5rem;
180
+ padding: 2px;
181
+ }
182
+ .smrt-switch__thumb {
183
+ display: block;
184
+ width: 1.125rem;
185
+ height: 1.125rem;
186
+ }
187
+ input:checked + .smrt-switch__track .smrt-switch__thumb {
188
+ transform: translateX(1.25rem);
189
+ }
190
+ .smrt-switch__sm {
191
+ transform-origin: left center;
192
+ }
193
+ .smrt-switch__lg .smrt-switch__track {
194
+ transform: scale(1.15);
195
+ margin-inline: .2rem;
196
+ }
197
+ .smrt-switch__root[data-density='touch'] {
198
+ --smrt-switch-target-min: var(--smrt-touch-target-min);
199
+ }
200
+ .smrt-switch__root[data-density='comfortable'] {
201
+ --smrt-switch-target-min: 0px;
202
+ }
203
+ .smrt-switch__root {
204
+ min-height: var(--smrt-switch-target-min, var(--smrt-control-target-min));
205
+ min-width: var(--smrt-switch-target-min, var(--smrt-control-target-min));
206
+ }
207
+ }
208
+ @layer smrt.theme {
209
+ .smrt-switch__root {
210
+ color: var(--smrt-color-on-surface);
211
+ }
212
+ .smrt-switch__disabled {
213
+ opacity: .5;
214
+ }
215
+ .smrt-switch__track {
216
+ border-radius: var(--smrt-radius-full);
217
+ background: var(--smrt-color-surface-container-highest);
218
+ border: var(--smrt-hairline-strong);
219
+ transition: background var(--smrt-duration-short2);
220
+ }
221
+ .smrt-switch__thumb {
222
+ border-radius: 50%;
223
+ background: var(--smrt-color-outline);
224
+ transition: transform var(--smrt-duration-short2), background var(--smrt-duration-short2);
225
+ }
226
+ input:checked + .smrt-switch__track {
227
+ background: var(--smrt-color-primary);
228
+ border-color: var(--smrt-color-primary);
229
+ }
230
+ input:checked + .smrt-switch__track .smrt-switch__thumb {
231
+ background: var(--smrt-color-on-primary);
232
+ }
233
+ input:focus-visible + .smrt-switch__track {
234
+ outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
235
+ outline-offset: var(--smrt-focus-ring-offset);
236
+ }
237
+ .smrt-switch__sm {
238
+ font-size: .8rem;
239
+ }
240
+ .smrt-switch__root[data-smrt-highlighted='true'] {
241
+ outline: 3px solid var(--smrt-color-tertiary);
242
+ outline-offset: 4px;
243
+ border-radius: var(--smrt-radius-full);
244
+ }
245
+ @media (prefers-reduced-motion: reduce) {
246
+ .smrt-switch__track, .smrt-switch__thumb {
247
+ transition: none;
248
+ }
249
+ }
158
250
  /* Forced colors (#3908): system colours where colour alone carries meaning. */
159
251
  @media (forced-colors: active) {
160
- .switch__track { background: Canvas; border-color: CanvasText; }
161
- .switch__thumb { background: CanvasText; }
162
- input:checked + .switch__track { background: Highlight; border-color: Highlight; }
163
- input:checked + .switch__track .switch__thumb { background: HighlightText; }
164
- .switch--disabled { opacity: 1; color: GrayText; }
165
- .switch--disabled .switch__track, .switch--disabled input:checked + .switch__track { background: Canvas; border-color: GrayText; }
166
- .switch--disabled .switch__thumb, .switch--disabled input:checked + .switch__track .switch__thumb { background: GrayText; }
252
+ .smrt-switch__track { background: Canvas; border-color: CanvasText; }
253
+ .smrt-switch__thumb { background: CanvasText; }
254
+ input:checked + .smrt-switch__track { background: Highlight; border-color: Highlight; }
255
+ input:checked + .smrt-switch__track .smrt-switch__thumb { background: HighlightText; }
256
+ .smrt-switch__disabled { opacity: 1; color: GrayText; }
257
+ .smrt-switch__disabled .smrt-switch__track, .smrt-switch__disabled input:checked + .smrt-switch__track { background: Canvas; border-color: GrayText; }
258
+ .smrt-switch__disabled .smrt-switch__thumb, .smrt-switch__disabled input:checked + .smrt-switch__track .smrt-switch__thumb { background: GrayText; }
167
259
  }
168
260
  }
169
261
  </style>
@@ -139,7 +139,7 @@ useControlRegistration(() => {
139
139
  @layer smrt.reset, smrt.structure, smrt.theme;
140
140
  @layer smrt.theme {
141
141
  .tags-field { display: grid; gap: var(--smrt-spacing-1); color: var(--smrt-color-on-surface); } label { font: var(--smrt-typography-label-large-font); }
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); }
142
+ .tags { display: flex; flex-wrap: wrap; gap: var(--smrt-spacing-1); min-height: 2.5rem; padding: var(--smrt-spacing-1); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); }
143
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); }
144
144
  .tag button { display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent; color: inherit; cursor: pointer; }
145
145
  /* Phones and touch screens: the × is a 44px target (the tag grows with it). */
@@ -94,7 +94,7 @@ useControlRegistration(() => {
94
94
  <style>
95
95
  @layer smrt.reset, smrt.structure, smrt.theme;
96
96
  @layer smrt.theme {
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; }
97
+ .toggle-button { display: inline-flex; align-items: center; justify-content: center; min-height: 2.5rem; padding: 0 var(--smrt-spacing-4); border: var(--smrt-hairline-strong); border-radius: var(--smrt-radius-full); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); cursor: pointer; }
98
98
  .toggle-button.pressed { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); border-color: var(--smrt-color-secondary); }
99
99
  .toggle-button:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
100
100
  .toggle-button:disabled { opacity: .5; cursor: not-allowed; }
@@ -35,7 +35,7 @@ const currentYear = new Date().getFullYear();
35
35
  @layer smrt.theme {
36
36
  .site-footer {
37
37
  background: var(--smrt-color-surface-container-low);
38
- border-top: 1px solid var(--smrt-color-outline-variant);
38
+ border-top: var(--smrt-hairline);
39
39
  padding: var(--smrt-spacing-8) 0;
40
40
  margin-top: var(--smrt-spacing-12);
41
41
  text-align: center;
@@ -90,7 +90,7 @@ const {
90
90
  @layer smrt.reset, smrt.structure, smrt.theme;
91
91
  @layer smrt.theme {
92
92
  .masthead {
93
- border-bottom: 1px solid var(--smrt-color-outline-variant);
93
+ border-bottom: var(--smrt-hairline);
94
94
  background: var(--smrt-color-surface);
95
95
  }
96
96
 
@@ -77,7 +77,7 @@ function formatDate(date: Date | string | null | undefined): string {
77
77
  .membership-card {
78
78
  padding: 1rem;
79
79
  background: var(--smrt-color-surface);
80
- border: 1px solid var(--smrt-color-outline-variant);
80
+ border: var(--smrt-hairline);
81
81
  border-radius: 0.5rem;
82
82
  }
83
83
 
@@ -132,7 +132,7 @@ function formatDate(date: Date | string | null | undefined): string {
132
132
  justify-content: space-between;
133
133
  margin-top: 0.75rem;
134
134
  padding-top: 0.75rem;
135
- border-top: 1px solid var(--smrt-color-outline-variant);
135
+ border-top: var(--smrt-hairline);
136
136
  }
137
137
 
138
138
  .date {
@@ -148,7 +148,7 @@ function formatDate(date: Date | string | null | undefined): string {
148
148
  .action-btn {
149
149
  padding: 0.25rem 0.5rem;
150
150
  background: none;
151
- border: 1px solid var(--smrt-color-outline);
151
+ border: var(--smrt-hairline-strong);
152
152
  border-radius: 0.25rem;
153
153
  font-size: var(--smrt-typography-label-medium-size, 0.75rem);
154
154
  color: var(--smrt-color-on-surface-variant);
@@ -102,7 +102,7 @@ function handleClick(value: string) {
102
102
  font-weight: var(--smrt-typography-weight-medium, 500);
103
103
  color: var(--smrt-color-on-surface-variant);
104
104
  background-color: transparent;
105
- border: 1px solid var(--smrt-color-outline);
105
+ border: var(--smrt-hairline-strong);
106
106
  border-radius: var(--smrt-radius-md);
107
107
  cursor: pointer;
108
108
  transition: all 200ms cubic-bezier(0.2, 0, 0, 1);