@synergy-design-system/mcp 2.6.1 → 2.7.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/utilities/storybook/scraper.js +14 -3
  3. package/metadata/checksum.txt +1 -1
  4. package/metadata/packages/components/components/syn-checkbox/component.angular.ts +13 -0
  5. package/metadata/packages/components/components/syn-checkbox/component.styles.ts +99 -39
  6. package/metadata/packages/components/components/syn-checkbox/component.ts +13 -10
  7. package/metadata/packages/components/components/syn-checkbox/component.vue +5 -0
  8. package/metadata/packages/components/components/syn-combobox/component.angular.ts +13 -0
  9. package/metadata/packages/components/components/syn-combobox/component.styles.ts +216 -193
  10. package/metadata/packages/components/components/syn-combobox/component.ts +68 -39
  11. package/metadata/packages/components/components/syn-combobox/component.vue +5 -0
  12. package/metadata/packages/components/components/syn-file/component.angular.ts +13 -0
  13. package/metadata/packages/components/components/syn-file/component.styles.ts +20 -3
  14. package/metadata/packages/components/components/syn-file/component.ts +19 -5
  15. package/metadata/packages/components/components/syn-file/component.vue +5 -0
  16. package/metadata/packages/components/components/syn-input/component.ts +1 -2
  17. package/metadata/packages/components/components/syn-radio/component.angular.ts +13 -0
  18. package/metadata/packages/components/components/syn-radio/component.styles.ts +91 -29
  19. package/metadata/packages/components/components/syn-radio/component.ts +19 -10
  20. package/metadata/packages/components/components/syn-radio/component.vue +5 -0
  21. package/metadata/packages/components/components/syn-radio-group/component.styles.ts +30 -9
  22. package/metadata/packages/components/components/syn-radio-group/component.ts +61 -32
  23. package/metadata/packages/components/components/syn-range/component.angular.ts +13 -0
  24. package/metadata/packages/components/components/syn-range/component.styles.ts +27 -3
  25. package/metadata/packages/components/components/syn-range/component.ts +17 -5
  26. package/metadata/packages/components/components/syn-range/component.vue +5 -0
  27. package/metadata/packages/components/components/syn-select/component.angular.ts +13 -0
  28. package/metadata/packages/components/components/syn-select/component.styles.ts +222 -151
  29. package/metadata/packages/components/components/syn-select/component.ts +30 -15
  30. package/metadata/packages/components/components/syn-select/component.vue +5 -0
  31. package/metadata/packages/components/components/syn-switch/component.angular.ts +13 -0
  32. package/metadata/packages/components/components/syn-switch/component.styles.ts +145 -63
  33. package/metadata/packages/components/components/syn-switch/component.ts +16 -4
  34. package/metadata/packages/components/components/syn-switch/component.vue +5 -0
  35. package/metadata/packages/components/components/syn-textarea/component.styles.ts +55 -27
  36. package/metadata/packages/components/components/syn-textarea/component.ts +1 -3
  37. package/metadata/packages/components/static/CHANGELOG.md +27 -0
  38. package/metadata/packages/tokens/CHANGELOG.md +22 -0
  39. package/metadata/packages/tokens/dark.css +7 -1
  40. package/metadata/packages/tokens/index.js +31 -1
  41. package/metadata/packages/tokens/light.css +7 -1
  42. package/metadata/packages/tokens/sick2018_dark.css +7 -1
  43. package/metadata/packages/tokens/sick2018_light.css +7 -1
  44. package/metadata/packages/tokens/sick2025_dark.css +7 -1
  45. package/metadata/packages/tokens/sick2025_light.css +7 -1
  46. package/metadata/static/components/syn-checkbox/docs.md +36 -0
  47. package/metadata/static/components/syn-combobox/docs.md +138 -0
  48. package/metadata/static/components/syn-file/docs.md +24 -0
  49. package/metadata/static/components/syn-input/docs.md +1 -1
  50. package/metadata/static/components/syn-radio/docs.md +21 -0
  51. package/metadata/static/components/syn-radio-group/docs.md +46 -0
  52. package/metadata/static/components/syn-range/docs.md +19 -0
  53. package/metadata/static/components/syn-select/docs.md +81 -0
  54. package/metadata/static/components/syn-switch/docs.md +22 -0
  55. package/metadata/static/components/syn-textarea/docs.md +1 -1
  56. package/metadata/static/components/syn-tooltip/docs.md +73 -0
  57. package/package.json +4 -4
  58. package/metadata/packages/components/components/syn-checkbox/component.custom.styles.ts +0 -86
  59. package/metadata/packages/components/components/syn-combobox/component.custom.styles.ts +0 -122
  60. package/metadata/packages/components/components/syn-radio/component.custom.styles.ts +0 -86
  61. package/metadata/packages/components/components/syn-radio-group/component.custom.styles.ts +0 -25
  62. package/metadata/packages/components/components/syn-select/component.custom.styles.ts +0 -175
  63. package/metadata/packages/components/components/syn-switch/component.custom.styles.ts +0 -141
  64. package/metadata/packages/components/components/syn-textarea/component.custom.styles.ts +0 -48
