@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.
- package/AGENTS.md +14 -0
- package/README.md +75 -0
- package/dist/components/calendar/Calendar.svelte +59 -56
- package/dist/components/calendar/CalendarView.svelte +80 -77
- package/dist/components/calendar/DayView.svelte +39 -36
- package/dist/components/chat/MessageBubble.svelte +26 -23
- package/dist/components/chat/ReactionPicker.svelte +12 -9
- package/dist/components/chat/TypingIndicator.svelte +12 -9
- package/dist/components/data/CollectionList.svelte +11 -8
- package/dist/components/data/CollectionToolbar.svelte +5 -2
- package/dist/components/data/DataTable.svelte +74 -59
- package/dist/components/data/ListSortSelect.svelte +8 -5
- package/dist/components/data/SortableHeader.svelte +10 -7
- package/dist/components/display/ConfidenceBadge.svelte +11 -8
- package/dist/components/display/CurrencyDisplay.svelte +7 -4
- package/dist/components/display/DateDisplay.svelte +6 -3
- package/dist/components/display/Icon.svelte +4 -1
- package/dist/components/display/StatusBadge.svelte +9 -6
- package/dist/components/feedback/Alert.svelte +12 -8
- package/dist/components/feedback/ConfirmDialog.svelte +13 -10
- package/dist/components/feedback/LoadingOverlay.svelte +37 -34
- package/dist/components/feedback/Meter.svelte +4 -1
- package/dist/components/feedback/Modal.svelte +26 -21
- package/dist/components/feedback/PhoneSheet.svelte +6 -3
- package/dist/components/feedback/Progress.svelte +8 -5
- package/dist/components/feedback/ProgressBar.svelte +13 -10
- package/dist/components/feedback/Spinner.svelte +4 -1
- package/dist/components/feedback/ToastViewport.svelte +18 -15
- package/dist/components/feedback/WorkingStrip.svelte +6 -3
- package/dist/components/forms/CameraCapture.svelte +8 -5
- package/dist/components/forms/Checkbox.svelte +11 -8
- package/dist/components/forms/Combobox.svelte +5 -2
- package/dist/components/forms/DatePicker.svelte +7 -2
- package/dist/components/forms/DictationButton.svelte +17 -14
- package/dist/components/forms/DictationStatus.svelte +12 -9
- package/dist/components/forms/ErrorSummary.svelte +4 -1
- package/dist/components/forms/FieldLabel.svelte +9 -6
- package/dist/components/forms/Fieldset.svelte +4 -1
- package/dist/components/forms/FilePicker.svelte +5 -2
- package/dist/components/forms/Form.svelte +1 -1
- package/dist/components/forms/FormActionBar.svelte +4 -1
- package/dist/components/forms/FormGroup.svelte +6 -3
- package/dist/components/forms/Input.svelte +22 -15
- package/dist/components/forms/InputGroup.svelte +6 -3
- package/dist/components/forms/Listbox.svelte +5 -2
- package/dist/components/forms/MultiSelect.svelte +4 -1
- package/dist/components/forms/Radio.svelte +9 -6
- package/dist/components/forms/RadioGroup.svelte +5 -2
- package/dist/components/forms/RangeSlider.svelte +5 -2
- package/dist/components/forms/RelationInput.svelte +7 -4
- package/dist/components/forms/SearchInput.svelte +7 -4
- package/dist/components/forms/SegmentedControl.svelte +6 -3
- package/dist/components/forms/Select.svelte +20 -13
- package/dist/components/forms/SignaturePad.svelte +8 -5
- package/dist/components/forms/Slider.svelte +5 -2
- package/dist/components/forms/StagedControlReview.svelte +15 -12
- package/dist/components/forms/Switch.svelte +8 -5
- package/dist/components/forms/TagsInput.svelte +5 -2
- package/dist/components/forms/Textarea.svelte +20 -13
- package/dist/components/forms/TimePicker.svelte +7 -2
- package/dist/components/forms/Toggle.svelte +14 -11
- package/dist/components/forms/ToggleButton.svelte +5 -2
- package/dist/components/layout/ActionGroup.svelte +4 -1
- package/dist/components/layout/Container.svelte +4 -1
- package/dist/components/layout/EmptyState.svelte +11 -8
- package/dist/components/layout/Footer.svelte +4 -1
- package/dist/components/layout/Grid.svelte +13 -10
- package/dist/components/layout/Header.svelte +4 -1
- package/dist/components/layout/Masthead.svelte +4 -1
- package/dist/components/layout/PageHeader.svelte +12 -9
- package/dist/components/layout/PageLayout.svelte +3 -0
- package/dist/components/layout/SummaryCard.svelte +9 -6
- package/dist/components/memberships/MembershipCard.svelte +5 -2
- package/dist/components/memberships/MembershipList.svelte +5 -2
- package/dist/components/nav/FilterChips.svelte +13 -10
- package/dist/components/nav/Tabs.svelte +75 -41
- package/dist/components/permissions/PermissionPicker.svelte +5 -2
- package/dist/components/roles/RoleBadge.svelte +8 -5
- package/dist/components/roles/RoleSelector.svelte +22 -19
- package/dist/components/theme/ThemeProvider.svelte +7 -4
- package/dist/components/ui/Accordion.svelte +4 -1
- package/dist/components/ui/AccordionItem.svelte +5 -2
- package/dist/components/ui/Avatar.svelte +10 -7
- package/dist/components/ui/Badge.svelte +6 -2
- package/dist/components/ui/Button.svelte +49 -37
- package/dist/components/ui/Card.svelte +18 -14
- package/dist/components/ui/Chip.svelte +41 -14
- package/dist/components/ui/Disclosure.svelte +5 -2
- package/dist/components/ui/Dropdown.svelte +33 -25
- package/dist/components/ui/IconToggle.svelte +12 -9
- package/dist/components/ui/IconToggle.svelte.d.ts +1 -1
- package/dist/components/ui/IconToggle.svelte.d.ts.map +1 -1
- package/dist/components/ui/IconToggleGroup.svelte +8 -5
- package/dist/components/ui/Pagination.svelte +11 -8
- package/dist/components/ui/Popover.svelte +9 -6
- package/dist/components/ui/Skeleton.svelte +10 -7
- package/dist/components/ui/Tooltip.svelte +13 -9
- package/dist/components/ui/Tree.svelte +12 -9
- package/dist/styles/layers.css +8 -0
- package/dist/styles/layers.d.ts +9 -0
- package/dist/styles/layers.d.ts.map +1 -0
- package/dist/styles/layers.js +8 -0
- package/dist/styles/tokens.css +27 -69
- package/dist/styles/unstyled.css +65 -0
- package/dist/svelte/playground/BaseControlsPreview.svelte +3 -0
- package/dist/svelte/playground/CalendarPreview.svelte +5 -2
- package/dist/svelte/playground/CapturePreview.svelte +3 -0
- package/dist/svelte/playground/CodeSelectorsPreview.svelte +3 -0
- package/dist/svelte/playground/CollectionsPreview.svelte +3 -0
- package/dist/svelte/playground/DataTablePreview.svelte +3 -0
- package/dist/svelte/playground/FeedbackPreview.svelte +3 -0
- package/dist/svelte/playground/InteractiveControlsPreview.svelte +3 -0
- package/dist/svelte/playground/StylelessPreview.svelte +110 -0
- package/dist/svelte/playground/StylelessPreview.svelte.d.ts +4 -0
- package/dist/svelte/playground/StylelessPreview.svelte.d.ts.map +1 -0
- package/dist/svelte/playground.d.ts.map +1 -1
- package/dist/svelte/playground.js +10 -0
- package/dist/test-support/setup.js +9 -0
- package/dist/theme/ThemeProvider.svelte +3 -0
- package/dist/themes/CUSTOM_THEME_GUIDE.md +40 -0
- package/dist/themes/README.md +151 -0
- package/dist/themes/ThemeProvider.svelte +181 -12
- package/dist/themes/ThemeProvider.svelte.d.ts +7 -2
- package/dist/themes/ThemeProvider.svelte.d.ts.map +1 -1
- package/dist/themes/components/ColorSchemeToggle.svelte +17 -14
- package/dist/themes/components/ThemeSwitcher.svelte +14 -11
- package/dist/themes/create-theme.d.ts +22 -1
- package/dist/themes/create-theme.d.ts.map +1 -1
- package/dist/themes/create-theme.js +100 -9
- package/dist/themes/css-generator.d.ts.map +1 -1
- package/dist/themes/css-generator.js +20 -20
- package/dist/themes/derive.d.ts +31 -0
- package/dist/themes/derive.d.ts.map +1 -0
- package/dist/themes/derive.js +183 -0
- package/dist/themes/glass/index.d.ts.map +1 -1
- package/dist/themes/glass/index.js +127 -14
- package/dist/themes/happyvertical/index.d.ts.map +1 -1
- package/dist/themes/happyvertical/index.js +101 -20
- package/dist/themes/index.d.ts +2 -2
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +1 -1
- package/dist/themes/material/index.d.ts.map +1 -1
- package/dist/themes/material/index.js +129 -28
- package/dist/themes/required-tokens.generated.json +201 -0
- package/dist/themes/shared.d.ts +35 -0
- package/dist/themes/shared.d.ts.map +1 -1
- package/dist/themes/shared.js +32 -0
- package/dist/themes/smrt/index.d.ts +3 -0
- package/dist/themes/smrt/index.d.ts.map +1 -1
- package/dist/themes/smrt/index.js +108 -26
- package/dist/themes/studio/index.d.ts.map +1 -1
- package/dist/themes/studio/index.js +116 -40
- package/dist/themes/styles/base.css +229 -1
- package/dist/themes/styles/glass.css +107 -20
- package/dist/themes/styles/happyvertical.css +111 -15
- package/dist/themes/styles/material.css +127 -35
- package/dist/themes/styles/smrt.css +126 -31
- package/dist/themes/styles/studio.css +132 -37
- package/dist/themes/theme-script.d.ts +3 -1
- package/dist/themes/theme-script.d.ts.map +1 -1
- package/dist/themes/theme-script.js +7 -2
- package/dist/themes/types.d.ts +118 -6
- package/dist/themes/types.d.ts.map +1 -1
- package/dist/utils/theme/typography.d.ts +21 -21
- package/dist/utils/theme/typography.js +21 -21
- package/package.json +8 -2
|
@@ -71,7 +71,7 @@ function errorText(kind: DictationErrorKind | null): string {
|
|
|
71
71
|
}
|
|
72
72
|
</script>
|
|
73
73
|
|
|
74
|
-
<div class={`smrt-dictation-status ${className}`.trim()}>
|
|
74
|
+
<div class={`smrt-dictation-status ${className}`.trim()} data-smrt-component="DictationStatus">
|
|
75
75
|
<p
|
|
76
76
|
class="smrt-dictation-status-line"
|
|
77
77
|
class:smrt-dictation-status--empty={!showLine || announceOnly}
|
|
@@ -118,6 +118,8 @@ function errorText(kind: DictationErrorKind | null): string {
|
|
|
118
118
|
</div>
|
|
119
119
|
|
|
120
120
|
<style>
|
|
121
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
122
|
+
@layer smrt.theme {
|
|
121
123
|
.smrt-dictation-status {
|
|
122
124
|
display: contents;
|
|
123
125
|
}
|
|
@@ -135,7 +137,7 @@ function errorText(kind: DictationErrorKind | null): string {
|
|
|
135
137
|
align-items: center;
|
|
136
138
|
gap: 0.4rem;
|
|
137
139
|
padding: 0.25rem 0;
|
|
138
|
-
color: var(--smrt-color-on-surface
|
|
140
|
+
color: var(--smrt-color-on-surface);
|
|
139
141
|
}
|
|
140
142
|
|
|
141
143
|
/* Kept mounted while empty (live regions must exist before they speak),
|
|
@@ -154,15 +156,15 @@ function errorText(kind: DictationErrorKind | null): string {
|
|
|
154
156
|
inline-size: 8px;
|
|
155
157
|
block-size: 8px;
|
|
156
158
|
border-radius: 50%;
|
|
157
|
-
background: var(--smrt-color-error
|
|
159
|
+
background: var(--smrt-color-error);
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
.smrt-dictation-status-spinner {
|
|
161
163
|
inline-size: 12px;
|
|
162
164
|
block-size: 12px;
|
|
163
165
|
border-radius: 50%;
|
|
164
|
-
border: 2px solid var(--smrt-color-outline-variant
|
|
165
|
-
border-block-start-color: var(--smrt-color-primary
|
|
166
|
+
border: 2px solid var(--smrt-color-outline-variant);
|
|
167
|
+
border-block-start-color: var(--smrt-color-primary);
|
|
166
168
|
animation: smrt-dictation-spin 0.9s linear infinite;
|
|
167
169
|
}
|
|
168
170
|
|
|
@@ -179,14 +181,15 @@ function errorText(kind: DictationErrorKind | null): string {
|
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
.smrt-dictation-status-interim {
|
|
182
|
-
color: var(--smrt-color-on-surface-variant
|
|
184
|
+
color: var(--smrt-color-on-surface-variant);
|
|
183
185
|
font-style: italic;
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
.smrt-dictation-status-error {
|
|
187
189
|
padding: 0.4rem 0.6rem;
|
|
188
|
-
border-radius: var(--smrt-radius-medium
|
|
189
|
-
background: var(--smrt-color-error-container
|
|
190
|
-
color: var(--smrt-color-on-error-container
|
|
190
|
+
border-radius: var(--smrt-radius-medium);
|
|
191
|
+
background: var(--smrt-color-error-container);
|
|
192
|
+
color: var(--smrt-color-on-error-container);
|
|
191
193
|
}
|
|
194
|
+
}
|
|
192
195
|
</style>
|
|
@@ -28,9 +28,12 @@ function select(error: FormError) {
|
|
|
28
28
|
onselect?.(error.controlId);
|
|
29
29
|
}
|
|
30
30
|
</script>
|
|
31
|
-
{#if errors.length > 0}<section class="error-summary {className}" role="alert" aria-labelledby={titleId}><h2 id={titleId}>{title}</h2><ul>{#each errors as error}<li><button type="button" onclick={() => select(error)}>{error.label ? `${error.label}: ` : ''}{error.message}</button></li>{/each}</ul></section>{/if}
|
|
31
|
+
{#if errors.length > 0}<section class="error-summary {className}" role="alert" aria-labelledby={titleId} data-smrt-component="ErrorSummary"><h2 id={titleId}>{title}</h2><ul>{#each errors as error}<li><button type="button" onclick={() => select(error)}>{error.label ? `${error.label}: ` : ''}{error.message}</button></li>{/each}</ul></section>{/if}
|
|
32
32
|
<style>
|
|
33
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
34
|
+
@layer smrt.theme {
|
|
33
35
|
.error-summary { padding: var(--smrt-spacing-4); border-inline-start: 4px solid var(--smrt-color-error); border-radius: var(--smrt-radius-small); background: var(--smrt-color-error-container); color: var(--smrt-color-on-error-container); }
|
|
34
36
|
h2 { margin: 0 0 var(--smrt-spacing-2); font: var(--smrt-typography-title-small-font); } ul { margin: 0; padding-inline-start: var(--smrt-spacing-5); }
|
|
35
37
|
button { padding: 0; border: 0; background: transparent; color: inherit; text-decoration: underline; cursor: pointer; }
|
|
38
|
+
}
|
|
36
39
|
</style>
|
|
@@ -19,26 +19,29 @@ let { label, for: forId, id, required = false }: Props = $props();
|
|
|
19
19
|
</script>
|
|
20
20
|
|
|
21
21
|
{#if forId}
|
|
22
|
-
<label {id} for={forId} class="smrt-field-label">{label}{#if required}<span class="required" aria-hidden="true">*</span>{/if}</label>
|
|
22
|
+
<label {id} for={forId} class="smrt-field-label" data-smrt-component="FieldLabel">{label}{#if required}<span class="required" aria-hidden="true">*</span>{/if}</label>
|
|
23
23
|
{:else}
|
|
24
|
-
<span {id} class="smrt-field-label">{label}{#if required}<span class="required" aria-hidden="true">*</span>{/if}</span>
|
|
24
|
+
<span {id} class="smrt-field-label" data-smrt-component="FieldLabel">{label}{#if required}<span class="required" aria-hidden="true">*</span>{/if}</span>
|
|
25
25
|
{/if}
|
|
26
26
|
|
|
27
27
|
<style>
|
|
28
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
29
|
+
@layer smrt.theme {
|
|
28
30
|
.smrt-field-label {
|
|
29
31
|
display: block;
|
|
30
|
-
margin-bottom: var(--smrt-spacing-1
|
|
32
|
+
margin-bottom: var(--smrt-spacing-1);
|
|
31
33
|
font-size: var(--smrt-typography-label-large-size, 0.875rem);
|
|
32
34
|
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
33
35
|
line-height: var(--smrt-typography-label-large-line-height, 1.4);
|
|
34
36
|
letter-spacing: normal;
|
|
35
37
|
text-transform: none;
|
|
36
38
|
font-family: inherit;
|
|
37
|
-
color: var(--smrt-color-on-surface
|
|
39
|
+
color: var(--smrt-color-on-surface);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
.required {
|
|
41
|
-
color: var(--smrt-color-error
|
|
42
|
-
margin-left: var(--smrt-spacing-1
|
|
43
|
+
color: var(--smrt-color-error);
|
|
44
|
+
margin-left: var(--smrt-spacing-1);
|
|
43
45
|
}
|
|
46
|
+
}
|
|
44
47
|
</style>
|
|
@@ -30,12 +30,15 @@ const descriptionId = $derived(
|
|
|
30
30
|
);
|
|
31
31
|
const errorId = $derived(error ? `fieldset-${instanceId}-error` : undefined);
|
|
32
32
|
</script>
|
|
33
|
-
<fieldset class="fieldset {className}" aria-describedby={[descriptionId, errorId].filter(Boolean).join(' ') || undefined} {...rest}>
|
|
33
|
+
<fieldset class="fieldset {className}" aria-describedby={[descriptionId, errorId].filter(Boolean).join(' ') || undefined} {...rest} data-smrt-component="Fieldset">
|
|
34
34
|
<legend>{legend}</legend>{#if description}<p id={descriptionId} class="description">{description}</p>{/if}<div class="content" class:content--stack={stack}>{@render children()}</div>{#if error}<p id={errorId} class="error" role="alert">{error}</p>{/if}
|
|
35
35
|
</fieldset>
|
|
36
36
|
<style>
|
|
37
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
38
|
+
@layer smrt.theme {
|
|
37
39
|
.fieldset { margin: 0; padding: var(--smrt-spacing-4); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-medium); }
|
|
38
40
|
legend { padding: 0 var(--smrt-spacing-2); color: var(--smrt-color-on-surface); font: var(--smrt-typography-title-small-font); }
|
|
39
41
|
.content--stack { display: grid; gap: var(--smrt-spacing-4); }
|
|
40
42
|
.description, .error { margin: 0 0 var(--smrt-spacing-3); font: var(--smrt-typography-body-small-font); color: var(--smrt-color-on-surface-variant); } .error { margin: var(--smrt-spacing-3) 0 0; color: var(--smrt-color-error); }
|
|
43
|
+
}
|
|
41
44
|
</style>
|
|
@@ -111,16 +111,19 @@ useControlRegistration(() => {
|
|
|
111
111
|
data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
|
|
112
112
|
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}
|
|
113
113
|
ondragenter={(event) => { event.preventDefault(); dragging = true; }}
|
|
114
|
-
ondragover={(event) => event.preventDefault()} ondragleave={() => dragging = false} ondrop={handleDrop}>
|
|
114
|
+
ondragover={(event) => event.preventDefault()} ondragleave={() => dragging = false} ondrop={handleDrop} data-smrt-component="FilePicker">
|
|
115
115
|
<input bind:this={inputEl} id={resolvedId} type="file" {name} {accept} {multiple} {disabled} {required} onchange={handleChange} {...rest} />
|
|
116
116
|
<span class="label">{label}</span><span class="description">{files.length ? `${files.length} file${files.length === 1 ? '' : 's'} selected` : description}</span>
|
|
117
117
|
</label>
|
|
118
118
|
<style>
|
|
119
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
120
|
+
@layer smrt.theme {
|
|
119
121
|
.file-picker { display: inline-flex; flex-direction: column; gap: var(--smrt-spacing-1); padding: var(--smrt-spacing-3) var(--smrt-spacing-4); border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-small); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); cursor: pointer; }
|
|
120
122
|
.file-picker.dropzone { width: 100%; min-height: 8rem; align-items: center; justify-content: center; border-style: dashed; text-align: center; }
|
|
121
123
|
.file-picker.dragging { border-color: var(--smrt-color-primary); background: var(--smrt-color-primary-container); }
|
|
122
124
|
.file-picker.disabled { opacity: .5; cursor: not-allowed; } input { position: absolute; width: 1px; height: 1px; opacity: 0; }
|
|
123
|
-
input:focus-visible ~ .label { outline:
|
|
125
|
+
input:focus-visible ~ .label { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
|
|
124
126
|
.label { font: var(--smrt-typography-label-large-font); } .description { font: var(--smrt-typography-body-small-font); color: var(--smrt-color-on-surface-variant); }
|
|
125
127
|
.file-picker[data-smrt-highlighted='true'] { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
|
|
128
|
+
}
|
|
126
129
|
</style>
|
|
@@ -152,7 +152,7 @@ function handleChange(event: Event & { currentTarget: HTMLFormElement }) {
|
|
|
152
152
|
{onclick}
|
|
153
153
|
oninput={handleInput}
|
|
154
154
|
onchange={handleChange}
|
|
155
|
-
{...rest}
|
|
155
|
+
{...rest} data-smrt-component="Form"
|
|
156
156
|
>
|
|
157
157
|
{@render children()}
|
|
158
158
|
<StagedControlReview
|
|
@@ -33,12 +33,14 @@ const { t } = useI18n();
|
|
|
33
33
|
role="group"
|
|
34
34
|
aria-label={label ?? t(M['ui.form_action_bar.label'])}
|
|
35
35
|
data-form-action-bar
|
|
36
|
-
data-testid="form-action-bar"
|
|
36
|
+
data-testid="form-action-bar" data-smrt-component="FormActionBar"
|
|
37
37
|
>
|
|
38
38
|
{@render children()}
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
41
|
<style>
|
|
42
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
43
|
+
@layer smrt.theme {
|
|
42
44
|
.form-action-bar {
|
|
43
45
|
display: flex;
|
|
44
46
|
flex-wrap: wrap;
|
|
@@ -81,4 +83,5 @@ const { t } = useI18n();
|
|
|
81
83
|
display: none;
|
|
82
84
|
}
|
|
83
85
|
}
|
|
86
|
+
}
|
|
84
87
|
</style>
|
|
@@ -62,7 +62,7 @@ setFormGroupContext(
|
|
|
62
62
|
);
|
|
63
63
|
</script>
|
|
64
64
|
|
|
65
|
-
<div class="form-group">
|
|
65
|
+
<div class="form-group" data-smrt-component="FormGroup">
|
|
66
66
|
<FieldLabel for={fieldId} {label} {required} />
|
|
67
67
|
{@render children()}
|
|
68
68
|
{#if hintId}
|
|
@@ -74,6 +74,8 @@ setFormGroupContext(
|
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
76
|
<style>
|
|
77
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
78
|
+
@layer smrt.theme {
|
|
77
79
|
.form-group {
|
|
78
80
|
margin-bottom: 1rem;
|
|
79
81
|
}
|
|
@@ -83,12 +85,13 @@ setFormGroupContext(
|
|
|
83
85
|
.form-hint {
|
|
84
86
|
margin: 0.25rem 0 0;
|
|
85
87
|
font-size: var(--smrt-typography-body-small-size, 0.75rem);
|
|
86
|
-
color: var(--smrt-color-on-surface-variant
|
|
88
|
+
color: var(--smrt-color-on-surface-variant);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
.form-error {
|
|
90
92
|
margin: 0.25rem 0 0;
|
|
91
93
|
font-size: var(--smrt-typography-body-small-size, 0.75rem);
|
|
92
|
-
color: var(--smrt-color-error
|
|
94
|
+
color: var(--smrt-color-error);
|
|
93
95
|
}
|
|
96
|
+
}
|
|
94
97
|
</style>
|
|
@@ -218,46 +218,52 @@ export function getElement(): HTMLInputElement | null {
|
|
|
218
218
|
data-smrt-form={controlInteraction?.formId}
|
|
219
219
|
data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
|
|
220
220
|
data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id}
|
|
221
|
-
{...rest}
|
|
221
|
+
{...rest} data-smrt-component="Input"
|
|
222
222
|
/>
|
|
223
223
|
|
|
224
224
|
<style>
|
|
225
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
226
|
+
@layer smrt.theme {
|
|
225
227
|
.input {
|
|
226
228
|
box-sizing: border-box;
|
|
227
229
|
display: block;
|
|
228
230
|
width: 100%;
|
|
229
231
|
padding: 0.5rem 0.75rem;
|
|
230
232
|
font-size: var(--smrt-typography-body-medium-size, 0.875rem);
|
|
233
|
+
font-weight: var(--smrt-control-weight);
|
|
231
234
|
line-height: var(--smrt-typography-body-medium-line-height, 1.5);
|
|
232
|
-
color: var(--smrt-color-on-surface
|
|
233
|
-
background-color: var(--smrt-
|
|
234
|
-
border:
|
|
235
|
-
border-radius: var(--smrt-radius
|
|
235
|
+
color: var(--smrt-color-on-surface);
|
|
236
|
+
background-color: var(--smrt-surface-control);
|
|
237
|
+
border: var(--smrt-hairline-strong);
|
|
238
|
+
border-radius: var(--smrt-control-radius);
|
|
236
239
|
transition:
|
|
237
240
|
border-color var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease-in-out),
|
|
238
241
|
box-shadow var(--smrt-duration-short2, 150ms) var(--smrt-easing-standard, ease-in-out);
|
|
239
242
|
}
|
|
240
243
|
|
|
241
244
|
.input:focus {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
border-color: var(--smrt-color-primary);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.input:focus-visible {
|
|
249
|
+
outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
|
|
250
|
+
outline-offset: var(--smrt-focus-ring-offset);
|
|
245
251
|
}
|
|
246
252
|
|
|
247
253
|
.input[data-smrt-highlighted='true'] {
|
|
248
|
-
outline: 3px solid var(--smrt-color-tertiary
|
|
254
|
+
outline: 3px solid var(--smrt-color-tertiary);
|
|
249
255
|
outline-offset: 3px;
|
|
250
|
-
box-shadow: 0 0 0 6px color-mix(in srgb, var(--smrt-color-tertiary
|
|
256
|
+
box-shadow: 0 0 0 6px color-mix(in srgb, var(--smrt-color-tertiary) 20%, transparent);
|
|
251
257
|
}
|
|
252
258
|
|
|
253
259
|
.input:disabled {
|
|
254
|
-
background-color: var(--smrt-color-surface-container-high
|
|
260
|
+
background-color: var(--smrt-color-surface-container-high);
|
|
255
261
|
cursor: not-allowed;
|
|
256
|
-
opacity:
|
|
262
|
+
opacity: var(--smrt-state-disabled);
|
|
257
263
|
}
|
|
258
264
|
|
|
259
265
|
.input::placeholder {
|
|
260
|
-
color: var(--smrt-color-on-surface-variant
|
|
266
|
+
color: var(--smrt-color-on-surface-variant);
|
|
261
267
|
}
|
|
262
268
|
|
|
263
269
|
/* Phones: 16px text so iOS Safari doesn't zoom the page when the field
|
|
@@ -275,7 +281,8 @@ export function getElement(): HTMLInputElement | null {
|
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
283
|
|
|
278
|
-
.input[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min
|
|
284
|
+
.input[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
|
|
279
285
|
.input[data-density='comfortable'] { --smrt-control-target-min: 0px; }
|
|
280
|
-
.input { min-height: var(--smrt-control-target-min, 0px); }
|
|
286
|
+
.input { min-height: max(var(--smrt-control-height), var(--smrt-control-target-min, 0px)); }
|
|
287
|
+
}
|
|
281
288
|
</style>
|
|
@@ -12,10 +12,13 @@ export interface Props {
|
|
|
12
12
|
}
|
|
13
13
|
let { prefix, suffix, children, class: className = '' }: Props = $props();
|
|
14
14
|
</script>
|
|
15
|
-
<div class="input-group {className}">{#if prefix}<span class="adornment">{@render prefix()}</span>{/if}<div class="control">{@render children()}</div>{#if suffix}<span class="adornment">{@render suffix()}</span>{/if}</div>
|
|
15
|
+
<div class="input-group {className}" data-smrt-component="InputGroup">{#if prefix}<span class="adornment">{@render prefix()}</span>{/if}<div class="control">{@render children()}</div>{#if suffix}<span class="adornment">{@render suffix()}</span>{/if}</div>
|
|
16
16
|
<style>
|
|
17
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
18
|
+
@layer smrt.theme {
|
|
17
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; }
|
|
18
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); }
|
|
19
|
-
.control { flex: 1; min-width: 0; } .control :global(input), .control :global(select), .control :global(textarea) { border: 0
|
|
20
|
-
.input-group:focus-within { outline:
|
|
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
|
+
.input-group:focus-within { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
|
|
23
|
+
}
|
|
21
24
|
</style>
|
|
@@ -156,15 +156,18 @@ useControlRegistration(() => {
|
|
|
156
156
|
</script>
|
|
157
157
|
<div bind:this={rootEl} class="listbox {className}" role="listbox" aria-label={label} aria-disabled={disabled} data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
|
|
158
158
|
data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
|
|
159
|
-
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}>
|
|
159
|
+
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id} data-smrt-component="Listbox">
|
|
160
160
|
{#if name}<input type="hidden" {name} value={value ?? ''} disabled={disabled || matchingOption(options, value)?.disabled} />{/if}
|
|
161
161
|
{#each options as option, index (option.value)}<button bind:this={optionEls[index]} type="button" role="option" aria-selected={value === option.value}
|
|
162
162
|
disabled={disabled || option.disabled} tabindex={value === option.value || (value === undefined && index === 0) ? 0 : -1}
|
|
163
163
|
onkeydown={(event) => move(event, index)} onclick={() => select(option.value, true)}>{option.label}</button>{/each}
|
|
164
164
|
</div>
|
|
165
165
|
<style>
|
|
166
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
167
|
+
@layer smrt.theme {
|
|
166
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); }
|
|
167
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; }
|
|
168
|
-
button[aria-selected='true'] { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); } button:focus-visible { outline:
|
|
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); }
|
|
169
171
|
button:disabled { opacity: .5; cursor: not-allowed; } :global(.listbox[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
|
|
172
|
+
}
|
|
170
173
|
</style>
|
|
@@ -216,15 +216,18 @@ useControlRegistration(() => {
|
|
|
216
216
|
</script>
|
|
217
217
|
<div bind:this={rootEl} class="multi-select {className}" data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
|
|
218
218
|
data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
|
|
219
|
-
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}>
|
|
219
|
+
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id} data-smrt-component="MultiSelect">
|
|
220
220
|
{#if name}{#each canonicalValues as value}<input type="hidden" {name} value={String(value)} disabled={disabled || options.some((option) => Object.is(option.value, value) && option.disabled)} />{/each}{/if}
|
|
221
221
|
<span class="label" id={`${listId}-label`}>{label}</span><button bind:this={triggerEl} id={triggerId} type="button" class="trigger" {disabled} aria-haspopup="listbox" aria-expanded={open} aria-controls={listId} aria-labelledby={`${listId}-label ${triggerId}`} onclick={() => open ? closeOptions() : openOptions()} onkeydown={handleTriggerKeydown}>{selectedLabels.length ? selectedLabels.join(', ') : placeholder}</button>
|
|
222
222
|
{#if open}<div id={listId} class="options" role="listbox" tabindex="-1" aria-multiselectable="true" aria-labelledby={`${listId}-label`} onkeydown={handleOptionsKeydown}>{#each options as option, index (option.value)}<button bind:this={optionEls[index]} type="button" role="option" tabindex="-1" aria-selected={canonicalValues.some((value) => Object.is(value, option.value))} disabled={option.disabled} onclick={() => toggle(option)}><span aria-hidden="true">{canonicalValues.some((value) => Object.is(value, option.value)) ? '✓' : ''}</span>{option.label}</button>{/each}</div>{/if}
|
|
223
223
|
</div>
|
|
224
224
|
<style>
|
|
225
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
226
|
+
@layer smrt.theme {
|
|
225
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); }
|
|
226
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; }
|
|
227
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
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); }
|
|
229
231
|
:global(.multi-select[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
|
|
232
|
+
}
|
|
230
233
|
</style>
|
|
@@ -20,20 +20,22 @@ function handleChange(event: Event & { currentTarget: HTMLInputElement }) {
|
|
|
20
20
|
onchange?.(event);
|
|
21
21
|
}
|
|
22
22
|
</script>
|
|
23
|
-
<label class="radio" class:disabled={disabled || group.disabled} data-smrt-hit-target>
|
|
23
|
+
<label class="radio" class:disabled={disabled || group.disabled} data-smrt-hit-target data-smrt-component="Radio">
|
|
24
24
|
<input id={resolvedId} type="radio" name={group.name} {value} disabled={disabled || group.disabled} required={group.required}
|
|
25
25
|
checked={group.value === value} onchange={handleChange} {...rest} />
|
|
26
26
|
<span class="radio__mark" aria-hidden="true"></span><span class="radio__label">{label}</span>
|
|
27
27
|
</label>
|
|
28
28
|
<style>
|
|
29
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
30
|
+
@layer smrt.theme {
|
|
29
31
|
/* The visible mark stays 18px; a transparent 44x44 ::before hit area (see Checkbox) makes the
|
|
30
32
|
touch target. Mark and label text sit above every hit area, so neighbours' hit areas never
|
|
31
33
|
steal their clicks. Beside other content (a group's other options, text, a link) it keeps to
|
|
32
34
|
the mark's column and grows vertically only. --smrt-control-hit-size resizes it (0px turns it
|
|
33
35
|
off). */
|
|
34
|
-
.radio { --
|
|
35
|
-
.radio::before { content: ''; position: absolute; z-index: 0; inset-block-start: 50%; inset-inline-start: calc(var(--
|
|
36
|
-
.radio:not(:only-child)::before { inline-size: var(--
|
|
36
|
+
.radio { --smrt-radio-box: 1.15rem; --smrt-radio-hit: max(var(--smrt-control-hit-size, 2.75rem), var(--smrt-radio-box)); position: relative; display: inline-flex; align-items: center; gap: var(--smrt-spacing-2); cursor: pointer; }
|
|
37
|
+
.radio::before { content: ''; position: absolute; z-index: 0; inset-block-start: 50%; inset-inline-start: calc(var(--smrt-radio-box) / 2); inline-size: var(--smrt-radio-hit); block-size: var(--smrt-radio-hit); margin-block-start: calc(var(--smrt-radio-hit) / -2); margin-inline-start: calc(var(--smrt-radio-hit) / -2); }
|
|
38
|
+
.radio:not(:only-child)::before { inline-size: var(--smrt-radio-box); margin-inline-start: calc(var(--smrt-radio-box) / -2); }
|
|
37
39
|
.radio.disabled { opacity: .5; cursor: not-allowed; }
|
|
38
40
|
input { position: absolute; opacity: 0; width: 1px; height: 1px; }
|
|
39
41
|
.radio__mark { position: relative; z-index: 1; width: 1.15rem; height: 1.15rem; border: 2px solid var(--smrt-color-outline); border-radius: 50%; display: grid; place-items: center; }
|
|
@@ -41,9 +43,10 @@ function handleChange(event: Event & { currentTarget: HTMLInputElement }) {
|
|
|
41
43
|
.radio__mark::after { content: ''; width: .55rem; height: .55rem; border-radius: 50%; background: var(--smrt-color-primary); transform: scale(0); transition: transform var(--smrt-duration-short2); }
|
|
42
44
|
input:checked + .radio__mark { border-color: var(--smrt-color-primary); }
|
|
43
45
|
input:checked + .radio__mark::after { transform: scale(1); }
|
|
44
|
-
input:focus-visible + .radio__mark { outline:
|
|
46
|
+
input:focus-visible + .radio__mark { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
|
|
45
47
|
.radio { min-height: var(--smrt-control-target-min, 0px); min-width: var(--smrt-control-target-min, 0px); }
|
|
46
48
|
|
|
47
49
|
/* Table cells: grow vertically only, never into a neighbouring cell. */
|
|
48
|
-
:global(:is(td, th)) .radio::before { inline-size: var(--
|
|
50
|
+
:global(:is(td, th)) .radio::before { inline-size: var(--smrt-radio-box); margin-inline-start: calc(var(--smrt-radio-box) / -2); }
|
|
51
|
+
}
|
|
49
52
|
</style>
|
|
@@ -139,13 +139,15 @@ useControlRegistration(() => {
|
|
|
139
139
|
<fieldset bind:this={fieldsetEl} data-density={density} class="radio-group {className}" {disabled}
|
|
140
140
|
aria-describedby={description ? `${name}-description` : undefined} data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
|
|
141
141
|
data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
|
|
142
|
-
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}>
|
|
142
|
+
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id} data-smrt-component="RadioGroup">
|
|
143
143
|
{#if label}<legend>{label}{#if required}<span aria-hidden="true"> *</span>{/if}</legend>{/if}
|
|
144
144
|
{#if description}<p id={`${name}-description`} class="description">{description}</p>{/if}
|
|
145
145
|
<div class="options">{@render children()}</div>
|
|
146
146
|
{#if error}<p class="error" role="alert">{error}</p>{/if}
|
|
147
147
|
</fieldset>
|
|
148
148
|
<style>
|
|
149
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
150
|
+
@layer smrt.theme {
|
|
149
151
|
.radio-group { margin: 0; padding: 0; border: 0; color: var(--smrt-color-on-surface); }
|
|
150
152
|
legend { margin-bottom: var(--smrt-spacing-2); font: var(--smrt-typography-label-large-font); }
|
|
151
153
|
.description, .error { margin: var(--smrt-spacing-1) 0 var(--smrt-spacing-2); font: var(--smrt-typography-body-small-font); color: var(--smrt-color-on-surface-variant); }
|
|
@@ -153,6 +155,7 @@ useControlRegistration(() => {
|
|
|
153
155
|
.options { display: flex; flex-wrap: wrap; gap: var(--smrt-spacing-3); }
|
|
154
156
|
:global(.radio-group[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; border-radius: var(--smrt-radius-small); }
|
|
155
157
|
|
|
156
|
-
.radio-group[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min
|
|
158
|
+
.radio-group[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
|
|
157
159
|
.radio-group[data-density='comfortable'] { --smrt-control-target-min: 0px; }
|
|
160
|
+
}
|
|
158
161
|
</style>
|
|
@@ -175,7 +175,7 @@ useControlRegistration(() => {
|
|
|
175
175
|
</script>
|
|
176
176
|
<div bind:this={rootEl} class="range-slider {className}" class:disabled data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
|
|
177
177
|
data-smrt-subject-type={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.type}
|
|
178
|
-
data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id} role="group" aria-label={label ?? formGroup?.().label ?? 'Range'}>
|
|
178
|
+
data-smrt-subject-id={resolvedInteraction === false ? undefined : resolvedInteraction.subject?.id} role="group" aria-label={label ?? formGroup?.().label ?? 'Range'} data-smrt-component="RangeSlider">
|
|
179
179
|
{#if label}<div class="range-slider__header"><span>{label}</span><output>{value.min}{unit ?? ''} – {value.max}{unit ?? ''}</output></div>{/if}
|
|
180
180
|
<div class="range-slider__track">
|
|
181
181
|
<input bind:this={minEl} id={minId} type="range" name={name ? `${name}[min]` : undefined} {min} max={value.max} {step} {disabled} value={value.min}
|
|
@@ -189,6 +189,8 @@ useControlRegistration(() => {
|
|
|
189
189
|
</div>
|
|
190
190
|
</div>
|
|
191
191
|
<style>
|
|
192
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
193
|
+
@layer smrt.theme {
|
|
192
194
|
.range-slider { display: grid; gap: var(--smrt-spacing-3); color: var(--smrt-color-on-surface); }
|
|
193
195
|
.range-slider.disabled { opacity: .5; }
|
|
194
196
|
.range-slider__header { display: flex; justify-content: space-between; font: var(--smrt-typography-label-large-font); }
|
|
@@ -200,6 +202,7 @@ useControlRegistration(() => {
|
|
|
200
202
|
.range-slider__inputs { display: flex; gap: var(--smrt-spacing-3); }
|
|
201
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); }
|
|
202
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); }
|
|
203
|
-
input:focus-visible { outline:
|
|
205
|
+
input:focus-visible { outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color); outline-offset: var(--smrt-focus-ring-offset); }
|
|
204
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
|
+
}
|
|
205
208
|
</style>
|
|
@@ -288,7 +288,7 @@ $effect(() => {
|
|
|
288
288
|
$effect(() => () => clearTimeout(timer));
|
|
289
289
|
</script>
|
|
290
290
|
|
|
291
|
-
<div class="relation-input" bind:this={rootEl}>
|
|
291
|
+
<div class="relation-input" bind:this={rootEl} data-smrt-component="RelationInput">
|
|
292
292
|
<div class="field">
|
|
293
293
|
<Combobox
|
|
294
294
|
{name}
|
|
@@ -343,9 +343,11 @@ $effect(() => () => clearTimeout(timer));
|
|
|
343
343
|
</div>
|
|
344
344
|
|
|
345
345
|
<style>
|
|
346
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
347
|
+
@layer smrt.theme {
|
|
346
348
|
.relation-input {
|
|
347
349
|
display: grid;
|
|
348
|
-
gap: var(--smrt-spacing-1
|
|
350
|
+
gap: var(--smrt-spacing-1);
|
|
349
351
|
min-width: 0;
|
|
350
352
|
}
|
|
351
353
|
.field {
|
|
@@ -353,8 +355,8 @@ $effect(() => () => clearTimeout(timer));
|
|
|
353
355
|
}
|
|
354
356
|
.field :global(.clear) {
|
|
355
357
|
position: absolute;
|
|
356
|
-
right: var(--smrt-spacing-1
|
|
357
|
-
bottom: var(--smrt-spacing-1
|
|
358
|
+
right: var(--smrt-spacing-1);
|
|
359
|
+
bottom: var(--smrt-spacing-1);
|
|
358
360
|
}
|
|
359
361
|
.option-label,
|
|
360
362
|
.option-detail {
|
|
@@ -375,4 +377,5 @@ $effect(() => () => clearTimeout(timer));
|
|
|
375
377
|
.error {
|
|
376
378
|
color: var(--smrt-color-error);
|
|
377
379
|
}
|
|
380
|
+
}
|
|
378
381
|
</style>
|
|
@@ -112,7 +112,7 @@ function clear() {
|
|
|
112
112
|
onDestroy(cancel);
|
|
113
113
|
</script>
|
|
114
114
|
|
|
115
|
-
<div class="search-input {className}" role="search">
|
|
115
|
+
<div class="search-input {className}" role="search" data-smrt-component="SearchInput">
|
|
116
116
|
<label class="search-input__label" for={inputId}>{label}</label>
|
|
117
117
|
<span class="search-input__icon" aria-hidden="true">
|
|
118
118
|
<svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
|
|
@@ -137,6 +137,8 @@ onDestroy(cancel);
|
|
|
137
137
|
</div>
|
|
138
138
|
|
|
139
139
|
<style>
|
|
140
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
141
|
+
@layer smrt.theme {
|
|
140
142
|
.search-input {
|
|
141
143
|
position: relative;
|
|
142
144
|
display: flex;
|
|
@@ -185,7 +187,7 @@ onDestroy(cancel);
|
|
|
185
187
|
block-size: 2.75rem;
|
|
186
188
|
padding: 0;
|
|
187
189
|
border: none;
|
|
188
|
-
border-radius: var(--smrt-radius-full
|
|
190
|
+
border-radius: var(--smrt-radius-full);
|
|
189
191
|
background: transparent;
|
|
190
192
|
color: var(--smrt-color-on-surface-variant);
|
|
191
193
|
cursor: pointer;
|
|
@@ -194,8 +196,8 @@ onDestroy(cancel);
|
|
|
194
196
|
color: var(--smrt-color-on-surface);
|
|
195
197
|
}
|
|
196
198
|
.search-input__clear:focus-visible {
|
|
197
|
-
outline:
|
|
198
|
-
outline-offset: -
|
|
199
|
+
outline: var(--smrt-focus-ring-width) solid var(--smrt-focus-ring-color);
|
|
200
|
+
outline-offset: calc(var(--smrt-focus-ring-width) * -1);
|
|
199
201
|
}
|
|
200
202
|
/* Phones: full width. */
|
|
201
203
|
@media (max-width: 48rem) {
|
|
@@ -204,4 +206,5 @@ onDestroy(cancel);
|
|
|
204
206
|
max-inline-size: none;
|
|
205
207
|
}
|
|
206
208
|
}
|
|
209
|
+
}
|
|
207
210
|
</style>
|
|
@@ -236,7 +236,7 @@ useControlRegistration(() => {
|
|
|
236
236
|
</script>
|
|
237
237
|
<div bind:this={rootEl} data-density={density} class="segmented {className}" class:full-width={fullWidth} role="radiogroup" tabindex="-1" aria-label={label} aria-required={required} onkeydown={handleKeydown} data-smrt-control={controlId} data-smrt-form={interactionContext?.formId}
|
|
238
238
|
data-smrt-subject-type={interaction === false ? undefined : interaction?.subject?.type}
|
|
239
|
-
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id}>
|
|
239
|
+
data-smrt-subject-id={interaction === false ? undefined : interaction?.subject?.id} data-smrt-component="SegmentedControl">
|
|
240
240
|
{#each options as option, index (option.value)}
|
|
241
241
|
<label class:selected={selectedOption === option} class:disabled={disabled || option.disabled}>
|
|
242
242
|
<input type="radio" {name} value={option.value} disabled={disabled || option.disabled}
|
|
@@ -250,15 +250,18 @@ useControlRegistration(() => {
|
|
|
250
250
|
{/each}
|
|
251
251
|
</div>
|
|
252
252
|
<style>
|
|
253
|
+
@layer smrt.reset, smrt.structure, smrt.theme;
|
|
254
|
+
@layer smrt.theme {
|
|
253
255
|
.segmented { display: inline-flex; border: 1px solid var(--smrt-color-outline); border-radius: var(--smrt-radius-full); overflow: hidden; }
|
|
254
256
|
.segmented.full-width { display: flex; width: 100%; }
|
|
255
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; }
|
|
256
258
|
label:last-child { border-right: 0; } label.selected { background: var(--smrt-color-secondary-container); color: var(--smrt-color-on-secondary-container); }
|
|
257
|
-
label:has(input:focus-visible) { outline:
|
|
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; }
|
|
258
260
|
:global(.segmented[data-smrt-highlighted='true']) { outline: 3px solid var(--smrt-color-tertiary); outline-offset: 4px; }
|
|
259
261
|
|
|
260
|
-
.segmented[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min
|
|
262
|
+
.segmented[data-density='touch'] { --smrt-control-target-min: var(--smrt-touch-target-min); }
|
|
261
263
|
.segmented[data-density='comfortable'] { --smrt-control-target-min: 0px; }
|
|
262
264
|
label { min-height: max(2.5rem, var(--smrt-control-target-min, 0px)); min-width: var(--smrt-control-target-min, 0px); }
|
|
263
265
|
input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: inherit; }
|
|
266
|
+
}
|
|
264
267
|
</style>
|