@vaadin/context-menu 25.1.2 → 25.2.0-alpha10

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.
@@ -48,7 +48,7 @@
48
48
  "type": {
49
49
  "text": "!Array<!ContextMenuItem> | undefined"
50
50
  },
51
- "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
51
+ "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
52
52
  "attribute": "items",
53
53
  "inheritedFrom": {
54
54
  "name": "ItemsMixin",
@@ -230,13 +230,88 @@
230
230
  }
231
231
  ]
232
232
  },
233
+ {
234
+ "kind": "javascript-module",
235
+ "path": "src/vaadin-context-menu-tooltip-controller.js",
236
+ "declarations": [
237
+ {
238
+ "kind": "class",
239
+ "description": "Controller for the tooltip slotted into `<vaadin-context-menu>`. Configures\nthe tooltip in manual mode and drives its target, context, and position\nbased on the currently hovered or focused item.",
240
+ "name": "ContextMenuTooltipController",
241
+ "members": [
242
+ {
243
+ "kind": "method",
244
+ "name": "close",
245
+ "parameters": [
246
+ {
247
+ "name": "immediate",
248
+ "type": {
249
+ "text": "boolean"
250
+ }
251
+ }
252
+ ]
253
+ },
254
+ {
255
+ "kind": "method",
256
+ "name": "initCustomNode",
257
+ "parameters": [
258
+ {
259
+ "name": "tooltipNode"
260
+ }
261
+ ]
262
+ },
263
+ {
264
+ "kind": "method",
265
+ "name": "open",
266
+ "parameters": [
267
+ {
268
+ "name": "{ trigger }"
269
+ },
270
+ {
271
+ "name": "options",
272
+ "type": {
273
+ "text": "{ trigger: 'hover' | 'focus' }"
274
+ }
275
+ }
276
+ ]
277
+ },
278
+ {
279
+ "kind": "method",
280
+ "name": "setTarget",
281
+ "parameters": [
282
+ {
283
+ "name": "target",
284
+ "type": {
285
+ "text": "HTMLElement | null"
286
+ }
287
+ }
288
+ ]
289
+ }
290
+ ],
291
+ "superclass": {
292
+ "name": "SlotController",
293
+ "package": "@vaadin/component-base/src/slot-controller.js"
294
+ }
295
+ }
296
+ ],
297
+ "exports": [
298
+ {
299
+ "kind": "js",
300
+ "name": "ContextMenuTooltipController",
301
+ "declaration": {
302
+ "name": "ContextMenuTooltipController",
303
+ "module": "src/vaadin-context-menu-tooltip-controller.js"
304
+ }
305
+ }
306
+ ]
307
+ },
233
308
  {
234
309
  "kind": "javascript-module",
235
310
  "path": "src/vaadin-context-menu.js",
236
311
  "declarations": [
237
312
  {
238
313
  "kind": "class",
239
- "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
314
+ "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
240
315
  "name": "ContextMenu",
241
316
  "members": [
242
317
  {
@@ -269,7 +344,7 @@
269
344
  "type": {
270
345
  "text": "!Array<!ContextMenuItem> | undefined"
271
346
  },
272
- "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
347
+ "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
273
348
  "attribute": "items",
274
349
  "inheritedFrom": {
275
350
  "name": "ItemsMixin",
@@ -571,7 +646,7 @@
571
646
  "type": {
572
647
  "text": "!Array<!ContextMenuItem> | undefined"
573
648
  },
574
- "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
649
+ "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
575
650
  "attribute": "items"
576
651
  }
577
652
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/context-menu",
3
- "version": "25.1.2",
3
+ "version": "25.2.0-alpha10",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,21 +37,21 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@open-wc/dedupe-mixin": "^1.3.0",
40
- "@vaadin/a11y-base": "~25.1.2",
41
- "@vaadin/component-base": "~25.1.2",
42
- "@vaadin/item": "~25.1.2",
43
- "@vaadin/list-box": "~25.1.2",
44
- "@vaadin/lit-renderer": "~25.1.2",
45
- "@vaadin/overlay": "~25.1.2",
46
- "@vaadin/vaadin-themable-mixin": "~25.1.2",
40
+ "@vaadin/a11y-base": "25.2.0-alpha10",
41
+ "@vaadin/component-base": "25.2.0-alpha10",
42
+ "@vaadin/item": "25.2.0-alpha10",
43
+ "@vaadin/list-box": "25.2.0-alpha10",
44
+ "@vaadin/lit-renderer": "25.2.0-alpha10",
45
+ "@vaadin/overlay": "25.2.0-alpha10",
46
+ "@vaadin/vaadin-themable-mixin": "25.2.0-alpha10",
47
47
  "lit": "^3.0.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@vaadin/aura": "~25.1.2",
51
- "@vaadin/chai-plugins": "~25.1.2",
52
- "@vaadin/test-runner-commands": "~25.1.2",
50
+ "@vaadin/aura": "25.2.0-alpha10",
51
+ "@vaadin/chai-plugins": "25.2.0-alpha10",
52
+ "@vaadin/test-runner-commands": "25.2.0-alpha10",
53
53
  "@vaadin/testing-helpers": "^2.0.0",
54
- "@vaadin/vaadin-lumo-styles": "~25.1.2",
54
+ "@vaadin/vaadin-lumo-styles": "25.2.0-alpha10",
55
55
  "sinon": "^21.0.2"
56
56
  },
57
57
  "customElements": "custom-elements.json",
@@ -59,5 +59,5 @@
59
59
  "web-types.json",
60
60
  "web-types.lit.json"
61
61
  ],
62
- "gitHead": "48e5dc507ac5eb8d34839be06cac652f1635fe1c"
62
+ "gitHead": "1303b6a3eeecb44a9d26f2b53cb56d9e906febdf"
63
63
  }
@@ -47,6 +47,11 @@ class ContextMenuItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(Lumo
47
47
 
48
48
  this.setAttribute('role', 'menuitem');
49
49
  }
50
+
51
+ /** @override */
52
+ __shouldAllowFocusWhenDisabled() {
53
+ return window.Vaadin.featureFlags.accessibleDisabledMenuItems;
54
+ }
50
55
  }
51
56
 
52
57
  defineCustomElement(ContextMenuItem);
@@ -7,6 +7,7 @@ import { isElementFocusable, isKeyboardActive } from '@vaadin/a11y-base/src/focu
7
7
  import { isAndroid, isIOS } from '@vaadin/component-base/src/browser-utils.js';
8
8
  import { addListener, deepTargetFind, gestures, removeListener } from '@vaadin/component-base/src/gestures.js';
9
9
  import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
10
+ import { ContextMenuTooltipController } from './vaadin-context-menu-tooltip-controller.js';
10
11
  import { ItemsMixin } from './vaadin-contextmenu-items-mixin.js';
11
12
 
12
13
  /**
@@ -172,6 +173,15 @@ export const ContextMenuMixin = (superClass) =>
172
173
  this._fullscreen = matches;
173
174
  }),
174
175
  );
176
+
177
+ // Sub-menus inherit the tooltip controller from their parent menu
178
+ // (assigned before `firstUpdated` runs) to reuse the same slotted
179
+ // `<vaadin-tooltip>` across nesting levels. Only create a new one
180
+ // when none was inherited, i.e. on the outer host.
181
+ if (!this._tooltipController) {
182
+ this._tooltipController = new ContextMenuTooltipController(this);
183
+ this.addController(this._tooltipController);
184
+ }
175
185
  }
176
186
 
177
187
  /**
@@ -645,10 +655,4 @@ export const ContextMenuMixin = (superClass) =>
645
655
  this.close();
646
656
  }
647
657
  }
648
-
649
- /**
650
- * Fired when the context menu is closed.
651
- *
652
- * @event closed
653
- */
654
658
  };
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 2026 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
7
+
8
+ /**
9
+ * Controller for the tooltip slotted into `<vaadin-context-menu>`. Configures
10
+ * the tooltip in manual mode and drives its target, context, and position
11
+ * based on the currently hovered or focused item.
12
+ */
13
+ export class ContextMenuTooltipController extends SlotController {
14
+ constructor(host) {
15
+ super(host, 'tooltip');
16
+ }
17
+
18
+ /** @override */
19
+ initCustomNode(tooltipNode) {
20
+ tooltipNode.manual = true;
21
+ tooltipNode.generator ||= ({ item }) => item?.tooltip;
22
+ }
23
+
24
+ /** @protected */
25
+ _getItem(target) {
26
+ return target._item;
27
+ }
28
+
29
+ /** @protected */
30
+ _getDefaultPosition(target) {
31
+ const item = this._getItem(target);
32
+ return item.children?.length > 0 && !item.disabled ? 'start' : 'end';
33
+ }
34
+
35
+ /**
36
+ * @param {HTMLElement | null} target
37
+ */
38
+ setTarget(target) {
39
+ const tooltipNode = this.node;
40
+ if (!tooltipNode) {
41
+ return;
42
+ }
43
+
44
+ const item = target ? this._getItem(target) : null;
45
+ if (item?.tooltip) {
46
+ tooltipNode.target = target;
47
+ tooltipNode.context = { item };
48
+ tooltipNode._position = item.tooltipPosition || this._getDefaultPosition(target);
49
+ } else {
50
+ tooltipNode.target = null;
51
+ tooltipNode.context = { item: null };
52
+ this.close(true);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * @param {{ trigger: 'hover' | 'focus' }} options
58
+ */
59
+ open({ trigger }) {
60
+ const tooltipNode = this.node;
61
+ if (tooltipNode?.isConnected && tooltipNode.target) {
62
+ tooltipNode._stateController.open({
63
+ hover: trigger === 'hover',
64
+ focus: trigger === 'focus',
65
+ });
66
+ }
67
+ }
68
+
69
+ /**
70
+ * @param {boolean} immediate
71
+ */
72
+ close(immediate) {
73
+ const tooltipNode = this.node;
74
+ tooltipNode?._stateController.close(immediate);
75
+ }
76
+ }
@@ -106,6 +106,34 @@ export interface ContextMenuEventMap<TItem extends ContextMenuItem = ContextMenu
106
106
  *
107
107
  * **NOTE:** when the `items` array is defined, the renderer cannot be used.
108
108
  *
109
+ * #### Disabled menu items
110
+ *
111
+ * When disabled, menu items are rendered as "dimmed".
112
+ *
113
+ * By default, disabled items are not focusable and don't react to hover.
114
+ * As a result, they are hidden from assistive technologies, and it's not
115
+ * possible to show a tooltip to explain why they are disabled. This can
116
+ * be addressed by enabling the feature flag `accessibleDisabledMenuItems`,
117
+ * which makes disabled items focusable and hoverable, while still
118
+ * preventing them from being activated:
119
+ *
120
+ * ```js
121
+ * // Set before any context menu is attached to the DOM.
122
+ * window.Vaadin.featureFlags.accessibleDisabledMenuItems = true;
123
+ * ```
124
+ *
125
+ * #### Item tooltips
126
+ *
127
+ * Menu items can have tooltips that are shown on hover and keyboard
128
+ * focus. To enable them, add a slotted `<vaadin-tooltip>` element
129
+ * and set the `tooltip` property on each item that should have one:
130
+ *
131
+ * ```html
132
+ * <vaadin-context-menu>
133
+ * <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
134
+ * </vaadin-context-menu>
135
+ * ```
136
+ *
109
137
  * ### Rendering
110
138
  *
111
139
  * The content of the menu can be populated by using the renderer callback function.
@@ -54,6 +54,34 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
54
54
  *
55
55
  * **NOTE:** when the `items` array is defined, the renderer cannot be used.
56
56
  *
57
+ * #### Disabled menu items
58
+ *
59
+ * When disabled, menu items are rendered as "dimmed".
60
+ *
61
+ * By default, disabled items are not focusable and don't react to hover.
62
+ * As a result, they are hidden from assistive technologies, and it's not
63
+ * possible to show a tooltip to explain why they are disabled. This can
64
+ * be addressed by enabling the feature flag `accessibleDisabledMenuItems`,
65
+ * which makes disabled items focusable and hoverable, while still
66
+ * preventing them from being activated:
67
+ *
68
+ * ```js
69
+ * // Set before any context menu is attached to the DOM.
70
+ * window.Vaadin.featureFlags.accessibleDisabledMenuItems = true;
71
+ * ```
72
+ *
73
+ * #### Item tooltips
74
+ *
75
+ * Menu items can have tooltips that are shown on hover and keyboard
76
+ * focus. To enable them, add a slotted `<vaadin-tooltip>` element
77
+ * and set the `tooltip` property on each item that should have one:
78
+ *
79
+ * ```html
80
+ * <vaadin-context-menu>
81
+ * <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
82
+ * </vaadin-context-menu>
83
+ * ```
84
+ *
57
85
  * ### Rendering
58
86
  *
59
87
  * The content of the menu can be populated by using the renderer callback function.
@@ -267,7 +295,7 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
267
295
  .modeless="${this._modeless}"
268
296
  .renderer="${this.items ? this.__itemsRenderer : this.renderer}"
269
297
  .position="${position}"
270
- .positionTarget="${position ? context && context.target : this._positionTarget}"
298
+ .positionTarget="${position ? context?.target : this._positionTarget}"
271
299
  .horizontalAlign="${this.__computeHorizontalAlign(position)}"
272
300
  .verticalAlign="${this.__computeVerticalAlign(position)}"
273
301
  ?no-horizontal-overlap="${this.__computeNoHorizontalOverlap(position)}"
@@ -283,6 +311,8 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
283
311
  <slot name="overlay"></slot>
284
312
  <slot name="submenu" slot="submenu"></slot>
285
313
  </vaadin-context-menu-overlay>
314
+
315
+ <slot name="tooltip"></slot>
286
316
  `;
287
317
  }
288
318
 
@@ -321,14 +351,6 @@ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(Polyl
321
351
 
322
352
  return ['top-start', 'top-end', 'top', 'start-bottom', 'end-bottom'].includes(position) ? 'bottom' : 'top';
323
353
  }
324
-
325
- /**
326
- * Fired when an item is selected when the context menu is populated using the `items` API.
327
- *
328
- * @event item-selected
329
- * @param {Object} detail
330
- * @param {Object} detail.value the selected menu item
331
- */
332
354
  }
333
355
 
334
356
  defineCustomElement(ContextMenu);
@@ -120,7 +120,7 @@ register({
120
120
  ev.detail = { x, y, sourceEvent };
121
121
  target.dispatchEvent(ev);
122
122
  // Forward `preventDefault` in a clean way
123
- if (ev.defaultPrevented && sourceEvent && sourceEvent.preventDefault) {
123
+ if (ev.defaultPrevented && sourceEvent?.preventDefault) {
124
124
  sourceEvent.preventDefault();
125
125
  }
126
126
  },
@@ -9,6 +9,19 @@ import type { Constructor } from '@open-wc/dedupe-mixin';
9
9
 
10
10
  export type ContextMenuItem<TItemData extends object = object> = {
11
11
  text?: string;
12
+ /**
13
+ * Text to be set as the menu item's tooltip.
14
+ * Requires a `<vaadin-tooltip slot="tooltip">` element to be added inside the `<vaadin-context-menu>`.
15
+ */
16
+ tooltip?: string;
17
+ /**
18
+ * Position of the item's tooltip relative to the item
19
+ * (e.g. `end`, `top`, `bottom-start`). Items with a sub-menu default to `start` to
20
+ * avoid overlap with the opening sub-menu; all other items, including disabled ones
21
+ * (whose sub-menus cannot be opened), default to `end`. If the slotted
22
+ * `<vaadin-tooltip>` has its `position` property set, that value is used instead.
23
+ */
24
+ tooltipPosition?: string;
12
25
  component?: HTMLElement | string;
13
26
  disabled?: boolean;
14
27
  checked?: boolean;
@@ -48,6 +61,18 @@ export declare class ItemsMixinClass<TItem extends ContextMenuItem = ContextMenu
48
61
  * { text: 'Menu Item 3', disabled: true, className: 'last' }
49
62
  * ];
50
63
  * ```
64
+ *
65
+ * #### Item tooltips
66
+ *
67
+ * Menu items can have tooltips that are shown on hover and keyboard
68
+ * focus. To enable them, add a slotted `<vaadin-tooltip>` element
69
+ * and set the `tooltip` property on each item that should have one:
70
+ *
71
+ * ```html
72
+ * <vaadin-context-menu>
73
+ * <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
74
+ * </vaadin-context-menu>
75
+ * ```
51
76
  */
52
77
  items: TItem[] | undefined;
53
78
 
@@ -3,6 +3,7 @@
3
3
  * Copyright (c) 2016 - 2026 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
6
7
  import { isTouch } from '@vaadin/component-base/src/browser-utils.js';
7
8
 
8
9
  /**
@@ -16,6 +17,13 @@ export const ItemsMixin = (superClass) =>
16
17
  * @typedef ContextMenuItem
17
18
  * @type {object}
18
19
  * @property {string} text - Text to be set as the menu item component's textContent
20
+ * @property {string} tooltip - Text to be set as the menu item's tooltip.
21
+ * Requires a `<vaadin-tooltip slot="tooltip">` element to be added inside the `<vaadin-context-menu>`.
22
+ * @property {string} tooltipPosition - Position of the item's tooltip relative to the
23
+ * item (e.g. `end`, `top`, `bottom-start`). Items with a sub-menu default to `start`
24
+ * to avoid overlap with the opening sub-menu; all other items, including disabled
25
+ * ones (whose sub-menus cannot be opened), default to `end`. If the slotted
26
+ * `<vaadin-tooltip>` has its `position` property set, that value is used instead.
19
27
  * @property {string | HTMLElement} component - The component to represent the item.
20
28
  * Either a tagName or an element instance. Defaults to "vaadin-context-menu-item".
21
29
  * @property {boolean} disabled - If true, the item is disabled and cannot be selected
@@ -54,6 +62,18 @@ export const ItemsMixin = (superClass) =>
54
62
  * ];
55
63
  * ```
56
64
  *
65
+ * #### Item tooltips
66
+ *
67
+ * Menu items can have tooltips that are shown on hover and keyboard
68
+ * focus. To enable them, add a slotted `<vaadin-tooltip>` element
69
+ * and set the `tooltip` property on each item that should have one:
70
+ *
71
+ * ```html
72
+ * <vaadin-context-menu>
73
+ * <vaadin-tooltip slot="tooltip"></vaadin-tooltip>
74
+ * </vaadin-context-menu>
75
+ * ```
76
+ *
57
77
  * @type {!Array<!ContextMenuItem> | undefined}
58
78
  */
59
79
  items: {
@@ -105,6 +125,7 @@ export const ItemsMixin = (superClass) =>
105
125
  disconnectedCallback() {
106
126
  super.disconnectedCallback();
107
127
  document.documentElement.removeEventListener('click', this.__itemsOutsideClickListener);
128
+ this._tooltipController.setTarget(null);
108
129
  }
109
130
 
110
131
  /**
@@ -126,7 +147,7 @@ export const ItemsMixin = (superClass) =>
126
147
  // If parent item is not focused, do not focus submenu
127
148
  if (overlay.parentOverlay) {
128
149
  const parent = overlay.parentOverlay._contentRoot.querySelector('[expanded]');
129
- if (parent && parent.hasAttribute('focused') && child) {
150
+ if (parent?.hasAttribute('focused') && child) {
130
151
  child.focus();
131
152
  } else {
132
153
  overlay.$.overlay.focus();
@@ -264,6 +285,31 @@ export const ItemsMixin = (superClass) =>
264
285
  }
265
286
 
266
287
  this.__showSubMenu(event);
288
+
289
+ const itemElement = event.target.closest(`${this._tagNamePrefix}-item`);
290
+ this._tooltipController.setTarget(itemElement);
291
+ this._tooltipController.open({ trigger: 'hover' });
292
+ });
293
+
294
+ overlay.addEventListener('mouseleave', (event) => {
295
+ // Ignore events from the submenus
296
+ if (event.composedPath().includes(this._subMenu)) {
297
+ return;
298
+ }
299
+
300
+ this._tooltipController.close();
301
+ });
302
+
303
+ overlay.addEventListener('focusin', (event) => {
304
+ // Ignore events from the submenus
305
+ // Ignore non-keyboard focus changes (e.g. clicks).
306
+ if (event.composedPath().includes(this._subMenu) || !isKeyboardActive()) {
307
+ return;
308
+ }
309
+
310
+ const itemElement = event.target.closest(`${this._tagNamePrefix}-item`);
311
+ this._tooltipController.setTarget(itemElement);
312
+ this._tooltipController.open({ trigger: 'focus' });
267
313
  });
268
314
 
269
315
  overlay.addEventListener('keydown', (event) => {
@@ -300,6 +346,11 @@ export const ItemsMixin = (superClass) =>
300
346
  __initSubMenu() {
301
347
  const subMenu = document.createElement(this.constructor.is);
302
348
 
349
+ // The slotted `<vaadin-tooltip>` lives on the outer `<vaadin-context-menu>`
350
+ // host. Its tooltip controller instance is shared across sub-menus to
351
+ // reuse the same tooltip element for items at every nesting level.
352
+ subMenu._tooltipController = this._tooltipController;
353
+
303
354
  subMenu._modeless = true;
304
355
  subMenu.openOn = 'opensubmenu';
305
356
 
@@ -374,12 +425,12 @@ export const ItemsMixin = (superClass) =>
374
425
  const subMenu = this._subMenu;
375
426
  const expandedItem = this._listBox.querySelector('[expanded]');
376
427
 
377
- if (item && item !== expandedItem) {
428
+ if (item && item !== expandedItem && !item.disabled) {
378
429
  const { children } = item._item;
379
430
 
380
431
  // Check if the sub-menu was focused before closing it.
381
432
  const child = subMenu._overlayElement._contentRoot.firstElementChild;
382
- const isSubmenuFocused = child && child.focused;
433
+ const isSubmenuFocused = child?.focused;
383
434
 
384
435
  // Mark previously expanded item as collapsed
385
436
  if (expandedItem) {
@@ -395,7 +446,7 @@ export const ItemsMixin = (superClass) =>
395
446
  return;
396
447
  }
397
448
 
398
- if (children && children.length) {
449
+ if (children?.length) {
399
450
  // Open or update the submenu if the new item has children
400
451
  this.__updateExpanded(item, true);
401
452
  this.__openSubMenu(subMenu, item);
@@ -407,6 +458,12 @@ export const ItemsMixin = (superClass) =>
407
458
  this._overlayElement.$.overlay.focus();
408
459
  }
409
460
  }
461
+
462
+ // Only reachable with `accessibleDisabledMenuItems` enabled (disabled
463
+ // items otherwise have `pointer-events: none` and never receive mouseover).
464
+ if (item?.disabled) {
465
+ subMenu.close();
466
+ }
410
467
  }
411
468
 
412
469
  /** @protected */
@@ -103,7 +103,7 @@ export const MenuOverlayMixin = (superClass) =>
103
103
 
104
104
  // Adjust constraints to ensure bottom-aligned applies to sub-menu.
105
105
  const parent = this.parentOverlay;
106
- if (parent && parent.hasAttribute('bottom-aligned')) {
106
+ if (parent?.hasAttribute('bottom-aligned')) {
107
107
  const parentStyle = getComputedStyle(parent);
108
108
  yMax = yMax - parseFloat(parentStyle.bottom) - parseFloat(parentStyle.height);
109
109
  }
package/web-types.json CHANGED
@@ -1,23 +1,21 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/context-menu",
4
- "version": "25.1.2",
4
+ "version": "25.2.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-context-menu",
11
- "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.1.2/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.1.2/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
11
+ "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-alpha10/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-alpha10/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "close-on",
15
15
  "description": "Event name to listen for closing the context menu.",
16
16
  "value": {
17
17
  "type": [
18
- "string",
19
- "null",
20
- "undefined"
18
+ "string"
21
19
  ]
22
20
  }
23
21
  },
@@ -26,9 +24,7 @@
26
24
  "description": "Event name to listen for opening the context menu.",
27
25
  "value": {
28
26
  "type": [
29
- "string",
30
- "null",
31
- "undefined"
27
+ "string"
32
28
  ]
33
29
  }
34
30
  },
@@ -37,9 +33,7 @@
37
33
  "description": "Position of the overlay with respect to the target.\nSupported values: null, `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
38
34
  "value": {
39
35
  "type": [
40
- "string",
41
- "null",
42
- "undefined"
36
+ "string"
43
37
  ]
44
38
  }
45
39
  },
@@ -48,9 +42,7 @@
48
42
  "description": "CSS selector that can be used to target any child element\nof the context menu to listen for `openOn` events.",
49
43
  "value": {
50
44
  "type": [
51
- "string",
52
- "null",
53
- "undefined"
45
+ "string"
54
46
  ]
55
47
  }
56
48
  },