@@ -1,19 +1,34 @@
1
- /* eslint-disable */
2
1
  import { css } from 'lit';
2
+ import sharedOptionSize from '../option/option-size.styles.js';
3
3
 
4
4
  export default css`
5
- /* stylelint-disable */
5
+ /* stylelint-disable property-no-vendor-prefix */
6
+ /* stylelint-disable no-descending-specificity */
6
7
  :host {
8
+ /* Size-dependent CSS custom properties - defaults to medium */
9
+ --syn-select-input-border-radius: var(--syn-input-border-radius-medium);
10
+ --syn-select-input-font-size: var(--syn-input-font-size-medium);
11
+ --syn-select-input-height: var(--syn-input-height-medium);
12
+ --syn-select-input-spacing: var(--syn-input-spacing-medium);
13
+ --syn-select-clear-font-size: var(--syn-spacing-large);
14
+ --syn-select-clear-margin: var(--syn-spacing-small);
15
+ --syn-select-prefix-suffix-margin: var(--syn-input-spacing-small);
16
+ --syn-select-icon-font-size: var(--syn-font-size-x-large);
17
+ --syn-select-expand-icon-font-size: var(--syn-spacing-large);
18
+ --syn-select-tags-gap: var(--syn-spacing-x-small);
19
+ --syn-select-multiple-padding-block: 3px;
20
+ --syn-select-multiple-prefix-margin: var(--syn-input-spacing-medium);
21
+
7
22
  display: block;
8
23
  }
9
24
 
10
25
  /** The popup */
11
26
  .select {
12
- flex: 1 1 auto;
13
27
  display: inline-flex;
14
- width: 100%;
28
+ flex: 1 1 auto;
15
29
  position: relative;
16
30
  vertical-align: middle;
31
+ width: 100%;
17
32
  }
18
33
 
19
34
  .select::part(popup) {
@@ -30,38 +45,44 @@ export default css`
30
45
 
31
46
  /* Combobox */
32
47
  .select__combobox {
33
- flex: 1;
34
- display: flex;
35
- width: 100%;
36
- min-width: 0;
37
- position: relative;
38
48
  align-items: center;
39
- justify-content: start;
49
+ border-radius: var(--syn-select-input-border-radius);
50
+ cursor: pointer;
51
+ display: flex;
52
+ flex: 1;
40
53
  font-family: var(--syn-input-font-family);
54
+ font-size: var(--syn-select-input-font-size);
41
55
  font-weight: var(--syn-input-font-weight);
56
+ justify-content: start;
42
57
  letter-spacing: var(--syn-input-letter-spacing);
43
- vertical-align: middle;
58
+ min-height: var(--syn-select-input-height);
59
+ min-width: 0;
44
60
  overflow: hidden;
45
- cursor: pointer;
61
+ padding-block: 0;
62
+ padding-inline: var(--syn-select-input-spacing);
63
+ position: relative;
46
64
  transition:
47
65
  var(--syn-transition-fast) color,
48
66
  var(--syn-transition-fast) border,
49
67
  var(--syn-transition-fast) box-shadow,
50
68
  var(--syn-transition-fast) background-color;
69
+ vertical-align: middle;
70
+ width: 100%;
51
71
  }
52
72
 
