@synergy-design-system/mcp 2.6.1 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/dist/utilities/storybook/scraper.js +14 -3
- package/metadata/checksum.txt +1 -1
- package/metadata/packages/components/components/syn-alert/component.styles.ts +126 -26
- package/metadata/packages/components/components/syn-alert/component.ts +1 -2
- package/metadata/packages/components/components/syn-checkbox/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-checkbox/component.styles.ts +99 -39
- package/metadata/packages/components/components/syn-checkbox/component.ts +13 -10
- package/metadata/packages/components/components/syn-checkbox/component.vue +5 -0
- package/metadata/packages/components/components/syn-combobox/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-combobox/component.styles.ts +216 -193
- package/metadata/packages/components/components/syn-combobox/component.ts +68 -39
- package/metadata/packages/components/components/syn-combobox/component.vue +5 -0
- package/metadata/packages/components/components/syn-file/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-file/component.styles.ts +20 -3
- package/metadata/packages/components/components/syn-file/component.ts +19 -5
- package/metadata/packages/components/components/syn-file/component.vue +5 -0
- package/metadata/packages/components/components/syn-input/component.ts +1 -2
- package/metadata/packages/components/components/syn-popup/component.styles.ts +24 -17
- package/metadata/packages/components/components/syn-popup/component.ts +1 -2
- package/metadata/packages/components/components/syn-radio/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-radio/component.styles.ts +91 -29
- package/metadata/packages/components/components/syn-radio/component.ts +19 -10
- package/metadata/packages/components/components/syn-radio/component.vue +5 -0
- package/metadata/packages/components/components/syn-radio-group/component.styles.ts +30 -9
- package/metadata/packages/components/components/syn-radio-group/component.ts +61 -32
- package/metadata/packages/components/components/syn-range/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-range/component.styles.ts +27 -3
- package/metadata/packages/components/components/syn-range/component.ts +17 -5
- package/metadata/packages/components/components/syn-range/component.vue +5 -0
- package/metadata/packages/components/components/syn-select/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-select/component.styles.ts +222 -151
- package/metadata/packages/components/components/syn-select/component.ts +30 -15
- package/metadata/packages/components/components/syn-select/component.vue +5 -0
- package/metadata/packages/components/components/syn-switch/component.angular.ts +13 -0
- package/metadata/packages/components/components/syn-switch/component.styles.ts +145 -63
- package/metadata/packages/components/components/syn-switch/component.ts +16 -4
- package/metadata/packages/components/components/syn-switch/component.vue +5 -0
- package/metadata/packages/components/components/syn-textarea/component.styles.ts +55 -27
- package/metadata/packages/components/components/syn-textarea/component.ts +1 -3
- package/metadata/packages/components/components/syn-tooltip/component.styles.ts +15 -10
- package/metadata/packages/components/components/syn-tooltip/component.ts +13 -5
- package/metadata/packages/components/components/syn-validate/component.angular.ts +9 -0
- package/metadata/packages/components/components/syn-validate/component.react.ts +8 -0
- package/metadata/packages/components/components/syn-validate/component.ts +106 -8
- package/metadata/packages/components/components/syn-validate/component.vue +9 -0
- package/metadata/packages/components/static/CHANGELOG.md +43 -0
- package/metadata/packages/tokens/CHANGELOG.md +33 -0
- package/metadata/packages/tokens/dark.css +7 -1
- package/metadata/packages/tokens/index.js +31 -1
- package/metadata/packages/tokens/light.css +7 -1
- package/metadata/packages/tokens/sick2018_dark.css +7 -1
- package/metadata/packages/tokens/sick2018_light.css +7 -1
- package/metadata/packages/tokens/sick2025_dark.css +7 -1
- package/metadata/packages/tokens/sick2025_light.css +7 -1
- package/metadata/static/components/syn-checkbox/docs.md +36 -0
- package/metadata/static/components/syn-combobox/docs.md +138 -0
- package/metadata/static/components/syn-file/docs.md +24 -0
- package/metadata/static/components/syn-input/docs.md +1 -1
- package/metadata/static/components/syn-radio/docs.md +21 -0
- package/metadata/static/components/syn-radio-group/docs.md +46 -0
- package/metadata/static/components/syn-range/docs.md +19 -0
- package/metadata/static/components/syn-select/docs.md +81 -0
- package/metadata/static/components/syn-switch/docs.md +22 -0
- package/metadata/static/components/syn-textarea/docs.md +1 -1
- package/metadata/static/components/syn-tooltip/docs.md +73 -0
- package/metadata/static/components/syn-validate/docs.md +33 -6
- package/package.json +4 -4
- package/metadata/packages/components/components/syn-alert/component.custom.styles.ts +0 -136
- package/metadata/packages/components/components/syn-checkbox/component.custom.styles.ts +0 -86
- package/metadata/packages/components/components/syn-combobox/component.custom.styles.ts +0 -122
- package/metadata/packages/components/components/syn-popup/component.custom.styles.ts +0 -18
- package/metadata/packages/components/components/syn-radio/component.custom.styles.ts +0 -86
- package/metadata/packages/components/components/syn-radio-group/component.custom.styles.ts +0 -25
- package/metadata/packages/components/components/syn-select/component.custom.styles.ts +0 -175
- package/metadata/packages/components/components/syn-switch/component.custom.styles.ts +0 -141
- package/metadata/packages/components/components/syn-textarea/component.custom.styles.ts +0 -48
- package/metadata/packages/components/components/syn-tooltip/component.custom.styles.ts +0 -13
|
@@ -13,13 +13,11 @@ import { waitForEvent } from '../../internal/event.js';
|
|
|
13
13
|
import { watch } from '../../internal/watch.js';
|
|
14
14
|
import componentStyles from '../../styles/component.styles.js';
|
|
15
15
|
import formControlStyles from '../../styles/form-control.styles.js';
|
|
16
|
-
import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
|
|
17
16
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
18
17
|
import SynIcon from '../icon/icon.component.js';
|
|
19
18
|
import SynPopup from '../popup/popup.component.js';
|
|
20
19
|
import SynTag from '../tag/tag.component.js';
|
|
21
20
|
import styles from './select.styles.js';
|
|
22
|
-
import customStyles from './select.custom.styles.js';
|
|
23
21
|
import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
|
|
24
22
|
import type { SynergyFormControl } from '../../internal/synergy-element.js';
|
|
25
23
|
import type { SynRemoveEvent } from '../../events/syn-remove.js';
|
|
@@ -77,7 +75,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
|
|
|
77
75
|
*/
|
|
78
76
|
@enableDefaultSettings('SynSelect')
|
|
79
77
|
export default class SynSelect extends SynergyElement implements SynergyFormControl {
|
|
80
|
-
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles
|
|
78
|
+
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles];
|
|
81
79
|
static dependencies = {
|
|
82
80
|
'syn-icon': SynIcon,
|
|
83
81
|
'syn-popup': SynPopup,
|
|
@@ -168,6 +166,9 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
168
166
|
/** Disables the select control. */
|
|
169
167
|
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
170
168
|
|
|
169
|
+
/** Sets the select to a readonly state. */
|
|
170
|
+
@property({ reflect: true, type: Boolean }) readonly = false;
|
|
171
|
+
|
|
171
172
|
/** Adds a clear button when the select is not empty. */
|
|
172
173
|
@property({ type: Boolean }) clearable = false;
|
|
173
174
|
|
|
@@ -458,6 +459,12 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
458
459
|
}
|
|
459
460
|
};
|
|
460
461
|
|
|
462
|
+
private handleFormControlClick() {
|
|
463
|
+
if (this.readonly) {
|
|
464
|
+
this.displayInput.focus();
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
461
468
|
private handleLabelClick() {
|
|
462
469
|
this.displayInput.focus();
|
|
463
470
|
}
|
|
@@ -467,7 +474,7 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
467
474
|
const isIconButton = path.some(el => el instanceof Element && el.tagName.toLowerCase() === 'syn-icon-button');
|
|
468
475
|
|
|
469
476
|
// Ignore disabled controls and clicks on tags (remove buttons)
|
|
470
|
-
if (this.disabled || isIconButton) {
|
|
477
|
+
if (this.disabled || this.readonly || isIconButton) {
|
|
471
478
|
return;
|
|
472
479
|
}
|
|
473
480
|
|
|
@@ -571,7 +578,7 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
571
578
|
|
|
572
579
|
this.valueHasChanged = true;
|
|
573
580
|
|
|
574
|
-
if (!this.disabled) {
|
|
581
|
+
if (!this.disabled && !this.readonly) {
|
|
575
582
|
this.toggleOptionSelection(option, false);
|
|
576
583
|
|
|
577
584
|
// Emit after updating
|
|
@@ -654,7 +661,12 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
654
661
|
if (this.multiple) {
|
|
655
662
|
this.value = this.selectedOptions.map(el => el.value);
|
|
656
663
|
|
|
657
|
-
|
|
664
|
+
// #1177: When using a readonly field with multiple set,
|
|
665
|
+
// set the display label to the list of selected options instead of the count, since the user can't open the listbox to see which options are selected.
|
|
666
|
+
// This makes it possible to copy the values from the readonly select.
|
|
667
|
+
if (this.readonly) {
|
|
668
|
+
this.displayLabel = this.selectedOptions.map(opt => opt.getTextLabel()).join(', ');
|
|
669
|
+
} else if (this.placeholder && this.value.length === 0) {
|
|
658
670
|
// When no items are selected, keep the value empty so the placeholder shows
|
|
659
671
|
this.displayLabel = '';
|
|
660
672
|
} else {
|
|
@@ -702,10 +714,10 @@ export default class SynSelect extends SynergyElement implements SynergyFormCont
|
|
|
702
714
|
});
|
|
703
715
|
}
|
|
704
716
|
|
|
705
|
-
@watch('disabled', { waitUntilFirstUpdate: true })
|
|
717
|
+
@watch(['disabled', 'readonly'], { waitUntilFirstUpdate: true })
|
|
706
718
|
handleDisabledChange() {
|
|
707
|
-
// Close the listbox when the control is disabled
|
|
708
|
-
if (this.disabled) {
|
|
719
|
+
// Close the listbox when the control is disabled or readonly
|
|
720
|
+
if (this.disabled || this.readonly) {
|
|
709
721
|
this.open = false;
|
|
710
722
|
this.handleOpenChange();
|
|
711
723
|
}
|
|
@@ -774,7 +786,7 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
774
786
|
|
|
775
787
|
@watch('open', { waitUntilFirstUpdate: true })
|
|
776
788
|
async handleOpenChange() {
|
|
777
|
-
if (this.open && !this.disabled) {
|
|
789
|
+
if (this.open && (!this.disabled && !this.readonly)) {
|
|
778
790
|
// Reset the current option
|
|
779
791
|
this.setCurrentOption(this.selectedOptions[0] || this.getFirstOption());
|
|
780
792
|
|
|
@@ -817,7 +829,7 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
817
829
|
|
|
818
830
|
/** Shows the listbox. */
|
|
819
831
|
async show() {
|
|
820
|
-
if (this.open || this.disabled) {
|
|
832
|
+
if (this.open || this.disabled || this.readonly) {
|
|
821
833
|
this.open = false;
|
|
822
834
|
return undefined;
|
|
823
835
|
}
|
|
@@ -828,7 +840,7 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
828
840
|
|
|
829
841
|
/** Hides the listbox. */
|
|
830
842
|
async hide() {
|
|
831
|
-
if (!this.open || this.disabled) {
|
|
843
|
+
if (!this.open || this.disabled || this.readonly) {
|
|
832
844
|
this.open = false;
|
|
833
845
|
return undefined;
|
|
834
846
|
}
|
|
@@ -874,7 +886,7 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
874
886
|
const hasHelpTextSlot = this.hasSlotController.test('help-text');
|
|
875
887
|
const hasLabel = this.label ? true : !!hasLabelSlot;
|
|
876
888
|
const hasHelpText = this.helpText ? true : !!hasHelpTextSlot;
|
|
877
|
-
const hasClearIcon = this.clearable && !this.disabled && hasValue;
|
|
889
|
+
const hasClearIcon = this.clearable && (!this.disabled && !this.readonly) && hasValue;
|
|
878
890
|
const isPlaceholderVisible = this.placeholder && this.value && !hasValue;
|
|
879
891
|
|
|
880
892
|
return html`
|
|
@@ -886,8 +898,9 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
886
898
|
'form-control--medium': this.size === 'medium',
|
|
887
899
|
'form-control--large': this.size === 'large',
|
|
888
900
|
'form-control--has-label': hasLabel,
|
|
889
|
-
'form-control--has-help-text': hasHelpText
|
|
901
|
+
'form-control--has-help-text': hasHelpText,
|
|
890
902
|
})}
|
|
903
|
+
@click=${this.handleFormControlClick}
|
|
891
904
|
>
|
|
892
905
|
<label
|
|
893
906
|
id="label"
|
|
@@ -906,6 +919,7 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
906
919
|
'select--standard': true,
|
|
907
920
|
'select--open': this.open,
|
|
908
921
|
'select--disabled': this.disabled,
|
|
922
|
+
'select--readonly': this.readonly,
|
|
909
923
|
'select--multiple': this.multiple,
|
|
910
924
|
'select--focused': this.hasFocus,
|
|
911
925
|
'select--placeholder-visible': isPlaceholderVisible,
|
|
@@ -955,12 +969,13 @@ protected override willUpdate(changedProperties: PropertyValues) {
|
|
|
955
969
|
@blur=${this.handleBlur}
|
|
956
970
|
/>
|
|
957
971
|
|
|
958
|
-
${this.multiple ? html`<div part="tags" class="select__tags">${this.tags}</div>` : ''}
|
|
972
|
+
${this.multiple && !this.readonly ? html`<div part="tags" class="select__tags">${this.tags}</div>` : ''}
|
|
959
973
|
|
|
960
974
|
<input
|
|
961
975
|
class="select__value-input"
|
|
962
976
|
type="text"
|
|
963
977
|
?disabled=${this.disabled}
|
|
978
|
+
?readonly=${this.readonly}
|
|
964
979
|
?required=${this.required}
|
|
965
980
|
.value=${Array.isArray(this.value) ? this.value.join(', ') : this.value?.toString()}
|
|
966
981
|
tabindex="-1"
|
|
@@ -116,6 +116,11 @@ indicate the number of additional items that are selected.
|
|
|
116
116
|
*/
|
|
117
117
|
disabled?: SynSelect['disabled'];
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Sets the select to a readonly state.
|
|
121
|
+
*/
|
|
122
|
+
readonly?: SynSelect['readonly'];
|
|
123
|
+
|
|
119
124
|
/**
|
|
120
125
|
* Adds a clear button when the select is not empty.
|
|
121
126
|
*/
|
|
@@ -153,6 +153,19 @@ export class SynSwitchComponent {
|
|
|
153
153
|
return this.nativeElement.disabled;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Sets the switch to a readonly state.
|
|
158
|
+
*/
|
|
159
|
+
@Input()
|
|
160
|
+
set readonly(v: '' | SynSwitch['readonly']) {
|
|
161
|
+
this._ngZone.runOutsideAngular(
|
|
162
|
+
() => (this.nativeElement.readonly = v === '' || v),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
get readonly(): SynSwitch['readonly'] {
|
|
166
|
+
return this.nativeElement.readonly;
|
|
167
|
+
}
|
|
168
|
+
|
|
156
169
|
/**
|
|
157
170
|
* Draws the switch in a checked state.
|
|
158
171
|
*/
|
|
@@ -2,165 +2,247 @@
|
|
|
2
2
|
import { css } from 'lit';
|
|
3
3
|
|
|
4
4
|
export default css`
|
|
5
|
-
|
|
5
|
+
/* stylelint-disable no-descending-specificity */
|
|
6
6
|
:host {
|
|
7
7
|
display: inline-block;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
:host([size='small']) {
|
|
11
|
-
--height: var(--syn-
|
|
12
|
-
--thumb-size:
|
|
13
|
-
--width:
|
|
11
|
+
--height: var(--syn-switch-height-small);
|
|
12
|
+
--thumb-size: var(--syn-toggle-size-small);
|
|
13
|
+
--width: var(--syn-switch-width-small);
|
|
14
14
|
|
|
15
15
|
font-size: var(--syn-input-font-size-small);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
:host([size='medium']) {
|
|
19
|
-
--height: var(--syn-
|
|
20
|
-
--thumb-size:
|
|
21
|
-
--width:
|
|
19
|
+
--height: var(--syn-switch-height-medium);
|
|
20
|
+
--thumb-size: var(--syn-toggle-size-medium);
|
|
21
|
+
--width: var(--syn-switch-width-medium);
|
|
22
22
|
|
|
23
23
|
font-size: var(--syn-input-font-size-medium);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
:host([size='large']) {
|
|
27
|
-
--height: var(--syn-
|
|
28
|
-
--thumb-size:
|
|
29
|
-
--width:
|
|
27
|
+
--height: var(--syn-switch-height-large);
|
|
28
|
+
--thumb-size: var(--syn-toggle-size-large);
|
|
29
|
+
--width: var(--syn-switch-width-large);
|
|
30
30
|
|
|
31
31
|
font-size: var(--syn-input-font-size-large);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
.switch {
|
|
35
|
-
position: relative;
|
|
36
|
-
display: inline-flex;
|
|
37
35
|
align-items: center;
|
|
36
|
+
color: var(--syn-input-label-color);
|
|
37
|
+
cursor: pointer;
|
|
38
|
+
display: inline-flex;
|
|
38
39
|
font-family: var(--syn-input-font-family);
|
|
39
40
|
font-size: inherit;
|
|
40
41
|
font-weight: var(--syn-input-font-weight);
|
|
41
|
-
|
|
42
|
+
position: relative;
|
|
42
43
|
vertical-align: middle;
|
|
43
|
-
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.switch.switch--small {
|
|
47
|
+
padding: var(--syn-spacing-2x-small) 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.switch.switch--medium {
|
|
51
|
+
padding: var(--syn-spacing-2x-small) 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.switch.switch--large {
|
|
55
|
+
padding: var(--syn-spacing-3x-small) 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Hint: can be removed, if the padding stylings for sizes from above are removed */
|
|
59
|
+
.form-control--has-help-text .switch {
|
|
60
|
+
padding-bottom: 0;
|
|
44
61
|
}
|
|
45
62
|
|
|
46
63
|
.switch__control {
|
|
47
|
-
flex: 0 0 auto;
|
|
48
|
-
position: relative;
|
|
49
|
-
display: inline-flex;
|
|
50
64
|
align-items: center;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
height: var(--height);
|
|
54
|
-
background-color: var(--syn-color-neutral-400);
|
|
55
|
-
border: solid var(--syn-input-border-width) var(--syn-color-neutral-400);
|
|
65
|
+
background-color: var(--syn-input-icon-icon-clearable-color);
|
|
66
|
+
border: solid var(--syn-border-width-medium) var(--syn-input-icon-icon-clearable-color);
|
|
56
67
|
border-radius: var(--height);
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
flex: 0 0 auto;
|
|
70
|
+
height: var(--height);
|
|
71
|
+
justify-content: center;
|
|
72
|
+
position: relative;
|
|
57
73
|
transition:
|
|
58
74
|
var(--syn-transition-fast) border-color,
|
|
59
75
|
var(--syn-transition-fast) background-color;
|
|
76
|
+
width: var(--width);
|
|
60
77
|
}
|
|
61
78
|
|
|
62
79
|
.switch__control .switch__thumb {
|
|
63
|
-
width: var(--thumb-size);
|
|
64
|
-
height: var(--thumb-size);
|
|
65
80
|
background-color: var(--syn-color-neutral-0);
|
|
81
|
+
border: none;
|
|
66
82
|
border-radius: 50%;
|
|
67
|
-
|
|
68
|
-
translate: calc((var(--width) - var(--height)) / -2);
|
|
83
|
+
height: var(--thumb-size);
|
|
69
84
|
transition:
|
|
70
85
|
var(--syn-transition-fast) translate ease,
|
|
71
86
|
var(--syn-transition-fast) background-color,
|
|
72
87
|
var(--syn-transition-fast) border-color,
|
|
73
88
|
var(--syn-transition-fast) box-shadow;
|
|
89
|
+
translate: calc((var(--width) - var(--height)) / -2);
|
|
90
|
+
width: var(--thumb-size);
|
|
74
91
|
}
|
|
75
92
|
|
|
76
93
|
.switch__input {
|
|
77
|
-
|
|
94
|
+
margin: 0;
|
|
78
95
|
opacity: 0;
|
|
79
96
|
padding: 0;
|
|
80
|
-
margin: 0;
|
|
81
97
|
pointer-events: none;
|
|
98
|
+
position: absolute;
|
|
82
99
|
}
|
|
83
100
|
|
|
84
101
|
/* Hover */
|
|
85
|
-
.switch:not(.switch--checked):not(.switch--disabled)
|
|
86
|
-
background-color: var(--syn-color-
|
|
87
|
-
border-color: var(--syn-color-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.switch:not(.switch--checked):not(.switch--disabled) .switch__control:hover .switch__thumb {
|
|
91
|
-
background-color: var(--syn-color-neutral-0);
|
|
92
|
-
border-color: var(--syn-color-neutral-400);
|
|
102
|
+
.switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly):hover .switch__control {
|
|
103
|
+
background-color: var(--syn-input-icon-icon-clearable-color-hover);
|
|
104
|
+
border-color: var(--syn-input-icon-icon-clearable-color-hover);
|
|
93
105
|
}
|
|
94
106
|
|
|
95
107
|
/* Focus */
|
|
96
|
-
.switch:not(.switch--checked):not(.switch--disabled) .switch__input:focus-visible ~ .switch__control {
|
|
97
|
-
background-color: var(--syn-
|
|
98
|
-
border-color: var(--syn-
|
|
108
|
+
.switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly) .switch__input:focus-visible ~ .switch__control {
|
|
109
|
+
background-color: var(--syn-input-icon-icon-clearable-color);
|
|
110
|
+
border-color: var(--syn-input-icon-icon-clearable-color);
|
|
111
|
+
outline: var(--syn-focus-ring);
|
|
112
|
+
outline-offset: var(--syn-focus-ring-offset);
|
|
99
113
|
}
|
|
100
114
|
|
|
101
|
-
.switch:not(.switch--checked):not(.switch--disabled) .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
115
|
+
.switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly) .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
102
116
|
background-color: var(--syn-color-neutral-0);
|
|
103
|
-
|
|
104
|
-
outline: var(--syn-focus-ring);
|
|
105
|
-
outline-offset: var(--syn-focus-ring-offset);
|
|
117
|
+
outline: none;
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
/* Checked */
|
|
109
121
|
.switch--checked .switch__control {
|
|
110
|
-
background-color: var(--syn-
|
|
111
|
-
border-color: var(--syn-
|
|
122
|
+
background-color: var(--syn-interactive-emphasis-color);
|
|
123
|
+
border-color: var(--syn-interactive-emphasis-color);
|
|
112
124
|
}
|
|
113
125
|
|
|
114
126
|
.switch--checked .switch__control .switch__thumb {
|
|
115
127
|
background-color: var(--syn-color-neutral-0);
|
|
116
|
-
border-color: var(--syn-color-primary-600);
|
|
117
128
|
translate: calc((var(--width) - var(--height)) / 2);
|
|
118
129
|
}
|
|
119
130
|
|
|
120
131
|
/* Checked + hover */
|
|
121
|
-
.switch.switch--checked:not(.switch--disabled)
|
|
122
|
-
background-color: var(--syn-color-
|
|
123
|
-
border-color: var(--syn-color-
|
|
132
|
+
.switch.switch--checked:not(.switch--disabled):not(.switch--readonly):hover .switch__control {
|
|
133
|
+
background-color: var(--syn-interactive-emphasis-color-hover);
|
|
134
|
+
border-color: var(--syn-interactive-emphasis-color-hover);
|
|
124
135
|
}
|
|
125
136
|
|
|
126
|
-
.switch.switch--checked:not(.switch--disabled)
|
|
137
|
+
.switch.switch--checked:not(.switch--disabled):not(.switch--readonly):hover .switch__control .switch__thumb {
|
|
127
138
|
background-color: var(--syn-color-neutral-0);
|
|
128
|
-
border-color: var(--syn-color-primary-600);
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
/* Checked + focus */
|
|
132
|
-
.switch.switch--checked:not(.switch--disabled) .switch__input:focus-visible ~ .switch__control {
|
|
133
|
-
background-color: var(--syn-
|
|
134
|
-
border-color: var(--syn-
|
|
142
|
+
.switch.switch--checked:not(.switch--disabled):not(.switch--readonly) .switch__input:focus-visible ~ .switch__control {
|
|
143
|
+
background-color: var(--syn-interactive-emphasis-color);
|
|
144
|
+
border-color: var(--syn-interactive-emphasis-color);
|
|
145
|
+
outline: var(--syn-focus-ring);
|
|
146
|
+
outline-offset: var(--syn-focus-ring-offset);
|
|
135
147
|
}
|
|
136
148
|
|
|
137
|
-
.switch.switch--checked:not(.switch--disabled) .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
149
|
+
.switch.switch--checked:not(.switch--disabled):not(.switch--readonly) .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
138
150
|
background-color: var(--syn-color-neutral-0);
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
151
|
+
outline: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* #443: Add active styles
|
|
156
|
+
* The checked and unchecked states have different active colors
|
|
157
|
+
* Note the fallback is defined to match the hover color.
|
|
158
|
+
* This is done to make sure no active state is shown at all if no active color is defined.
|
|
159
|
+
* Still better than showing one for the unchecked state but not for the checked state.
|
|
160
|
+
*/
|
|
161
|
+
.switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly):active .switch__control {
|
|
162
|
+
background: var(--syn-input-icon-icon-clearable-color-active);
|
|
163
|
+
border-color: var(--syn-input-icon-icon-clearable-color-active);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.switch.switch--checked:not(.switch--disabled):not(.switch--readonly):active .switch__control {
|
|
167
|
+
background: var(--syn-interactive-emphasis-color-active);
|
|
168
|
+
border-color: var(--syn-interactive-emphasis-color-active);
|
|
142
169
|
}
|
|
143
170
|
|
|
144
|
-
|
|
171
|
+
/** #429: Use token for opacity */
|
|
145
172
|
.switch--disabled {
|
|
146
|
-
opacity: 0.5;
|
|
147
173
|
cursor: not-allowed;
|
|
174
|
+
opacity: var(--syn-input-disabled-opacity);
|
|
148
175
|
}
|
|
149
176
|
|
|
150
177
|
.switch__label {
|
|
151
178
|
display: inline-block;
|
|
152
179
|
line-height: var(--height);
|
|
153
|
-
margin-inline-start:
|
|
180
|
+
margin-inline-start: var(--syn-spacing-x-small);
|
|
154
181
|
user-select: none;
|
|
155
|
-
-webkit-user-select: none;
|
|
156
182
|
}
|
|
157
183
|
|
|
158
184
|
:host([required]) .switch__label::after {
|
|
159
|
-
content: var(--syn-input-required-content);
|
|
160
185
|
color: var(--syn-input-required-content-color);
|
|
186
|
+
content: var(--syn-input-required-content);
|
|
161
187
|
margin-inline-start: var(--syn-input-required-content-offset);
|
|
162
188
|
}
|
|
163
189
|
|
|
190
|
+
:host([data-user-invalid]) .switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly) .switch__control {
|
|
191
|
+
background-color: var(--syn-input-border-color-focus-error);
|
|
192
|
+
border-color: var(--syn-input-border-color-focus-error);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
:host([data-user-invalid]) .switch:not(.switch--checked):not(.switch--disabled):not(.switch--readonly):hover .switch__control {
|
|
196
|
+
background-color: var(--syn-input-border-color-hover);
|
|
197
|
+
border-color: var(--syn-input-border-color-hover);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* #1178: Readonly state
|
|
202
|
+
*/
|
|
203
|
+
.switch.switch--readonly {
|
|
204
|
+
cursor: default;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.switch.switch--readonly .switch__label {
|
|
208
|
+
user-select: auto;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.switch.switch--readonly .switch__control {
|
|
212
|
+
background: var(--syn-readonly-background-color);
|
|
213
|
+
border-color: var(--syn-readonly-background-color);
|
|
214
|
+
cursor: default;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.switch.switch--readonly:hover .switch__control {
|
|
218
|
+
background: var(--syn-input-readonly-background-color-hover);
|
|
219
|
+
border-color: var(--syn-input-readonly-background-color-hover);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.switch.switch--readonly .switch__input:focus ~ .switch__control {
|
|
223
|
+
outline: var(--syn-focus-ring);
|
|
224
|
+
outline-offset: var(--syn-focus-ring-offset);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.switch.switch--readonly .switch__control .switch__thumb {
|
|
228
|
+
background: var(--syn-readonly-indicator-color);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Override base styles to remove outline from thumb for readonly switches */
|
|
232
|
+
.switch.switch--readonly .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
233
|
+
outline: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.switch.switch--readonly.switch--checked .switch__input:focus-visible ~ .switch__control .switch__thumb {
|
|
237
|
+
outline: none !important;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Focus override */
|
|
241
|
+
.switch.switch--readonly .switch__input:focus-visible ~ .switch__control {
|
|
242
|
+
background-color: var(--syn-readonly-background-color);
|
|
243
|
+
border-color: var(--syn-readonly-background-color);
|
|
244
|
+
}
|
|
245
|
+
|
|
164
246
|
@media (forced-colors: active) {
|
|
165
247
|
.switch.switch--checked:not(.switch--disabled) .switch__control:hover .switch__thumb,
|
|
166
248
|
.switch--checked .switch__control .switch__thumb {
|
|
@@ -10,10 +10,8 @@ import { property, query, state } from 'lit/decorators.js';
|
|
|
10
10
|
import { watch } from '../../internal/watch.js';
|
|
11
11
|
import componentStyles from '../../styles/component.styles.js';
|
|
12
12
|
import formControlStyles from '../../styles/form-control.styles.js';
|
|
13
|
-
import formControlCustomStyles from '../../styles/form-control.custom.styles.js';
|
|
14
13
|
import SynergyElement from '../../internal/synergy-element.js';
|
|
15
14
|
import styles from './switch.styles.js';
|
|
16
|
-
import customStyles from './switch.custom.styles.js';
|
|
17
15
|
import type { CSSResultGroup } from 'lit';
|
|
18
16
|
import type { SynergyFormControl } from '../../internal/synergy-element.js';
|
|
19
17
|
import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
|
|
@@ -45,7 +43,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
|
|
|
45
43
|
*/
|
|
46
44
|
@enableDefaultSettings('SynSwitch')
|
|
47
45
|
export default class SynSwitch extends SynergyElement implements SynergyFormControl {
|
|
48
|
-
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles
|
|
46
|
+
static styles: CSSResultGroup = [componentStyles, formControlStyles, styles];
|
|
49
47
|
|
|
50
48
|
private readonly formControlController = new FormControlController(this, {
|
|
51
49
|
value: (control: SynSwitch) => (control.checked ? control.value || 'on' : undefined),
|
|
@@ -71,6 +69,9 @@ export default class SynSwitch extends SynergyElement implements SynergyFormCont
|
|
|
71
69
|
/** Disables the switch. */
|
|
72
70
|
@property({ type: Boolean, reflect: true }) disabled = false;
|
|
73
71
|
|
|
72
|
+
/** Sets the switch to a readonly state. */
|
|
73
|
+
@property({ type: Boolean, reflect: true }) readonly = false;
|
|
74
|
+
|
|
74
75
|
/** Draws the switch in a checked state. */
|
|
75
76
|
@property({ type: Boolean, reflect: true }) checked = false;
|
|
76
77
|
|
|
@@ -118,7 +119,12 @@ export default class SynSwitch extends SynergyElement implements SynergyFormCont
|
|
|
118
119
|
this.formControlController.emitInvalidEvent(event);
|
|
119
120
|
}
|
|
120
121
|
|
|
121
|
-
private handleClick() {
|
|
122
|
+
private handleClick(e: MouseEvent) {
|
|
123
|
+
if (this.readonly) {
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
122
128
|
this.checked = !this.checked;
|
|
123
129
|
this.emit('syn-change');
|
|
124
130
|
}
|
|
@@ -129,6 +135,10 @@ export default class SynSwitch extends SynergyElement implements SynergyFormCont
|
|
|
129
135
|
}
|
|
130
136
|
|
|
131
137
|
private handleKeyDown(event: KeyboardEvent) {
|
|
138
|
+
if (this.readonly) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
132
142
|
if (event.key === 'ArrowLeft') {
|
|
133
143
|
event.preventDefault();
|
|
134
144
|
this.checked = false;
|
|
@@ -212,6 +222,7 @@ export default class SynSwitch extends SynergyElement implements SynergyFormCont
|
|
|
212
222
|
switch: true,
|
|
213
223
|
'switch--checked': this.checked,
|
|
214
224
|
'switch--disabled': this.disabled,
|
|
225
|
+
'switch--readonly': this.readonly,
|
|
215
226
|
'switch--focused': this.hasFocus,
|
|
216
227
|
'switch--small': this.size === 'small',
|
|
217
228
|
'switch--medium': this.size === 'medium',
|
|
@@ -226,6 +237,7 @@ export default class SynSwitch extends SynergyElement implements SynergyFormCont
|
|
|
226
237
|
value=${ifDefined(this.value)}
|
|
227
238
|
.checked=${live(this.checked)}
|
|
228
239
|
.disabled=${this.disabled}
|
|
240
|
+
.readOnly=${this.readonly}
|
|
229
241
|
.required=${this.required}
|
|
230
242
|
role="switch"
|
|
231
243
|
aria-checked=${this.checked ? 'true' : 'false'}
|