@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.
Files changed (78) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/utilities/storybook/scraper.js +14 -3
  3. package/metadata/checksum.txt +1 -1
  4. package/metadata/packages/components/components/syn-alert/component.styles.ts +126 -26
  5. package/metadata/packages/components/components/syn-alert/component.ts +1 -2
  6. package/metadata/packages/components/components/syn-checkbox/component.angular.ts +13 -0
  7. package/metadata/packages/components/components/syn-checkbox/component.styles.ts +99 -39
  8. package/metadata/packages/components/components/syn-checkbox/component.ts +13 -10
  9. package/metadata/packages/components/components/syn-checkbox/component.vue +5 -0
  10. package/metadata/packages/components/components/syn-combobox/component.angular.ts +13 -0
  11. package/metadata/packages/components/components/syn-combobox/component.styles.ts +216 -193
  12. package/metadata/packages/components/components/syn-combobox/component.ts +68 -39
  13. package/metadata/packages/components/components/syn-combobox/component.vue +5 -0
  14. package/metadata/packages/components/components/syn-file/component.angular.ts +13 -0
  15. package/metadata/packages/components/components/syn-file/component.styles.ts +20 -3
  16. package/metadata/packages/components/components/syn-file/component.ts +19 -5
  17. package/metadata/packages/components/components/syn-file/component.vue +5 -0
  18. package/metadata/packages/components/components/syn-input/component.ts +1 -2
  19. package/metadata/packages/components/components/syn-popup/component.styles.ts +24 -17
  20. package/metadata/packages/components/components/syn-popup/component.ts +1 -2
  21. package/metadata/packages/components/components/syn-radio/component.angular.ts +13 -0
  22. package/metadata/packages/components/components/syn-radio/component.styles.ts +91 -29
  23. package/metadata/packages/components/components/syn-radio/component.ts +19 -10
  24. package/metadata/packages/components/components/syn-radio/component.vue +5 -0
  25. package/metadata/packages/components/components/syn-radio-group/component.styles.ts +30 -9
  26. package/metadata/packages/components/components/syn-radio-group/component.ts +61 -32
  27. package/metadata/packages/components/components/syn-range/component.angular.ts +13 -0
  28. package/metadata/packages/components/components/syn-range/component.styles.ts +27 -3
  29. package/metadata/packages/components/components/syn-range/component.ts +17 -5
  30. package/metadata/packages/components/components/syn-range/component.vue +5 -0
  31. package/metadata/packages/components/components/syn-select/component.angular.ts +13 -0
  32. package/metadata/packages/components/components/syn-select/component.styles.ts +222 -151
  33. package/metadata/packages/components/components/syn-select/component.ts +30 -15
  34. package/metadata/packages/components/components/syn-select/component.vue +5 -0
  35. package/metadata/packages/components/components/syn-switch/component.angular.ts +13 -0
  36. package/metadata/packages/components/components/syn-switch/component.styles.ts +145 -63
  37. package/metadata/packages/components/components/syn-switch/component.ts +16 -4
  38. package/metadata/packages/components/components/syn-switch/component.vue +5 -0
  39. package/metadata/packages/components/components/syn-textarea/component.styles.ts +55 -27
  40. package/metadata/packages/components/components/syn-textarea/component.ts +1 -3
  41. package/metadata/packages/components/components/syn-tooltip/component.styles.ts +15 -10
  42. package/metadata/packages/components/components/syn-tooltip/component.ts +13 -5
  43. package/metadata/packages/components/components/syn-validate/component.angular.ts +9 -0
  44. package/metadata/packages/components/components/syn-validate/component.react.ts +8 -0
  45. package/metadata/packages/components/components/syn-validate/component.ts +106 -8
  46. package/metadata/packages/components/components/syn-validate/component.vue +9 -0
  47. package/metadata/packages/components/static/CHANGELOG.md +43 -0
  48. package/metadata/packages/tokens/CHANGELOG.md +33 -0
  49. package/metadata/packages/tokens/dark.css +7 -1
  50. package/metadata/packages/tokens/index.js +31 -1
  51. package/metadata/packages/tokens/light.css +7 -1
  52. package/metadata/packages/tokens/sick2018_dark.css +7 -1
  53. package/metadata/packages/tokens/sick2018_light.css +7 -1
  54. package/metadata/packages/tokens/sick2025_dark.css +7 -1
  55. package/metadata/packages/tokens/sick2025_light.css +7 -1
  56. package/metadata/static/components/syn-checkbox/docs.md +36 -0
  57. package/metadata/static/components/syn-combobox/docs.md +138 -0
  58. package/metadata/static/components/syn-file/docs.md +24 -0
  59. package/metadata/static/components/syn-input/docs.md +1 -1
  60. package/metadata/static/components/syn-radio/docs.md +21 -0
  61. package/metadata/static/components/syn-radio-group/docs.md +46 -0
  62. package/metadata/static/components/syn-range/docs.md +19 -0
  63. package/metadata/static/components/syn-select/docs.md +81 -0
  64. package/metadata/static/components/syn-switch/docs.md +22 -0
  65. package/metadata/static/components/syn-textarea/docs.md +1 -1
  66. package/metadata/static/components/syn-tooltip/docs.md +73 -0
  67. package/metadata/static/components/syn-validate/docs.md +33 -6
  68. package/package.json +4 -4
  69. package/metadata/packages/components/components/syn-alert/component.custom.styles.ts +0 -136
  70. package/metadata/packages/components/components/syn-checkbox/component.custom.styles.ts +0 -86
  71. package/metadata/packages/components/components/syn-combobox/component.custom.styles.ts +0 -122
  72. package/metadata/packages/components/components/syn-popup/component.custom.styles.ts +0 -18
  73. package/metadata/packages/components/components/syn-radio/component.custom.styles.ts +0 -86
  74. package/metadata/packages/components/components/syn-radio-group/component.custom.styles.ts +0 -25
  75. package/metadata/packages/components/components/syn-select/component.custom.styles.ts +0 -175
  76. package/metadata/packages/components/components/syn-switch/component.custom.styles.ts +0 -141
  77. package/metadata/packages/components/components/syn-textarea/component.custom.styles.ts +0 -48
  78. package/metadata/packages/components/components/syn-tooltip/component.custom.styles.ts +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1192](https://github.com/synergy-design-system/synergy-design-system/pull/1192) [`31c54c0`](https://github.com/synergy-design-system/synergy-design-system/commit/31c54c04a651a14e20bc5f4b2aff1bd92ad26bc0) Thanks [@schilchSICKAG](https://github.com/schilchSICKAG)! - Released on: 2026-03-02
8
+
9
+ feat: ✨ New variant `tooltip` for `<syn-validate>` (#664)
10
+
11
+ `<syn-validate>` received the option to show validation errors using `<syn-tooltip>`.
12
+ To use this feature, set the `variant` property to `tooltip`.
13
+
14
+ ## 2.7.0
15
+
16
+ ### Minor Changes
17
+
18
+ - [#1189](https://github.com/synergy-design-system/synergy-design-system/pull/1189) [`a4f49ac`](https://github.com/synergy-design-system/synergy-design-system/commit/a4f49ac79a660ef5b8d1b380fe9fcd2159dc9b78) Thanks [@schilchSICKAG](https://github.com/schilchSICKAG)! - Released on: 2026-02-26
19
+
20
+ feat: ✨ Added readonly for various form fields (#1171, #1172, #1173, #1174, #1175, #1176, #1177, #1178)
21
+
22
+ Applies to:
23
+ - `<syn-checkbox>`
24
+ - `<syn-combobox>`
25
+ - `<syn-file>`
26
+ - `<syn-radio>`
27
+ - `<syn-radio-group>`
28
+ - `<syn-range>`
29
+ - `<syn-select>`
30
+ - `<syn-switch>`
31
+
32
+ Form elements now support being displayed as `readonly` fields.
33
+
34
+ Field marked `readonly` may receive focus, but their value cannot be changed by customer inputs.
35
+
3
36
  ## 2.6.1
4
37
 
5
38
  ### Patch Changes
@@ -65,11 +65,20 @@ export class StorybookScraper {
65
65
  // Extract the stories metadata first
66
66
  // We get basic info and identify stories that need iframe content
67
67
  const rawStoryMetadata = await page.evaluate(() => Array.from(document.querySelectorAll('.sb-anchor'))
68
+ // eslint-disable-next-line complexity
68
69
  .map((story, index) => {
69
70
  const description = story.querySelector(':scope > p')?.textContent || '';
70
- const exampleSource = story.querySelector('.sb-story #root-inner')?.innerHTML || '';
71
71
  const heading = story.querySelector('h3')?.textContent || '';
72
72
  const hasIframe = !!story.querySelector('.sb-story iframe');
73
+ let exampleSource = '';
74
+ if (!hasIframe) {
75
+ // #1152: The example source is usually in the #root-inner element.
76
+ // However, for at least one story (tag-group-template), the #root-inner container is missing.
77
+ // I am not sure why, but I think a fallback would be just to check the first element for the time being.
78
+ const exampleWithRoot = story.querySelector('.sb-story #root-inner')?.innerHTML || '';
79
+ const exampleWithoutRoot = story.querySelector('.sb-story > div')?.innerHTML || '';
80
+ exampleSource = exampleWithRoot || exampleWithoutRoot;
81
+ }
73
82
  return {
74
83
  description,
75
84
  exampleSource,
@@ -94,14 +103,16 @@ export class StorybookScraper {
94
103
  if (!exampleSource && storyMeta.hasIframe) {
95
104
  try {
96
105
  const storySection = page.locator('.sb-anchor').nth(storyMeta.index);
106
+ // Storybook uses lazy loading, so the iframe may not be loaded until we scroll it into view
107
+ await storySection.scrollIntoViewIfNeeded();
108
+ await page.waitForTimeout(1000);
97
109
  const frame = storySection.frameLocator('iframe');
98
110
  const frameContent = await frame.locator('#root-inner').innerHTML();
99
111
  exampleSource = frameContent || '';
100
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
101
112
  }
102
113
  catch (error) {
103
114
  // If iframe content extraction fails, continue with empty content
104
- console.log(`Failed to extract iframe content for story "${storyMeta.heading}"`);
115
+ console.log(`Failed to extract iframe content for story "${storyMeta.heading}"`, error);
105
116
  }
106
117
  }
107
118
  // Replace all lit internal comments
@@ -1 +1 @@
1
- c6fde0e7601ba4b7278a09634987804a
1
+ 8e6d1d17a574847bbf85bc978ec6d9c9
@@ -1,8 +1,7 @@
1
- /* eslint-disable */
2
1
  import { css } from 'lit';
3
2
 
4
3
  export default css`
5
- /* stylelint-disable */
4
+ /* stylelint-disable no-descending-specificity */
6
5
  :host {
7
6
  display: contents;
8
7
 
@@ -11,19 +10,54 @@ export default css`
11
10
  }
12
11
 
13
12
  .alert {
14
- position: relative;
15
- display: flex;
13
+ /* Defines the used border and icon color for variants */
14
+ --variant-color-border: var(--syn-alert-informative-color-border);
15
+ --variant-color-background: var(--syn-alert-informative-color-background);
16
+ --variant-color-icon: var(--syn-alert-informative-color-icon);
17
+ --variant-color-indicator: var(--syn-alert-informative-color-indicator);
18
+
19
+ /* Defines special settings for sizes */
20
+ --size-font-size: var(--syn-font-size-medium);
21
+ --size-icon-size: var(--syn-font-size-x-large);
22
+ --size-min-height: 54px;
23
+ --size-message-padding: var(--syn-spacing-medium) var(--syn-spacing-large) var(--syn-spacing-medium) var(--syn-spacing-medium);
24
+ --size-icon-padding-block: var(--syn-spacing-medium);
25
+ --size-icon-padding-inline: var(--syn-spacing-medium);
26
+
16
27
  align-items: stretch;
17
- background-color: var(--syn-panel-background-color);
18
- border: solid var(--syn-panel-border-width) var(--syn-panel-border-color);
19
- border-top-width: calc(var(--syn-panel-border-width) * 3);
20
- border-radius: var(--syn-border-radius-medium);
28
+ background-color: var(--variant-color-background);
29
+ border: var(--syn-panel-border-width) solid var(--variant-color-border);
30
+ border-left: 0;
31
+ border-radius: var(--syn-border-radius-none);
32
+ box-sizing: content-box;
33
+ color: var(--syn-typography-color-text);
34
+ display: flex;
21
35
  font-family: var(--syn-font-sans);
22
- font-size: var(--syn-font-size-small);
36
+ font-size: var(--size-font-size);
23
37
  font-weight: var(--syn-font-weight-normal);
24
- line-height: 1.6;
25
- color: var(--syn-color-neutral-700);
38
+ line-height: var(--syn-line-height-normal);
26
39
  margin: inherit;
40
+ min-height: var(--size-min-height);
41
+ position: relative;
42
+ }
43
+
44
+ /**
45
+ * Add back the items left borders
46
+ * This is done to prevent border clipping with the large border-left needed on .alert
47
+ * Note we also need to adjust our paddings to add the border width here
48
+ */
49
+ .alert::before {
50
+ background: var(--variant-color-indicator);
51
+ bottom: -1px;
52
+ content: "";
53
+ left: 0;
54
+ position: absolute;
55
+ top: -1px;
56
+ width: var(--syn-spacing-2x-small);
57
+ }
58
+
59
+ .alert :first-child {
60
+ margin-inline-start: var(--syn-spacing-2x-small);
27
61
  }
28
62
 
29
63
  .alert:not(.alert--has-icon) .alert__icon,
@@ -31,12 +65,17 @@ export default css`
31
65
  display: none;
32
66
  }
33
67
 
68
+ /**
69
+ * Make sure everything is aligned to top
70
+ */
34
71
  .alert__icon {
35
- flex: 0 0 auto;
72
+ align-items: flex-start;
73
+ color: var(--variant-color-icon);
36
74
  display: flex;
37
- align-items: center;
38
- font-size: var(--syn-font-size-large);
39
- padding-inline-start: var(--syn-spacing-large);
75
+ flex: 0 0 auto;
76
+ font-size: var(--size-icon-size);
77
+ padding-block-start: var(--size-icon-padding-block);
78
+ padding-inline-start: var(--size-icon-padding-inline);
40
79
  }
41
80
 
42
81
  .alert--has-countdown {
@@ -44,28 +83,34 @@ export default css`
44
83
  }
45
84
 
46
85
  .alert__message {
47
- flex: 1 1 auto;
86
+ align-self: center;
48
87
  display: block;
49
- padding: var(--syn-spacing-large);
88
+ flex: 1 1 auto;
89
+ padding: var(--size-message-padding);
50
90
  }
51
91
 
92
+ /**
93
+ * Close Icon
94
+ */
52
95
  .alert__close-button {
53
- flex: 0 0 auto;
96
+ align-items: flex-start;
97
+ align-self: start; /* #1135: Fix alignment for the close icon */
98
+ color: var(--syn-typography-color-text);
54
99
  display: flex;
55
- align-items: center;
56
- font-size: var(--syn-font-size-medium);
57
- margin-inline-end: var(--syn-spacing-medium);
58
- align-self: center;
100
+ flex: 0 0 auto;
101
+ font-size: var(--size-icon-size);
102
+ margin-block: calc(var(--syn-spacing-x-small) - var(--syn-panel-border-width));
103
+ margin-inline-end: var(--syn-spacing-x-small);
59
104
  }
60
105
 
61
106
  .alert__countdown {
62
- position: absolute;
107
+ background-color: var(--syn-panel-border-color);
63
108
  bottom: 0;
109
+ display: flex;
110
+ height: calc(var(--syn-panel-border-width) * 3);
64
111
  left: 0;
112
+ position: absolute;
65
113
  width: 100%;
66
- height: calc(var(--syn-panel-border-width) * 3);
67
- background-color: var(--syn-panel-border-color);
68
- display: flex;
69
114
  }
70
115
 
71
116
  .alert__countdown--ltr {
@@ -97,6 +142,61 @@ export default css`
97
142
  background-color: var(--syn-color-danger-600);
98
143
  }
99
144
 
145
+ /**
146
+ * Variant colors
147
+ */
148
+ .alert--success {
149
+ --variant-color-border: var(--syn-alert-success-color-border);
150
+ --variant-color-background: var(--syn-alert-success-color-background);
151
+ --variant-color-icon: var(--syn-alert-success-color-icon);
152
+ --variant-color-indicator: var(--syn-alert-success-color-indicator);
153
+ }
154
+
155
+ .alert--neutral {
156
+ --variant-color-border: var(--syn-alert-neutral-color-border);
157
+ --variant-color-background: var(--syn-alert-neutral-color-background);
158
+ --variant-color-icon: var(--syn-alert-neutral-color-icon);
159
+ --variant-color-indicator: var(--syn-alert-neutral-color-indicator);
160
+ }
161
+
162
+ .alert--warning {
163
+ --variant-color-border: var(--syn-alert-warning-color-border);
164
+ --variant-color-background: var(--syn-alert-warning-color-background);
165
+ --variant-color-icon: var(--syn-alert-warning-color-icon);
166
+ --variant-color-indicator: var(--syn-alert-warning-color-indicator);
167
+ }
168
+
169
+ .alert--danger {
170
+ --variant-color-border: var(--syn-alert-error-color-border);
171
+ --variant-color-background: var(--syn-alert-error-color-background);
172
+ --variant-color-icon: var(--syn-alert-error-color-icon);
173
+ --variant-color-indicator: var(--syn-alert-error-color-indicator);
174
+ }
175
+
176
+ /* #1119: Alert Sizes */
177
+ .alert--small {
178
+ --size-font-size: var(--syn-font-size-small);
179
+ --size-icon-size: var(--syn-font-size-large);
180
+ --size-min-height: 44px;
181
+ --size-message-padding: var(--syn-spacing-small) var(--syn-spacing-large) var(--syn-spacing-small) var(--syn-spacing-small);
182
+ --size-icon-padding-block: var(--syn-spacing-small);
183
+ --size-icon-padding-inline: var(--syn-spacing-small);
184
+ }
185
+
186
+ /* Adjust close button size for small alerts */
187
+ .alert--small .alert__close-button {
188
+ font-size: var(--syn-font-size-medium);
189
+ }
190
+
191
+ .alert--large {
192
+ --size-font-size: var(--syn-font-size-large);
193
+ --size-icon-size: var(--syn-font-size-2x-large);
194
+ --size-min-height: 68px;
195
+ --size-message-padding: var(--syn-spacing-medium-large) var(--syn-spacing-large) var(--syn-spacing-medium-large) var(--syn-spacing-medium-large);
196
+ --size-icon-padding-block: var(--syn-spacing-medium-large);
197
+ --size-icon-padding-inline: var(--syn-spacing-medium-large);
198
+ }
199
+
100
200
  .alert__timer {
101
201
  display: none;
102
202
  }
@@ -13,7 +13,6 @@ import componentStyles from '../../styles/component.styles.js';
13
13
  import SynergyElement from '../../internal/synergy-element.js';
14
14
  import SynIconButton from '../icon-button/icon-button.component.js';
15
15
  import styles from './alert.styles.js';
16
- import customStyles from './alert.custom.styles.js';
17
16
  import type { CSSResultGroup } from 'lit';
18
17
  import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
19
18
 
@@ -44,7 +43,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
44
43
  */
45
44
  @enableDefaultSettings('SynAlert')
46
45
  export default class SynAlert extends SynergyElement {
47
- static styles: CSSResultGroup = [componentStyles, styles, customStyles];
46
+ static styles: CSSResultGroup = [componentStyles, styles];
48
47
  static dependencies = { 'syn-icon-button': SynIconButton };
49
48
 
50
49
  private autoHideTimeout: number;
@@ -154,6 +154,19 @@ export class SynCheckboxComponent {
154
154
  return this.nativeElement.disabled;
155
155
  }
156
156
 
157
+ /**
158
+ * Sets the checkbox to a readonly state.
159
+ */
160
+ @Input()
161
+ set readonly(v: '' | SynCheckbox['readonly']) {
162
+ this._ngZone.runOutsideAngular(
163
+ () => (this.nativeElement.readonly = v === '' || v),
164
+ );
165
+ }
166
+ get readonly(): SynCheckbox['readonly'] {
167
+ return this.nativeElement.readonly;
168
+ }
169
+
157
170
  /**
158
171
  * Draws the checkbox in a checked state.
159
172
  */
@@ -2,79 +2,88 @@
2
2
  import { css } from 'lit';
3
3
 
4
4
  export default css`
5
- /* stylelint-disable */
5
+ /* stylelint-disable no-descending-specificity */
6
6
  :host {
7
7
  display: inline-block;
8
8
  }
9
9
 
10
10
  .checkbox {
11
- position: relative;
12
- display: inline-flex;
13
11
  align-items: flex-start;
12
+ color: var(--syn-input-label-color);
13
+ cursor: pointer;
14
+ display: inline-flex;
14
15
  font-family: var(--syn-input-font-family);
15
16
  font-weight: var(--syn-input-font-weight);
16
- color: var(--syn-input-label-color);
17
+ padding: var(--syn-spacing-2x-small) 0; /* #1083: This adds spacing around multi-line labels */
18
+ position: relative;
17
19
  vertical-align: middle;
18
- cursor: pointer;
19
20
  }
20
21
 
21
22
  .checkbox--small {
22
23
  --toggle-size: var(--syn-toggle-size-small);
24
+
23
25
  font-size: var(--syn-input-font-size-small);
26
+ padding: var(--syn-spacing-3x-small) 0;
24
27
  }
25
28
 
26
29
  .checkbox--medium {
27
30
  --toggle-size: var(--syn-toggle-size-medium);
31
+
28
32
  font-size: var(--syn-input-font-size-medium);
29
33
  }
30
34
 
31
35
  .checkbox--large {
32
36
  --toggle-size: var(--syn-toggle-size-large);
37
+
33
38
  font-size: var(--syn-input-font-size-large);
34
39
  }
35
40
 
36
41
  .checkbox__control {
37
- flex: 0 0 auto;
38
- position: relative;
39
- display: inline-flex;
40
42
  align-items: center;
41
- justify-content: center;
42
- width: var(--toggle-size);
43
- height: var(--toggle-size);
44
- border: solid var(--syn-input-border-width) var(--syn-input-border-color);
45
- border-radius: 2px;
46
43
  background-color: var(--syn-input-background-color);
44
+ border: solid var(--syn-input-border-width) var(--syn-input-border-color);
45
+ border-radius: var(--syn-checkbox-border-radius);
47
46
  color: var(--syn-color-neutral-0);
47
+ display: inline-flex;
48
+ flex: 0 0 auto;
49
+ height: var(--toggle-size);
50
+ justify-content: center;
51
+ margin: 0.1em 0; /* #1083: This adds spacing around multi-line labels */
52
+ position: relative;
48
53
  transition:
49
54
  var(--syn-transition-fast) border-color,
50
55
  var(--syn-transition-fast) background-color,
51
56
  var(--syn-transition-fast) color,
52
57
  var(--syn-transition-fast) box-shadow;
58
+ width: var(--toggle-size);
53
59
  }
54
60
 
55
61
  .checkbox__input {
56
- position: absolute;
62
+ margin: 0;
57
63
  opacity: 0;
58
64
  padding: 0;
59
- margin: 0;
60
65
  pointer-events: none;
66
+ position: absolute;
61
67
  }
62
68
 
63
69
  .checkbox__checked-icon,
64
70
  .checkbox__indeterminate-icon {
65
71
  display: inline-flex;
66
- width: var(--toggle-size);
67
72
  height: var(--toggle-size);
73
+ width: var(--toggle-size);
68
74
  }
69
75
 
70
- /* Hover */
71
- .checkbox:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__control:hover {
72
- border-color: var(--syn-input-border-color-hover);
76
+ /**
77
+ * Hover
78
+ * Applies the hover state to the whole component
79
+ */
80
+ .checkbox:not(.checkbox--checked):not(.checkbox--disabled):not(.checkbox--readonly):hover .checkbox__control {
73
81
  background-color: var(--syn-input-background-color-hover);
82
+ border-color: var(--syn-input-border-color-hover);
74
83
  }
75
84
 
76
85
  /* Focus */
77
- .checkbox:not(.checkbox--checked):not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control {
86
+ .checkbox:not(.checkbox--disabled):not(.checkbox--readonly) .checkbox__input:focus-visible ~ .checkbox__control {
78
87
  outline: var(--syn-focus-ring);
79
88
  outline-offset: var(--syn-focus-ring-offset);
80
89
  }
@@ -82,42 +91,93 @@ export default css`
82
91
  /* Checked/indeterminate */
83
92
  .checkbox--checked .checkbox__control,
84
93
  .checkbox--indeterminate .checkbox__control {
85
- border-color: var(--syn-color-primary-600);
86
- background-color: var(--syn-color-primary-600);
94
+ background-color: var(--syn-interactive-emphasis-color);
95
+ border-color: var(--syn-interactive-emphasis-color);
87
96
  }
88
97
 
89
- /* Checked/indeterminate + hover */
90
- .checkbox.checkbox--checked:not(.checkbox--disabled) .checkbox__control:hover,
91
- .checkbox.checkbox--indeterminate:not(.checkbox--disabled) .checkbox__control:hover {
92
- border-color: var(--syn-color-primary-500);
93
- background-color: var(--syn-color-primary-500);
98
+ /**
99
+ * Checked/indeterminate + hover
100
+ * Applies the hover state to the whole component
101
+ */
102
+ .checkbox.checkbox--checked:not(.checkbox--disabled):not(.checkbox--readonly):hover .checkbox__control,
103
+ .checkbox.checkbox--indeterminate:not(.checkbox--disabled):not(.checkbox--readonly):hover .checkbox__control {
104
+ background-color: var(--syn-interactive-emphasis-color-hover);
105
+ border-color: var(--syn-interactive-emphasis-color-hover);
94
106
  }
95
107
 
96
- /* Checked/indeterminate + focus */
97
- .checkbox.checkbox--checked:not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control,
98
- .checkbox.checkbox--indeterminate:not(.checkbox--disabled) .checkbox__input:focus-visible ~ .checkbox__control {
99
- outline: var(--syn-focus-ring);
100
- outline-offset: var(--syn-focus-ring-offset);
108
+ /*
109
+ * #443: Add active styles
110
+ * The checked and unchecked states have different active colors
111
+ * Note the fallback is defined to match the hover color.
112
+ * This is done to make sure no active state is shown at all if no active color is defined.
113
+ * Still better than showing one for the unchecked state but not for the checked state.
114
+ */
115
+ .checkbox:not(.checkbox--checked):not(.checkbox--disabled):not(.checkbox--readonly):active .checkbox__control {
116
+ border-color: var(--syn-input-border-color-active);
101
117
  }
102
118
 
103
- /* Disabled */
119
+ /* Checked/indeterminate */
120
+ .checkbox.checkbox--checked:not(.checkbox--disabled):not(.checkbox--readonly):active .checkbox__control,
121
+ .checkbox.checkbox--indeterminate:not(.checkbox--disabled):not(.checkbox--readonly):active .checkbox__control {
122
+ background: var(--syn-interactive-emphasis-color-active);
123
+ border-color: var(--syn-interactive-emphasis-color-active);
124
+ }
125
+
126
+ /** #429: Use token for opacity */
104
127
  .checkbox--disabled {
105
- opacity: 0.5;
106
128
  cursor: not-allowed;
129
+ opacity: var(--syn-input-disabled-opacity);
107
130
  }
108
131
 
109
132
  .checkbox__label {
110
- display: inline-block;
133
+ align-self: center;
111
134
  color: var(--syn-input-label-color);
112
- line-height: var(--toggle-size);
113
- margin-inline-start: 0.5em;
135
+ display: inline-block;
136
+ line-height: var(--syn-line-height-normal);
137
+ margin-inline-start: var(--syn-spacing-x-small);
114
138
  user-select: none;
115
- -webkit-user-select: none;
116
139
  }
117
140
 
118
141
  :host([required]) .checkbox__label::after {
119
- content: var(--syn-input-required-content);
120
142
  color: var(--syn-input-required-content-color);
143
+ content: var(--syn-input-required-content);
121
144
  margin-inline-start: var(--syn-input-required-content-offset);
122
145
  }
146
+
147
+ :host([data-user-invalid]) .checkbox__control {
148
+ background: var(--syn-input-border-color-focus-error);
149
+ border-color: var(--syn-input-border-color-focus-error);
150
+ }
151
+
152
+ /**
153
+ * #943: When invalid, use a transparent background if not checked or indeterminate
154
+ */
155
+ :host([data-user-invalid]:not([checked]):not([indeterminate])) .checkbox__control {
156
+ background: transparent;
157
+ }
158
+
159
+ /**
160
+ * #1171: Readonly state
161
+ */
162
+ .checkbox.checkbox--readonly {
163
+ cursor: default;
164
+ }
165
+
166
+ .checkbox.checkbox--readonly .checkbox__label {
167
+ /* stylelint-disable-next-line property-no-vendor-prefix */
168
+ -webkit-user-select: auto;
169
+ user-select: auto;
170
+ }
171
+
172
+ .checkbox.checkbox--readonly .checkbox__control {
173
+ background: var(--syn-input-readonly-background-color);
174
+ border-color: var(--syn-input-readonly-background-color);
175
+ color: var(--syn-readonly-indicator-color);
176
+ cursor: default;
177
+ }
178
+
179
+ .checkbox.checkbox--readonly .checkbox__input:focus ~ .checkbox__control {
180
+ outline: var(--syn-focus-ring);
181
+ outline-offset: var(--syn-focus-ring-offset);
182
+ }
123
183
  `;
@@ -6,15 +6,13 @@ import { HasSlotController } from '../../internal/slot.js';
6
6
  import { html } from 'lit';
7
7
  import { ifDefined } from 'lit/directives/if-defined.js';
8
8
  import { live } from 'lit/directives/live.js';
9
- import { property, query, state } from 'lit/decorators.js';
9
+ import { property, query } 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 SynIcon from '../icon/icon.component.js';
16
15
  import styles from './checkbox.styles.js';
17
- import customStyles from './checkbox.custom.styles.js';
18
16
  import type { CSSResultGroup } from 'lit';
19
17
  import type { SynergyFormControl } from '../../internal/synergy-element.js';
20
18
  import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator.js';
@@ -47,7 +45,7 @@ import { enableDefaultSettings } from '../../utilities/defaultSettings/decorator
47
45
  */
48
46
  @enableDefaultSettings('SynCheckbox')
49
47
  export default class SynCheckbox extends SynergyElement implements SynergyFormControl {
50
- static styles: CSSResultGroup = [componentStyles, formControlStyles, styles, formControlCustomStyles, customStyles];
48
+ static styles: CSSResultGroup = [componentStyles, formControlStyles, styles];
51
49
  static dependencies = { 'syn-icon': SynIcon };
52
50
 
53
51
  private readonly formControlController = new FormControlController(this, {
@@ -59,8 +57,6 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
59
57
 
60
58
  @query('input[type="checkbox"]') input: HTMLInputElement;
61
59
 
62
- @state() private hasFocus = false;
63
-
64
60
  @property({ reflect: true }) title = ''; // make reactive to pass through
65
61
 
66
62
  /** The name of the checkbox, submitted as a name/value pair with form data. */
@@ -75,6 +71,9 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
75
71
  /** Disables the checkbox. */
76
72
  @property({ type: Boolean, reflect: true }) disabled = false;
77
73
 
74
+ /** Sets the checkbox to a readonly state. */
75
+ @property({ type: Boolean, reflect: true }) readonly = false;
76
+
78
77
  /** Draws the checkbox in a checked state. */
79
78
  @property({ type: Boolean, reflect: true }) checked = false;
80
79
 
@@ -114,14 +113,18 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
114
113
  this.formControlController.updateValidity();
115
114
  }
116
115
 
117
- private handleClick() {
116
+ private handleClick(e: MouseEvent) {
117
+ if (this.readonly) {
118
+ e.preventDefault();
119
+ return;
120
+ }
121
+
118
122
  this.checked = !this.checked;
119
123
  this.indeterminate = false;
120
124
  this.emit('syn-change');
121
125
  }
122
126
 
123
127
  private handleBlur() {
124
- this.hasFocus = false;
125
128
  this.emit('syn-blur');
126
129
  }
127
130
 
@@ -135,7 +138,6 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
135
138
  }
136
139
 
137
140
  private handleFocus() {
138
- this.hasFocus = true;
139
141
  this.emit('syn-focus');
140
142
  }
141
143
 
@@ -216,7 +218,7 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
216
218
  checkbox: true,
217
219
  'checkbox--checked': this.checked,
218
220
  'checkbox--disabled': this.disabled,
219
- 'checkbox--focused': this.hasFocus,
221
+ 'checkbox--readonly': this.readonly,
220
222
  'checkbox--indeterminate': this.indeterminate,
221
223
  'checkbox--small': this.size === 'small',
222
224
  'checkbox--medium': this.size === 'medium',
@@ -232,6 +234,7 @@ export default class SynCheckbox extends SynergyElement implements SynergyFormCo
232
234
  .indeterminate=${live(this.indeterminate)}
233
235
  .checked=${live(this.checked)}
234
236
  .disabled=${this.disabled}
237
+ .readOnly=${this.readonly}
235
238
  .required=${this.required}
236
239
  aria-checked=${this.checked ? 'true' : 'false'}
237
240
  aria-describedby="help-text"
@@ -72,6 +72,11 @@ const props = defineProps<{
72
72
  */
73
73
  disabled?: SynCheckbox['disabled'];
74
74
 
75
+ /**
76
+ * Sets the checkbox to a readonly state.
77
+ */
78
+ readonly?: SynCheckbox['readonly'];
79
+
75
80
  /**
76
81
  * Draws the checkbox in a checked state.
77
82
  */
@@ -212,6 +212,19 @@ export class SynComboboxComponent {
212
212
  return this.nativeElement.disabled;
213
213
  }
214
214
 
215
+ /**
216
+ * Sets the combobox to a readonly state.
217
+ */
218
+ @Input()
219
+ set readonly(v: '' | SynCombobox['readonly']) {
220
+ this._ngZone.runOutsideAngular(
221
+ () => (this.nativeElement.readonly = v === '' || v),
222
+ );
223
+ }
224
+ get readonly(): SynCombobox['readonly'] {
225
+ return this.nativeElement.readonly;
226
+ }
227
+
215
228
  /**
216
229
  * Adds a clear button when the combobox is not empty.
217
230
  */