53
73
  .select__display-input {
54
- position: relative;
55
- width: 100%;
56
- font: inherit;
57
- border: none;
74
+ -webkit-appearance: none;
75
+ appearance: none;
58
76
  background: none;
77
+ border: none;
59
78
  color: var(--syn-input-color);
60
79
  cursor: inherit;
80
+ font: inherit;
81
+ margin: 0;
61
82
  overflow: hidden;
62
83
  padding: 0;
63
- margin: 0;
64
- -webkit-appearance: none;
84
+ position: relative;
85
+ width: 100%;
65
86
  }
66
87
 
67
88
  .select__display-input::placeholder {
@@ -77,34 +98,48 @@ export default css`
77
98
  }
78
99
 
79
100
  /* Visually hide the display input when multiple is enabled */
80
- .select--multiple:not(.select--placeholder-visible) .select__display-input {
101
+ .select--multiple:not(.select--placeholder-visible) .select__combobox {
102
+ padding-inline-start: 0;
103
+ }
104
+
105
+ .select--multiple.select--readonly:not(.select--placeholder-visible) .select__combobox {
106
+ padding-inline-start: var(--syn-select-prefix-suffix-margin);
107
+ }
108
+
109
+ .select--multiple:not(.select--readonly):not(.select--placeholder-visible) .select__display-input {
110
+ height: 100%;
111
+ left: 0;
112
+ opacity: 0;
81
113
  position: absolute;
82
- z-index: -1;
83
114
  top: 0;
84
- left: 0;
85
115
  width: 100%;
86
- height: 100%;
87
- opacity: 0;
116
+ z-index: -1;
117
+ }
118
+
119
+ /* #1177: Make sure that the values are copyable when using the readonly state */
120
+ .select--multiple.select--readonly:not(.select--placeholder-visible) .select__display-input {
121
+ flex: auto;
88
122
  }
89
123
 
90
124
  .select__value-input {
91
- position: absolute;
92
- top: 0;
93
- left: 0;
94
- width: 100%;
95
125
  height: 100%;
96
- padding: 0;
126
+ left: 0;
97
127
  margin: 0;
98
128
  opacity: 0;
129
+ padding: 0;
130
+ position: absolute;
131
+ top: 0;
132
+ width: 100%;
99
133
  z-index: -1;
100
134
  }
101
135
 
102
136
  .select__tags {
137
+ align-items: center;
103
138
  display: flex;
104
139
  flex: 1;
105
- align-items: center;
106
140
  flex-wrap: wrap;
107
- margin-inline-start: var(--syn-spacing-2x-small);
141
+ gap: var(--syn-select-tags-gap);
142
+ margin-inline-start: var(--syn-spacing-medium);
108
143
  }
109
144
 
110
145
  .select__tags::slotted(syn-tag) {
@@ -126,129 +161,100 @@ export default css`
126
161
  background-color: var(--syn-input-background-color-disabled);
127
162
  border-color: var(--syn-input-border-color-disabled);
128
163
  color: var(--syn-input-color-disabled);
129
- opacity: 0.5;
130
164
  cursor: not-allowed;
165
+ opacity: var(--syn-input-disabled-opacity); /* #429: Use token for opacity */
131
166
  outline: none;
132
167
  }
133
168
 