@@ -73,18 +65,16 @@
73
65
  "description": "Event name to listen for closing the context menu.",
74
66
  "value": {
75
67
  "type": [
76
- "string",
77
- "null",
78
- "undefined"
68
+ "string"
79
69
  ]
80
70
  }
81
71
  },
82
72
  {
83
73
  "name": "items",
84
- "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
74
+ "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
85
75
  "value": {
86
76
  "type": [
87
- "Array.<ContextMenuItem>",
77
+ "Array<ContextMenuItem>",
88
78
  "undefined"
89
79
  ]
90
80
  }
@@ -103,9 +93,7 @@
103
93
  "description": "Event name to listen for opening the context menu.",
104
94
  "value": {
105
95
  "type": [
106
- "string",
107
- "null",
108
- "undefined"
96
+ "string"
109
97
  ]
110
98
  }
111
99
  },
@@ -114,9 +102,7 @@
114
102
  "description": "Position of the overlay with respect to the target.\nSupported values: null, `top-start`, `top`, `top-end`,\n`bottom-start`, `bottom`, `bottom-end`, `start-top`,\n`start`, `start-bottom`, `end-top`, `end`, `end-bottom`.",
115
103
  "value": {
116
104
  "type": [
117
- "string",
118
- "null",
119
- "undefined"
105
+ "string"
120
106
  ]
121
107
  }
