@synergy-design-system/metadata 3.9.0 → 3.11.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 (54) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/data/core/setup/setup:angular-components-module.json +1 -1
  3. package/data/core/setup/setup:angular-forms-module.json +1 -1
  4. package/data/core/setup/setup:angular-package.json +2 -2
  5. package/data/core/setup/setup:angular-validators-module.json +1 -1
  6. package/data/core/setup/setup:components-package.json +2 -2
  7. package/data/core/setup/setup:react-package.json +2 -2
  8. package/data/core/setup/setup:tokens-package.json +2 -2
  9. package/data/core/setup/setup:vue-package.json +2 -2
  10. package/data/core/token/token:tokens-charts-js-index-d-ts.json +1 -1
  11. package/data/core/token/token:tokens-charts-js-index-js.json +1 -1
  12. package/data/core/token/token:tokens-charts-scss-tokens-scss.json +1 -1
  13. package/data/core/token/token:tokens-charts-themes-sick2025-dark-css.json +1 -1
  14. package/data/core/token/token:tokens-charts-themes-sick2025-light-css.json +1 -1
  15. package/data/core/token/token:tokens-figma-variables-sick2018-dark-json.json +1 -1
  16. package/data/core/token/token:tokens-figma-variables-sick2018-light-json.json +1 -1
  17. package/data/core/token/token:tokens-figma-variables-sick2025-dark-json.json +1 -1
  18. package/data/core/token/token:tokens-figma-variables-sick2025-light-json.json +1 -1
  19. package/data/core/token/token:tokens-js-index-d-ts.json +1 -1
  20. package/data/core/token/token:tokens-js-index-js.json +1 -1
  21. package/data/core/token/token:tokens-scss-tokens-scss.json +1 -1
  22. package/data/core/token/token:tokens-themes-sick2018-dark-css.json +1 -1
  23. package/data/core/token/token:tokens-themes-sick2018-light-css.json +1 -1
  24. package/data/core/token/token:tokens-themes-sick2025-dark-css.json +1 -1
  25. package/data/core/token/token:tokens-themes-sick2025-light-css.json +1 -1
  26. package/data/index.json +1 -1
  27. package/data/layers/full/component/component:syn-menu/components/menu.component.ts +62 -25
  28. package/data/layers/full/component/component:syn-menu/components/menu.styles.ts +0 -8
  29. package/data/layers/full/component/component:syn-menu-item/components/menu-item.component.ts +0 -7
  30. package/data/layers/full/component/component:syn-menu-item/components/submenu-controller.ts +94 -0
  31. package/data/layers/full/setup/setup:angular-package/angular/CHANGELOG.md +8 -0
  32. package/data/layers/full/setup/setup:angular-package/angular/package.json +1 -1
  33. package/data/layers/full/setup/setup:components-package/components/CHANGELOG.md +16 -0
  34. package/data/layers/full/setup/setup:components-package/components/package.json +1 -1
  35. package/data/layers/full/setup/setup:react-package/react/CHANGELOG.md +8 -0
  36. package/data/layers/full/setup/setup:react-package/react/package.json +1 -1
  37. package/data/layers/full/setup/setup:tokens-package/tokens/CHANGELOG.md +2 -0
  38. package/data/layers/full/setup/setup:tokens-package/tokens/package.json +1 -1
  39. package/data/layers/full/setup/setup:vue-package/vue/CHANGELOG.md +8 -0
  40. package/data/layers/full/setup/setup:vue-package/vue/package.json +1 -1
  41. package/data/layers/full/tokens/charts/js/index.d.ts +1 -1
  42. package/data/layers/full/tokens/charts/js/index.js +1 -1
  43. package/data/layers/full/tokens/charts/scss/_tokens.scss +1 -1
  44. package/data/layers/full/tokens/charts/themes/sick2025_dark.css +1 -1
  45. package/data/layers/full/tokens/charts/themes/sick2025_light.css +1 -1
  46. package/data/layers/full/tokens/js/index.d.ts +1 -1
  47. package/data/layers/full/tokens/js/index.js +1 -1
  48. package/data/layers/full/tokens/scss/_tokens.scss +1 -1
  49. package/data/layers/full/tokens/themes/sick2018_dark.css +1 -1
  50. package/data/layers/full/tokens/themes/sick2018_light.css +1 -1
  51. package/data/layers/full/tokens/themes/sick2025_dark.css +1 -1
  52. package/data/layers/full/tokens/themes/sick2025_light.css +1 -1
  53. package/data/manifest.json +1 -1
  54. package/package.json +5 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.11.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1296](https://github.com/synergy-design-system/synergy-design-system/pull/1296) [`4fdb69a`](https://github.com/synergy-design-system/synergy-design-system/commit/4fdb69aec5ddb0ddfa76a948c87eaf84be6fd670) Thanks [@schilchSICKAG](https://github.com/schilchSICKAG)! - Released on: 2026-06-03
8
+
9
+ fix: 🐛 `<syn-menu>` multiple issues ([#1295](https://github.com/synergy-design-system/synergy-design-system/issues/1295))
10
+
11
+ This release fixes multiple issues when using `<syn-menu>`:
12
+ - submenus no longer stay open when leaving the browser window ([#882](https://github.com/synergy-design-system/synergy-design-system/issues/882))
13
+ - `<syn-menu-item>` wrapped in tooltip can now be used reliably (including navigation and selection) ([#1162](https://github.com/synergy-design-system/synergy-design-system/issues/1162))
14
+ - `<syn-menu-item>` no longer steals focus on hover ([#1286](https://github.com/synergy-design-system/synergy-design-system/issues/1286))
15
+
16
+ ## 3.10.0
17
+
18
+ ### Minor Changes
19
+
20
+ - Released on: 2026-06-02
21
+
22
+ chore: ✨ Update Metadata and MCP with latest metadata
23
+
3
24
  ## 3.9.0
4
25
 
5
26
  ### Minor Changes
@@ -21,7 +21,7 @@
21
21
  "name": "Angular Components Module",
22
22
  "package": "angular",
23
23
  "relations": [],
24
- "since": "3.15.0",
24
+ "since": "3.15.1",
25
25
  "sources": [
26
26
  "packages/angular/modules/synergy/synergy.module.ts",
27
27
  "packages/angular/components/index.ts"
@@ -22,7 +22,7 @@
22
22
  "name": "Angular Forms Module",
23
23
  "package": "angular",
24
24
  "relations": [],
25
- "since": "3.15.0",
25
+ "since": "3.15.1",
26
26
  "sources": [
27
27
  "packages/angular/modules/forms/forms.module.ts"
28
28
  ],
@@ -2,7 +2,7 @@
2
2
  "custom": {
3
3
  "framework": "angular",
4
4
  "packageName": "@synergy-design-system/angular",
5
- "packageVersion": "3.15.0",
5
+ "packageVersion": "3.15.1",
6
6
  "subpathExports": [
7
7
  ".",
8
8
  "./components/*",
@@ -39,7 +39,7 @@
39
39
  "name": "Angular Framework Package",
40
40
  "package": "angular",
41
41
  "relations": [],
42
- "since": "3.15.0",
42
+ "since": "3.15.1",
43
43
  "sources": [
44
44
  "packages/angular/README.md",
45
45
  "packages/angular/CHANGELOG.md",
@@ -22,7 +22,7 @@
22
22
  "name": "Angular Validators Module",
23
23
  "package": "angular",
24
24
  "relations": [],
25
- "since": "3.15.0",
25
+ "since": "3.15.1",
26
26
  "sources": [
27
27
  "packages/angular/directives/validators/validators.ts"
28
28
  ],
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "custom": {
3
3
  "packageName": "@synergy-design-system/components",
4
- "packageVersion": "3.15.0"
4
+ "packageVersion": "3.15.1"
5
5
  },
6
6
  "id": "setup:components-package",
7
7
  "kind": "setup",
@@ -40,7 +40,7 @@
40
40
  "name": "Components Package",
41
41
  "package": "components",
42
42
  "relations": [],
43
- "since": "3.15.0",
43
+ "since": "3.15.1",
44
44
  "sources": [
45
45
  "packages/components/README.md",
46
46
  "packages/components/CHANGELOG.md",
@@ -2,7 +2,7 @@
2
2
  "custom": {
3
3
  "framework": "react",
4
4
  "packageName": "@synergy-design-system/react",
5
- "packageVersion": "3.15.0",
5
+ "packageVersion": "3.15.1",
6
6
  "subpathExports": [
7
7
  ".",
8
8
  "./components/*",
@@ -42,7 +42,7 @@
42
42
  "name": "React Framework Package",
43
43
  "package": "react",
44
44
  "relations": [],
45
- "since": "3.15.0",
45
+ "since": "3.15.1",
46
46
  "sources": [
47
47
  "packages/react/README.md",
48
48
  "packages/react/CHANGELOG.md",
@@ -32,7 +32,7 @@
32
32
  "./themes/*"
33
33
  ],
34
34
  "packageName": "@synergy-design-system/tokens",
35
- "packageVersion": "3.15.0"
35
+ "packageVersion": "3.15.1"
36
36
  },
37
37
  "id": "setup:tokens-package",
38
38
  "kind": "setup",
@@ -59,7 +59,7 @@
59
59
  "name": "Tokens Package",
60
60
  "package": "tokens",
61
61
  "relations": [],
62
- "since": "3.15.0",
62
+ "since": "3.15.1",
63
63
  "sources": [
64
64
  "packages/tokens/BREAKING_CHANGES.md",
65
65
  "packages/tokens/CHANGELOG.md",
@@ -2,7 +2,7 @@
2
2
  "custom": {
3
3
  "framework": "vue",
4
4
  "packageName": "@synergy-design-system/vue",
5
- "packageVersion": "3.15.0"
5
+ "packageVersion": "3.15.1"
6
6
  },
7
7
  "id": "setup:vue-package",
8
8
  "kind": "setup",
@@ -33,7 +33,7 @@
33
33
  "name": "Vue Framework Package",
34
34
  "package": "vue",
35
35
  "relations": [],
36
- "since": "3.15.0",
36
+ "since": "3.15.1",
37
37
  "sources": [
38
38
  "packages/vue/README.md",
39
39
  "packages/vue/CHANGELOG.md",
@@ -17,7 +17,7 @@
17
17
  "name": "index.d.ts",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/charts/js/index.d.ts"
23
23
  ],
@@ -17,7 +17,7 @@
17
17
  "name": "index.js",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/charts/js/index.js"
23
23
  ],
@@ -17,7 +17,7 @@
17
17
  "name": "_tokens.scss",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/charts/scss/_tokens.scss"
23
23
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025_dark.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/charts/themes/sick2025_dark.css"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025_light.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/charts/themes/sick2025_light.css"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2018-dark.json",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/src/figma-variables/output/sick2018-dark.json"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2018-light.json",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/src/figma-variables/output/sick2018-light.json"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025-dark.json",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/src/figma-variables/output/sick2025-dark.json"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025-light.json",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/src/figma-variables/output/sick2025-light.json"
24
24
  ],
@@ -17,7 +17,7 @@
17
17
  "name": "index.d.ts",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/js/index.d.ts"
23
23
  ],
@@ -17,7 +17,7 @@
17
17
  "name": "index.js",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/js/index.js"
23
23
  ],
@@ -17,7 +17,7 @@
17
17
  "name": "_tokens.scss",
18
18
  "package": "tokens",
19
19
  "relations": [],
20
- "since": "3.15.0",
20
+ "since": "3.15.1",
21
21
  "sources": [
22
22
  "packages/tokens/dist/scss/_tokens.scss"
23
23
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2018_dark.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/themes/sick2018_dark.css"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2018_light.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/themes/sick2018_light.css"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025_dark.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/themes/sick2025_dark.css"
24
24
  ],
@@ -18,7 +18,7 @@
18
18
  "name": "sick2025_light.css",
19
19
  "package": "tokens",
20
20
  "relations": [],
21
- "since": "3.15.0",
21
+ "since": "3.15.1",
22
22
  "sources": [
23
23
  "packages/tokens/dist/themes/sick2025_light.css"
24
24
  ],
package/data/index.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "builtAt": "2026-05-28T08:21:08.714Z",
2
+ "builtAt": "2026-06-03T07:07:11.049Z",
3
3
  "entities": [
4
4
  {
5
5
  "corePath": "data/core/asset/asset:sick2018-icons.json",
@@ -2,7 +2,6 @@
2
2
  import { html } from 'lit';
3
3
  import { query } from 'lit/decorators.js';
4
4
  import { state } from 'lit/decorators.js';
5
- import { classMap } from 'lit/directives/class-map.js';
6
5
  import type { SynAttributesChangedEvent } from '../../events/syn-attributes-changed.js';
7
6
  import componentStyles from '../../styles/component.styles.js';
8
7
  import SynergyElement from '../../internal/synergy-element.js';
@@ -29,11 +28,35 @@ export default class SynMenu extends SynergyElement {
29
28
 
30
29
  @query('slot') defaultSlot: HTMLSlotElement;
31
30
  @state() hasMenuItemsWithCheckmarks = false;
31
+ private checkmarkStyledItems = new Set<SynMenuItem>();
32
32
 
33
33
  private handleUpdateCheckmarks(items: SynMenuItem[]) {
34
34
  // #368: Treat a menu as having checkmarks if it has any checkboxes or items with loading states
35
35
  // The loading indicator has to be checked as well, as it's specially placed over the check mark
36
- this.hasMenuItemsWithCheckmarks = items.some(item => item.type === 'checkbox' || item.loading);
36
+ this.hasMenuItemsWithCheckmarks = items.some(item => item.type === 'checkbox' || item.loading);
37
+ this.syncCheckmarkVisibility(items);
38
+ }
39
+
40
+ private syncCheckmarkVisibility(items: SynMenuItem[]) {
41
+ this.checkmarkStyledItems.forEach(item => {
42
+ if (!items.includes(item)) {
43
+ item.style.removeProperty('--display-checkmark');
44
+ this.checkmarkStyledItems.delete(item);
45
+ }
46
+ });
47
+
48
+ if (this.hasMenuItemsWithCheckmarks) {
49
+ items.forEach(item => {
50
+ item.style.removeProperty('--display-checkmark');
51
+ this.checkmarkStyledItems.delete(item);
52
+ });
53
+ return;
54
+ }
55
+
56
+ items.forEach(item => {
57
+ item.style.setProperty('--display-checkmark', 'none');
58
+ this.checkmarkStyledItems.add(item);
59
+ });
37
60
  }
38
61
 
39
62
  private updateCheckMarksByChildPropChange = (e: SynAttributesChangedEvent) => {
@@ -43,6 +66,8 @@ export default class SynMenu extends SynergyElement {
43
66
 
44
67
  disconnectedCallback() {
45
68
  this.removeEventListener('syn-attributes-changed', this.updateCheckMarksByChildPropChange);
69
+ this.checkmarkStyledItems.forEach(item => item.style.removeProperty('--display-checkmark'));
70
+ this.checkmarkStyledItems.clear();
46
71
  }
47
72
 
48
73
  connectedCallback() {
@@ -51,22 +76,26 @@ export default class SynMenu extends SynergyElement {
51
76
  this.addEventListener('syn-attributes-changed', this.updateCheckMarksByChildPropChange);
52
77
  }
53
78
 
54
- private handleClick(event: MouseEvent) {
55
- const menuItemTypes = ['menuitem', 'menuitemcheckbox'];
56
-
79
+ private getMenuItemFromEvent(event: Event) {
57
80
  const composedPath = event.composedPath();
58
- const target = composedPath.find((el: Element) => menuItemTypes.includes(el?.getAttribute?.('role') || ''));
81
+ const target = composedPath.find((el: EventTarget) => el instanceof HTMLElement && this.isMenuItem(el));
82
+
83
+ if (!target || !(target instanceof HTMLElement)) {
84
+ return undefined;
85
+ }
59
86
 
60
- if (!target) return;
87
+ const closestMenu = composedPath.find((el: EventTarget) => el instanceof Element && el.getAttribute('role') === 'menu');
88
+ if (closestMenu !== this) {
89
+ return undefined;
90
+ }
61
91
 
62
- const closestMenu = composedPath.find((el: Element) => el?.getAttribute?.('role') === 'menu');
63
- const clickHasSubmenu = closestMenu !== this;
92
+ return target as SynMenuItem;
93
+ }
64
94
 
65
- // Make sure we're the menu thats supposed to be handling the click event.
66
- if (clickHasSubmenu) return;
95
+ private handleClick(event: MouseEvent) {
96
+ const item = this.getMenuItemFromEvent(event);
67
97
 
68
- // This isn't true. But we use it for TypeScript checks below.
69
- const item = target as SynMenuItem;
98
+ if (!item) return;
70
99
 
71
100
  if (item.type === 'checkbox') {
72
101
  item.checked = !item.checked;
@@ -120,10 +149,10 @@ export default class SynMenu extends SynergyElement {
120
149
  }
121
150
 
122
151
  private handleMouseDown(event: MouseEvent) {
123
- const target = event.target as HTMLElement;
152
+ const target = this.getMenuItemFromEvent(event);
124
153
 
125
- if (this.isMenuItem(target)) {
126
- this.setCurrentItem(target as SynMenuItem);
154
+ if (target) {
155
+ this.setCurrentItem(target);
127
156
  }
128
157
  }
129
158
 
@@ -144,14 +173,25 @@ export default class SynMenu extends SynergyElement {
144
173
  );
145
174
  }
146
175
 
176
+ private getMenuItemsFromElement(element: HTMLElement): SynMenuItem[] {
177
+ if (element.inert) {
178
+ return [];
179
+ }
180
+
181
+ if (this.isMenuItem(element)) {
182
+ return [element as SynMenuItem];
183
+ }
184
+
185
+ if (element.tagName.toLowerCase() === 'syn-menu') {
186
+ return [];
187
+ }
188
+
189
+ return [...element.children].flatMap(child => this.getMenuItemsFromElement(child as HTMLElement));
190
+ }
191
+
147
192
  /** @internal Gets all slotted menu items, ignoring dividers, headers, and other elements. */
148
193
  getAllItems() {
149
- return [...this.defaultSlot.assignedElements({ flatten: true })].filter((el: HTMLElement) => {
150
- if (el.inert || !this.isMenuItem(el)) {
151
- return false;
152
- }
153
- return true;
154
- }) as SynMenuItem[];
194
+ return [...this.defaultSlot.assignedElements({ flatten: true })].flatMap(el => this.getMenuItemsFromElement(el as HTMLElement));
155
195
  }
156
196
 
157
197
  /**
@@ -178,9 +218,6 @@ export default class SynMenu extends SynergyElement {
178
218
  render() {
179
219
  return html`
180
220
  <slot
181
- class=${classMap({
182
- 'menu--no-checkmarks': !this.hasMenuItemsWithCheckmarks,
183
- })}
184
221
  @slotchange=${this.handleSlotChange}
185
222
  @click=${this.handleClick}
186
223
  @keydown=${this.handleKeyDown}
@@ -26,12 +26,4 @@ export default css`
26
26
  ::slotted(syn-menu-label:first-of-type) {
27
27
  --display-divider: none;
28
28
  }
29
-
30
- /*
31
- * #368: Hide the checkmarks for menu items
32
- * when no syn-menu-item[checkbox] or loading is present
33
- */
34
- .menu--no-checkmarks::slotted(syn-menu-item) {
35
- --display-checkmark: none;
36
- }
37
29
  `;
@@ -79,13 +79,11 @@ export default class SynMenuItem extends SynergyElement {
79
79
  connectedCallback() {
80
80
  super.connectedCallback();
81
81
  this.addEventListener('click', this.handleHostClick);
82
- this.addEventListener('mouseover', this.handleMouseOver);
83
82
  }
84
83
 
85
84
  disconnectedCallback() {
86
85
  super.disconnectedCallback();
87
86
  this.removeEventListener('click', this.handleHostClick);
88
- this.removeEventListener('mouseover', this.handleMouseOver);
89
87
  }
90
88
 
91
89
  private handleDefaultSlotChange() {
@@ -112,11 +110,6 @@ export default class SynMenuItem extends SynergyElement {
112
110
  }
113
111
  };
114
112
 
115
- private handleMouseOver = (event: MouseEvent) => {
116
- this.focus();
117
- event.stopPropagation();
118
- };
119
-
120
113
  @watch('checked')
121
114
  handleCheckedChange() {
122
115
  // For proper accessibility, users have to use type="checkbox" to use the checked attribute
@@ -11,6 +11,7 @@ export class SubmenuController implements ReactiveController {
11
11
  private host: ReactiveControllerHost & SynMenuItem;
12
12
  private popupRef: Ref<SynPopup> = createRef();
13
13
  private enableSubmenuTimer = -1;
14
+ private hasGlobalDismissListeners = false;
14
15
  private isConnected = false;
15
16
  private isPopupConnected = false;
16
17
  private skidding = 0;
@@ -45,6 +46,7 @@ export class SubmenuController implements ReactiveController {
45
46
  if (!this.isConnected) {
46
47
  this.host.addEventListener('mousemove', this.handleMouseMove);
47
48
  this.host.addEventListener('mouseover', this.handleMouseOver);
49
+ this.host.addEventListener('mouseleave', this.handleHostMouseLeave);
48
50
  this.host.addEventListener('keydown', this.handleKeyDown);
49
51
  this.host.addEventListener('click', this.handleClick);
50
52
  this.host.addEventListener('focusout', this.handleFocusOut);
@@ -56,6 +58,7 @@ export class SubmenuController implements ReactiveController {
56
58
  if (!this.isPopupConnected) {
57
59
  if (this.popupRef.value) {
58
60
  this.popupRef.value.addEventListener('mouseover', this.handlePopupMouseover);
61
+ this.popupRef.value.addEventListener('mouseleave', this.handlePopupMouseLeave);
59
62
  this.popupRef.value.addEventListener('syn-reposition', this.handlePopupReposition);
60
63
  this.isPopupConnected = true;
61
64
  }
@@ -66,6 +69,7 @@ export class SubmenuController implements ReactiveController {
66
69
  if (this.isConnected) {
67
70
  this.host.removeEventListener('mousemove', this.handleMouseMove);
68
71
  this.host.removeEventListener('mouseover', this.handleMouseOver);
72
+ this.host.removeEventListener('mouseleave', this.handleHostMouseLeave);
69
73
  this.host.removeEventListener('keydown', this.handleKeyDown);
70
74
  this.host.removeEventListener('click', this.handleClick);
71
75
  this.host.removeEventListener('focusout', this.handleFocusOut);
@@ -74,10 +78,37 @@ export class SubmenuController implements ReactiveController {
74
78
  if (this.isPopupConnected) {
75
79
  if (this.popupRef.value) {
76
80
  this.popupRef.value.removeEventListener('mouseover', this.handlePopupMouseover);
81
+ this.popupRef.value.removeEventListener('mouseleave', this.handlePopupMouseLeave);
77
82
  this.popupRef.value.removeEventListener('syn-reposition', this.handlePopupReposition);
78
83
  this.isPopupConnected = false;
79
84
  }
80
85
  }
86
+
87
+ this.removeGlobalDismissListeners();
88
+ }
89
+
90
+ private addGlobalDismissListeners() {
91
+ if (this.hasGlobalDismissListeners) {
92
+ return;
93
+ }
94
+
95
+ document.addEventListener('keydown', this.handleDocumentKeyDown);
96
+ window.addEventListener('blur', this.handleWindowBlur);
97
+ window.addEventListener('pagehide', this.handlePageHide);
98
+ document.addEventListener('visibilitychange', this.handleVisibilityChange);
99
+ this.hasGlobalDismissListeners = true;
100
+ }
101
+
102
+ private removeGlobalDismissListeners() {
103
+ if (!this.hasGlobalDismissListeners) {
104
+ return;
105
+ }
106
+
107
+ document.removeEventListener('keydown', this.handleDocumentKeyDown);
108
+ window.removeEventListener('blur', this.handleWindowBlur);
109
+ window.removeEventListener('pagehide', this.handlePageHide);
110
+ document.removeEventListener('visibilitychange', this.handleVisibilityChange);
111
+ this.hasGlobalDismissListeners = false;
81
112
  }
82
113
 
83
114
  // Set the safe triangle cursor position
@@ -92,6 +123,35 @@ export class SubmenuController implements ReactiveController {
92
123
  }
93
124
  };
94
125
 
126
+ private isWithinSubmenuInteractionTree(target: EventTarget | null): boolean {
127
+ if (!(target instanceof Node)) {
128
+ return false;
129
+ }
130
+
131
+ if (this.host.contains(target)) {
132
+ return true;
133
+ }
134
+
135
+ if (this.popupRef.value?.contains(target)) {
136
+ return true;
137
+ }
138
+
139
+ const rootNode = target.getRootNode();
140
+ if (rootNode instanceof ShadowRoot) {
141
+ return this.isWithinSubmenuInteractionTree(rootNode.host);
142
+ }
143
+
144
+ return false;
145
+ }
146
+
147
+ private handleHostMouseLeave = (event: MouseEvent) => {
148
+ if (this.isWithinSubmenuInteractionTree(event.relatedTarget)) {
149
+ return;
150
+ }
151
+
152
+ this.disableSubmenu();
153
+ };
154
+
95
155
  private handleSubmenuEntry(event: KeyboardEvent) {
96
156
  // Pass focus to the first menu-item in the submenu.
97
157
  const submenuSlot: HTMLSlotElement | null = this.host.renderRoot.querySelector("slot[name='submenu']");
@@ -187,11 +247,40 @@ export class SubmenuController implements ReactiveController {
187
247
  this.disableSubmenu();
188
248
  };
189
249
 
250
+ private handleWindowBlur = () => {
251
+ this.disableSubmenu();
252
+ };
253
+
254
+ private handlePageHide = () => {
255
+ this.disableSubmenu();
256
+ };
257
+
258
+ private handleVisibilityChange = () => {
259
+ if (document.visibilityState === 'hidden') {
260
+ this.disableSubmenu();
261
+ }
262
+ };
263
+
264
+ private handleDocumentKeyDown = (event: KeyboardEvent) => {
265
+ if (event.key === 'Escape' && this.isExpanded()) {
266
+ this.disableSubmenu();
267
+ event.stopPropagation();
268
+ }
269
+ };
270
+
190
271
  // Prevent the parent menu-item from getting focus on mouse movement on the submenu
191
272
  private handlePopupMouseover = (event: MouseEvent) => {
192
273
  event.stopPropagation();
193
274
  };
194
275
 
276
+ private handlePopupMouseLeave = (event: MouseEvent) => {
277
+ if (this.isWithinSubmenuInteractionTree(event.relatedTarget)) {
278
+ return;
279
+ }
280
+
281
+ this.disableSubmenu();
282
+ };
283
+
195
284
  // Set the safe triangle values for the submenu when the position changes
196
285
  private handlePopupReposition = () => {
197
286
  const submenuSlot: HTMLSlotElement | null = this.host.renderRoot.querySelector("slot[name='submenu']");
@@ -213,6 +302,11 @@ export class SubmenuController implements ReactiveController {
213
302
  if (this.popupRef.value) {
214
303
  if (this.popupRef.value.active !== state) {
215
304
  this.popupRef.value.active = state;
305
+ if (state) {
306
+ this.addGlobalDismissListeners();
307
+ } else {
308
+ this.removeGlobalDismissListeners();
309
+ }
216
310
  this.host.requestUpdate();
217
311
  }
218
312
  }
@@ -1,5 +1,13 @@
1
1
  # @synergy-design-system/angular
2
2
 
3
+ ## 3.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`4fdb69a`](https://github.com/synergy-design-system/synergy-design-system/commit/4fdb69aec5ddb0ddfa76a948c87eaf84be6fd670)]:
8
+ - @synergy-design-system/components@3.15.1
9
+ - @synergy-design-system/tokens@3.15.1
10
+
3
11
  ## 3.15.0
4
12
 
5
13
  ### Minor Changes
@@ -22,7 +22,7 @@
22
22
  "url": "https://github.com/synergy-design-system/synergy-design-system.git",
23
23
  "directory": "packages/angular"
24
24
  },
25
- "version": "3.15.0",
25
+ "version": "3.15.1",
26
26
  "scripts": {
27
27
  "_build": "pnpm _clean && ng-packagr -c tsconfig.lib.json && pnpm _after-build",
28
28
  "_clean": "rm -rf ../_private/angular-demo/.angular",
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1296](https://github.com/synergy-design-system/synergy-design-system/pull/1296) [`4fdb69a`](https://github.com/synergy-design-system/synergy-design-system/commit/4fdb69aec5ddb0ddfa76a948c87eaf84be6fd670) Thanks [@schilchSICKAG](https://github.com/schilchSICKAG)! - Released on: 2026-06-03
8
+
9
+ fix: 🐛 `<syn-menu>` multiple issues ([#1295](https://github.com/synergy-design-system/synergy-design-system/issues/1295))
10
+
11
+ This release fixes multiple issues when using `<syn-menu>`:
12
+ - submenus no longer stay open when leaving the browser window ([#882](https://github.com/synergy-design-system/synergy-design-system/issues/882))
13
+ - `<syn-menu-item>` wrapped in tooltip can now be used reliably (including navigation and selection) ([#1162](https://github.com/synergy-design-system/synergy-design-system/issues/1162))
14
+ - `<syn-menu-item>` no longer steals focus on hover ([#1286](https://github.com/synergy-design-system/synergy-design-system/issues/1286))
15
+
16
+ - Updated dependencies []:
17
+ - @synergy-design-system/tokens@3.15.1
18
+
3
19
  ## 3.15.0
4
20
 
5
21
  ### Minor Changes
@@ -4,7 +4,7 @@
4
4
  "url": "https://www.sick.com"
5
5
  },
6
6
  "name": "@synergy-design-system/components",
7
- "version": "3.15.0",
7
+ "version": "3.15.1",
8
8
  "description": "",
9
9
  "repository": {
10
10
  "type": "git",
@@ -1,5 +1,13 @@
1
1
  # @synergy-design-system/react
2
2
 
3
+ ## 3.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`4fdb69a`](https://github.com/synergy-design-system/synergy-design-system/commit/4fdb69aec5ddb0ddfa76a948c87eaf84be6fd670)]:
8
+ - @synergy-design-system/components@3.15.1
9
+ - @synergy-design-system/tokens@3.15.1
10
+
3
11
  ## 3.15.0
4
12
 
5
13
  ### Minor Changes
@@ -43,7 +43,7 @@
43
43
  "directory": "packages/react"
44
44
  },
45
45
  "type": "module",
46
- "version": "3.15.0",
46
+ "version": "3.15.1",
47
47
  "devDependencies": {
48
48
  "@types/react": "^19.2.14",
49
49
  "react": "^19.2.5"
@@ -1,5 +1,7 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.15.1
4
+
3
5
  ## 3.15.0
4
6
 
5
7
  ### Minor Changes
@@ -82,5 +82,5 @@
82
82
  },
83
83
  "type": "module",
84
84
  "types": "./dist/js/index.d.ts",
85
- "version": "3.15.0"
85
+ "version": "3.15.1"
86
86
  }
@@ -1,5 +1,13 @@
1
1
  # @synergy-design-system/vue
2
2
 
3
+ ## 3.15.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`4fdb69a`](https://github.com/synergy-design-system/synergy-design-system/commit/4fdb69aec5ddb0ddfa76a948c87eaf84be6fd670)]:
8
+ - @synergy-design-system/components@3.15.1
9
+ - @synergy-design-system/tokens@3.15.1
10
+
3
11
  ## 3.15.0
4
12
 
5
13
  ### Minor Changes
@@ -50,7 +50,7 @@
50
50
  "directory": "packages/vue"
51
51
  },
52
52
  "type": "module",
53
- "version": "3.15.0",
53
+ "version": "3.15.1",
54
54
  "devDependencies": {
55
55
  "@vitejs/plugin-vue": "^6.0.6",
56
56
  "@vue/tsconfig": "^0.9.1",
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
  $SynCategorical10: var(--syn-categorical-10) !default;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  */
5
5
  $SynAlertErrorColorBackground: var(--syn-alert-error-color-background) !default;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @synergy-design-system/tokens version 3.15.0
2
+ * @synergy-design-system/tokens version 3.15.1
3
3
  * SICK Global UX Foundation
4
4
  * Do not edit directly, this file was auto-generated.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  {
2
- "builtAt": "2026-05-28T08:21:08.716Z",
2
+ "builtAt": "2026-06-03T07:07:11.050Z",
3
3
  "sources": [
4
4
  {
5
5
  "entityCount": 4,
package/package.json CHANGED
@@ -22,12 +22,12 @@
22
22
  "serve-handler": "^6.1.7",
23
23
  "typescript": "^5.9.3",
24
24
  "zod": "^4.3.6",
25
- "@synergy-design-system/tokens": "^3.15.0",
26
- "@synergy-design-system/components": "3.15.0",
25
+ "@synergy-design-system/eslint-config-syn": "^0.1.0",
26
+ "@synergy-design-system/fonts": "1.0.6",
27
27
  "@synergy-design-system/docs": "0.1.0",
28
+ "@synergy-design-system/components": "3.15.1",
28
29
  "@synergy-design-system/styles": "2.1.0",
29
- "@synergy-design-system/fonts": "1.0.6",
30
- "@synergy-design-system/eslint-config-syn": "^0.1.0"
30
+ "@synergy-design-system/tokens": "^3.15.1"
31
31
  },
32
32
  "exports": {
33
33
  ".": {
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "types": "./dist/index.d.ts",
72
72
  "type": "module",
73
- "version": "3.9.0",
73
+ "version": "3.11.0",
74
74
  "scripts": {
75
75
  "build:all": "METADATA_LOG_LEVEL=info pnpm run build:ts && RUN_STORYBOOK_SCRAPER=true pnpm run build:data",
76
76
  "build": "METADATA_LOG_LEVEL=info pnpm run build:ts && pnpm run build:data",