134
- .select--standard:not(.select--disabled).select--open .select__combobox,
135
- .select--standard:not(.select--disabled).select--focused .select__combobox {
136
- background-color: var(--syn-input-background-color-focus);
137
- border-color: var(--syn-input-border-color-focus);
138
- box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-color);
139
- }
140
-
141
- /* Sizes */
142
- .select--small .select__combobox {
143
- border-radius: var(--syn-input-border-radius-small);
144
- font-size: var(--syn-input-font-size-small);
145
- min-height: var(--syn-input-height-small);
146
- padding-block: 0;
147
- padding-inline: var(--syn-input-spacing-small);
148
- }
149
-
150
- .select--small .select__clear {
151
- margin-inline-start: var(--syn-input-spacing-small);
152
- }
153
-
154
- .select--small .select__prefix::slotted(*) {
155
- margin-inline-end: var(--syn-input-spacing-small);
156
- }
157
-
158
- .select--small.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) {
159
- margin-inline-start: var(--syn-input-spacing-small);
160
- }
161
-
162
- .select--small.select--multiple:not(.select--placeholder-visible) .select__combobox {
163
- padding-block: 2px;
164
- padding-inline-start: 0;
165
- }
166
-
167
- .select--small .select__tags {
168
- gap: 2px;
169
- }
170
-
171
- .select--medium .select__combobox {
172
- border-radius: var(--syn-input-border-radius-medium);
173
- font-size: var(--syn-input-font-size-medium);
174
- min-height: var(--syn-input-height-medium);
175
- padding-block: 0;
176
- padding-inline: var(--syn-input-spacing-medium);
177
- }
178
-
179
- .select--medium .select__clear {
180
- margin-inline-start: var(--syn-input-spacing-medium);
181
- }
182
-
183
- .select--medium .select__prefix::slotted(*) {
184
- margin-inline-end: var(--syn-input-spacing-medium);
185
- }
186
-
187
- .select--medium.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) {
188
- margin-inline-start: var(--syn-input-spacing-medium);
189
- }
190
-
191
- .select--medium.select--multiple:not(.select--placeholder-visible) .select__combobox {
192
- padding-inline-start: 0;
193
- padding-block: 3px;
194
- }
195
-
196
- .select--medium .select__tags {
197
- gap: 3px;
198
- }
199
-
200
- .select--large .select__combobox {
201
- border-radius: var(--syn-input-border-radius-large);
202
- font-size: var(--syn-input-font-size-large);
203
- min-height: var(--syn-input-height-large);
204
- padding-block: 0;
205
- padding-inline: var(--syn-input-spacing-large);
206
- }
207
-
208
- .select--large .select__clear {
209
- margin-inline-start: var(--syn-input-spacing-large);
210
- }
211
-
212
- .select--large .select__prefix::slotted(*) {
213
- margin-inline-end: var(--syn-input-spacing-large);
214
- }
215
-
216
- .select--large.select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) {
217
- margin-inline-start: var(--syn-input-spacing-large);
218
- }
219
-
220
- .select--large.select--multiple:not(.select--placeholder-visible) .select__combobox {
221
- padding-inline-start: 0;
222
- padding-block: 4px;
223
- }
224
-
225
- .select--large .select__tags {
226
- gap: 4px;
227
- }/* Prefix and Suffix */
169
+ /**
170
+ * Invalid user data
171
+ */
172
+ :host([data-user-invalid]) .select__combobox {
173
+ border-color: var(--syn-input-border-color-focus-error);
174
+ }
175
+
176
+ :host([data-user-invalid]) .select--standard:not(.select--disabled).select--open .select__combobox,
177
+ :host([data-user-invalid]) .select--standard:not(.select--disabled).select--focused .select__combobox {
178
+ border-color: var(--syn-input-border-color-focus-error);
179
+ box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-error);
180
+ }
181
+
182
+ /* Change select border on hover */
183
+ .select:not(.select--disabled):not(.select--readonly):hover .select__combobox {
184
+ border-color: var(--syn-input-border-color-hover);
185
+ }
186
+
187
+ /* Size variants */
188
+ .select--small {
189
+ --syn-select-input-border-radius: var(--syn-input-border-radius-small);
190
+ --syn-select-input-font-size: var(--syn-input-font-size-small);
191
+ --syn-select-input-height: var(--syn-input-height-small);
192
+ --syn-select-input-spacing: var(--syn-input-spacing-small);
193
+ --syn-select-clear-font-size: var(--syn-spacing-medium);
194
+ --syn-select-clear-margin: var(--syn-input-spacing-small);
195
+ --syn-select-prefix-suffix-margin: var(--syn-spacing-x-small);
196
+ --syn-select-icon-font-size: var(--syn-font-size-medium);
197
+ --syn-select-expand-icon-font-size: var(--syn-spacing-medium);
198
+ --syn-select-tags-gap: var(--syn-spacing-2x-small);
199
+ --syn-select-multiple-padding-block: 2px;
200
+ --syn-select-multiple-prefix-margin: var(--syn-input-spacing-small);
201
+ }
202
+
203
+ .select--large {
204
+ --syn-select-input-border-radius: var(--syn-input-border-radius-large);
205
+ --syn-select-input-font-size: var(--syn-input-font-size-large);
206
+ --syn-select-input-height: var(--syn-input-height-large);
207
+ --syn-select-input-spacing: var(--syn-input-spacing-large);
208
+ --syn-select-clear-font-size: var(--syn-spacing-x-large);
209
+ --syn-select-clear-margin: var(--syn-input-spacing-large);
210
+ --syn-select-prefix-suffix-margin: var(--syn-input-spacing-medium);
211
+ --syn-select-icon-font-size: var(--syn-font-size-2x-large);
212
+ --syn-select-expand-icon-font-size: var(--syn-spacing-x-large);
213
+ --syn-select-tags-gap: var(--syn-spacing-small);
214
+ --syn-select-multiple-padding-block: 4px;
215
+ --syn-select-multiple-prefix-margin: var(--syn-input-spacing-large);
216
+ }
217
+
218
+ /* Multiple select specific styles */
219
+ .select--multiple:not(.select--placeholder-visible) .select__prefix::slotted(*) {
220
+ margin-inline-start: var(--syn-select-multiple-prefix-margin);
221
+ }
222
+
223
+ /* Prefix and Suffix */
228
224
  .select__prefix,