122
108
  },
@@ -135,14 +121,16 @@
135
121
  "description": "CSS selector that can be used to target any child element\nof the context menu to listen for `openOn` events.",
136
122
  "value": {
137
123
  "type": [
138
- "string",
139
- "null",
140
- "undefined"
124
+ "string"
141
125
  ]
142
126
  }
143
127
  }
144
128
  ],
145
129
  "events": [
130
+ {
131
+ "name": "close-all-menus",
132
+ "description": "Fired when all menus should close, e.g., after pressing Tab or on submenu close."
133
+ },
146
134
  {
147
135
  "name": "closed",
148
136
  "description": "Fired when the context menu is closed."
@@ -151,6 +139,10 @@
151
139
  "name": "item-selected",
152
140
  "description": "Fired when an item is selected when the context menu is populated using the `items` API."
153
141
  },
142
+ {
143
+ "name": "items-outside-click",
144
+ "description": "Fired when a click happens outside any open sub-menus."
145
+ },
154
146
  {
155
147
  "name": "opened-changed",
156
148
  "description": "Fired when the `opened` property changes."
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/context-menu",
4
- "version": "25.1.2",
4
+ "version": "25.2.0-alpha10",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,7 +16,7 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-context-menu",
19
- "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.1.2/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.1.2/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
19
+ "description": "`<vaadin-context-menu>` is a Web Component for creating context menus.\n\n### Items\n\nItems is a higher level convenience API for defining a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nWhen an item is selected, `<vaadin-context-menu>` dispatches an \"item-selected\" event\nwith the selected item as `event.detail.value` property.\nIf item does not have `keepOpen` property the menu will be closed.\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n\ncontextMenu.addEventListener('item-selected', e => {\n const item = e.detail.value;\n console.log(`${item.text} selected`);\n});\n```\n\n**NOTE:** when the `items` array is defined, the renderer cannot be used.\n\n#### Disabled menu items\n\nWhen disabled, menu items are rendered as \"dimmed\".\n\nBy default, disabled items are not focusable and don't react to hover.\nAs a result, they are hidden from assistive technologies, and it's not\npossible to show a tooltip to explain why they are disabled. This can\nbe addressed by enabling the feature flag `accessibleDisabledMenuItems`,\nwhich makes disabled items focusable and hoverable, while still\npreventing them from being activated:\n\n```js\n// Set before any context menu is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledMenuItems = true;\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```\n\n### Rendering\n\nThe content of the menu can be populated by using the renderer callback function.\n\nThe renderer function provides `root`, `contextMenu`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `contextMenu`. Before generating\nnew content, the renderer function should check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-context-menu id=\"contextMenu\">\n <p>This paragraph has a context menu.</p>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'Content of the selector: ' + context.target.textContent;\n};\n```\n\nYou can access the menu context inside the renderer using\n`context.target` and `context.detail`.\n\nRenderer is called on the opening of the context-menu and each time the related context is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\n\n### `vaadin-contextmenu` Gesture Event\n\n`vaadin-contextmenu` is a gesture event (a custom event),\nwhich is dispatched after either `contextmenu` or long touch events.\nThis enables support for both mouse and touch environments in a uniform way.\n\n`<vaadin-context-menu>` opens the menu overlay on the `vaadin-contextmenu`\nevent by default.\n\n### Menu Listener\n\nBy default, the `<vaadin-context-menu>` element listens for the menu opening\nevent on itself. In case if you do not want to wrap the target, you can listen for\nevents on an element outside the `<vaadin-context-menu>` by setting the\n`listenOn` property:\n\n```html\n<vaadin-context-menu id=\"contextMenu\"></vaadin-context-menu>\n\n<div id=\"menuListener\">The element that listens for the contextmenu event.</div>\n```\n```javascript\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.listenOn = document.querySelector('#menuListener');\n```\n\n### Filtering Menu Targets\n\nBy default, the listener element and all its descendants open the context\nmenu. You can filter the menu targets to a smaller set of elements inside\nthe listener element by setting the `selector` property.\n\nIn the following example, only the elements matching `.has-menu` will open the context menu:\n\n```html\n<vaadin-context-menu selector=\".has-menu\">\n <p class=\"has-menu\">This paragraph opens the context menu</p>\n <p>This paragraph does not open the context menu</p>\n</vaadin-context-menu>\n```\n\n### Menu Context\n\nThe following properties are available in the `context` argument:\n\n- `target` is the menu opening event target, which is the element that\nthe user has called the context menu for\n- `detail` is the menu opening event detail\n\nIn the following example, the menu item text is composed with the contents\nof the element that opened the menu:\n\n```html\n<vaadin-context-menu selector=\"li\" id=\"contextMenu\">\n <ul>\n <li>Foo</li>\n <li>Bar</li>\n <li>Baz</li>\n </ul>\n</vaadin-context-menu>\n```\n```js\nconst contextMenu = document.querySelector('#contextMenu');\ncontextMenu.renderer = (root, contextMenu, context) => {\n let listBox = root.firstElementChild;\n if (!listBox) {\n listBox = document.createElement('vaadin-list-box');\n root.appendChild(listBox);\n }\n\n let item = listBox.querySelector('vaadin-item');\n if (!item) {\n item = document.createElement('vaadin-item');\n listBox.appendChild(item);\n }\n item.textContent = 'The menu target: ' + context.target.textContent;\n};\n```\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description\n--------------------------------------|-------------\n`--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target\n`--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target\n`--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target\n`--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API the following internal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-alpha10/#/elements/vaadin-item).\n- `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.2.0-alpha10/#/elements/vaadin-list-box).\n\nThe `<vaadin-context-menu-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "name": ".items",
31
- "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```",
31
+ "description": "Defines a (hierarchical) menu structure for the component.\nIf a menu item has a non-empty `children` set, a sub-menu with the child items is opened\nnext to the parent menu on mouseover, tap or a right arrow keypress.\n\nThe items API can't be used together with a renderer!\n\n#### Example\n\n```javascript\ncontextMenu.items = [\n { text: 'Menu Item 1', theme: 'primary', className: 'first', children:\n [\n { text: 'Menu Item 1-1', checked: true, keepOpen: true },\n { text: 'Menu Item 1-2' }\n ]\n },\n { component: 'hr' },\n { text: 'Menu Item 2', children:\n [\n { text: 'Menu Item 2-1' },\n { text: 'Menu Item 2-2', disabled: true }\n ]\n },\n { text: 'Menu Item 3', disabled: true, className: 'last' }\n];\n```\n\n#### Item tooltips\n\nMenu items can have tooltips that are shown on hover and keyboard\nfocus. To enable them, add a slotted `<vaadin-tooltip>` element\nand set the `tooltip` property on each item that should have one:\n\n```html\n<vaadin-context-menu>\n <vaadin-tooltip slot=\"tooltip\"></vaadin-tooltip>\n</vaadin-context-menu>\n```",
32
32
  "value": {
33
33
  "kind": "expression"
34
34
  }
@@ -68,6 +68,13 @@
68
68
  "kind": "expression"
69
69
  }
70
70
  },
71
+ {
72
+ "name": "@close-all-menus",
73
+ "description": "Fired when all menus should close, e.g., after pressing Tab or on submenu close.",
74
+ "value": {
75
+ "kind": "expression"
76
+ }
77
+ },
71
78
  {
72
79
  "name": "@closed",
73
80
  "description": "Fired when the context menu is closed.",
@@ -82,6 +89,13 @@
82
89
  "kind": "expression"
83
90
  }
84
91
  },
92
+ {
93
+ "name": "@items-outside-click",
94
+ "description": "Fired when a click happens outside any open sub-menus.",
95
+ "value": {
96
+ "kind": "expression"
97
+ }
98
+ },
85
99
  {
86
100
  "name": "@opened-changed",
87
101
  "description": "Fired when the `opened` property changes.",