229
225
  .select__suffix {
230
- flex: 0;
231
- display: inline-flex;
232
226
  align-items: center;
233
- color: var(--syn-input-placeholder-color);
227
+ color: var(--syn-input-icon-color);
228
+ display: inline-flex;
229
+ flex: 0;
230
+ }
231
+
232
+ .select__prefix::slotted(*) {
233
+ margin-inline-end: var(--syn-select-prefix-suffix-margin);
234
234
  }
235
235
 
236
236
  .select__suffix::slotted(*) {
237
- margin-inline-start: var(--syn-spacing-small);
237
+ margin-inline-start: var(--syn-select-prefix-suffix-margin);
238
+ }
239
+
240
+ .select__suffix::slotted(syn-icon),
241
+ .select__prefix::slotted(syn-icon) {
242
+ font-size: var(--syn-select-icon-font-size);
238
243
  }
239
244
 
240
245
  /* Clear button */
241
246
  .select__clear {
242
- display: inline-flex;
243
247
  align-items: center;
244
- justify-content: center;
245
- font-size: inherit;
246
- color: var(--syn-input-icon-color);
247
- border: none;
248
248
  background: none;
249
+ border: none;
250
+ color: var(--syn-input-icon-icon-clearable-color);
251
+ cursor: pointer;
252
+ display: inline-flex;
253
+ font-size: var(--syn-select-clear-font-size);
254
+ justify-content: center;
255
+ margin-inline-start: var(--syn-select-clear-margin);
249
256
  padding: 0;
250
257
  transition: var(--syn-transition-fast) color;
251
- cursor: pointer;
252
258
  }
253
259
 
254
260
  .select__clear:hover {
@@ -261,12 +267,14 @@ export default css`
261
267
 
262
268
  /* Expand icon */
263
269
  .select__expand-icon {
264
- flex: 0 0 auto;
265
- display: flex;
266
270
  align-items: center;
267
- transition: var(--syn-transition-medium) rotate ease;
268
- rotate: 0;
271
+ color: var(--syn-color-neutral-950);
272
+ display: flex;
273
+ flex: 0 0 auto;
274
+ font-size: var(--syn-select-expand-icon-font-size);
269
275
  margin-inline-start: var(--syn-spacing-small);
276
+ rotate: 0deg;
277
+ transition: var(--syn-transition-medium) rotate ease;
270
278
  }
271
279
 
272
280
  .select--open .select__expand-icon {
@@ -275,23 +283,21 @@ export default css`
275
283
 
276
284
  /* Listbox */
277
285
  .select__listbox {
286
+ background: var(--syn-panel-background-color);
287
+ border: solid var(--syn-panel-border-width) var(--syn-panel-border-color);
288
+ border-radius: var(--syn-input-border-radius-medium);
289
+ box-shadow: var(--syn-shadow-medium);
278
290
  display: block;
279
- position: relative;
280
291
  font-family: var(--syn-font-sans);
281
292
  font-size: var(--syn-font-size-medium);
282
293
  font-weight: var(--syn-font-weight-normal);
283
- box-shadow: var(--syn-shadow-large);
284
- background: var(--syn-panel-background-color);
285
- border: solid var(--syn-panel-border-width) var(--syn-panel-border-color);
286
- border-radius: var(--syn-border-radius-medium);
287
- padding-block: var(--syn-spacing-x-small);
288
- padding-inline: 0;
294
+ max-height: var(--auto-size-available-height); /* Make sure it adheres to the popup's auto size */
295
+ max-width: var(--auto-size-available-width);
289
296
  overflow: auto;
290
297
  overscroll-behavior: none;
291
-
292
- /* Make sure it adheres to the popup's auto size */
293
- max-width: var(--auto-size-available-width);
294
- max-height: var(--auto-size-available-height);
298
+ padding-block: var(--syn-spacing-x-small);
299
+ padding-inline: 0;
300
+ position: relative;
295
301
  }
296
302
 
297
303
  .select__listbox ::slotted(syn-divider) {
@@ -299,11 +305,76 @@ export default css`
299
305
  }
300
306
 
301
307
  .select__listbox ::slotted(small) {
308
+ color: var(--syn-color-neutral-500);
302
309
  display: block;
303
310
  font-size: var(--syn-font-size-small);
304
311
  font-weight: var(--syn-font-weight-semibold);
305
- color: var(--syn-color-neutral-500);
306
312
  padding-block: var(--syn-spacing-2x-small);
307
313
  padding-inline: var(--syn-spacing-x-large);
308
314
  }
315
+
316
+ .select--standard:not(.select--disabled).select--open .select__combobox,
317
+ .select--standard:not(.select--disabled).select--focused .select__combobox {
318
+ background-color: var(--syn-input-background-color-focus);
319
+ border-color: var(--syn-input-border-color-focus);
320
+ box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-color);
321
+ }
322
+
323
+ .select--standard.select--readonly.select--focused .select__combobox {
324
+ background: var(--syn-readonly-background-color);
325
+ border-color: var(--syn-input-border-color-focus);
326
+ box-shadow: 0 0 0 var(--syn-focus-ring-width) var(--syn-input-focus-ring-color);
327
+ }
328
+
329
+ /**
330
+ * Make sure to hide the syn-divider for the first syn-optgroup
331
+ * Note! ::slotted does currently not work with ::part, so we
332
+ * opted for using a css variable here.
333
+ */
334
+ .select__listbox ::slotted(syn-optgroup:first-of-type) {
335
+ --display-divider: none;
336
+ }
337
+
338
+ /**
339
+ * #850: Allow to measure the size of the combobox.
340
+ * This is needed so we can automatically size and truncate the tags in the <syn-select multiple> component.
341
+ * Scoped to multiple to not break the single select per accident.
342
+ * Scoped to when placeholder is not visible to not break the placeholder visualization
343
+ */
344
+ :host([multiple]) :not(.select--placeholder-visible) > .select__combobox > .select__tags {
345
+ min-width: 100px;
346
+ overflow: hidden;
347
+ }
348
+
349
+ :host([multiple]) .select__tags > div {
350
+ display: contents;
351
+ }
352
+
353
+ :host([multiple]) .select__tags > div > syn-tag {
354
+ --syn-tag-position-adjustment: var(--syn-spacing-3x-small);
355
+
356
+ max-width: var(--syn-select-tag-max-width);
357
+ }
358
+
359
+ :host([multiple]) .select__tags > div > syn-tag::part(content) {
360
+ display: initial;
361
+ overflow: hidden;
362
+ text-overflow: ellipsis;
363
+ white-space: nowrap;
364
+ }
365
+
366
+ /**
367
+ * #1177: Add support for readonly
368
+ */
369
+ .select--readonly .select__combobox {
370
+ background: var(--syn-readonly-background-color);
371
+ border-color: var(--syn-readonly-background-color);
372
+ cursor: default;
373
+ }
374
+
375
+ .select--readonly .select__expand-icon {
376
+ color: var(--syn-readonly-icon-color-expand);
377
+ }
378
+
379
+ ${sharedOptionSize}
309
380
  `;
@@ -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, formControlCustomStyles, customStyles];
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
- if (this.placeholder && this.value.length === 0) {
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
  */