@vaadin/context-menu 25.0.0-alpha8 → 25.0.0-beta1

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 (29) hide show
  1. package/package.json +13 -16
  2. package/src/styles/vaadin-context-menu-item-base-styles.js +3 -3
  3. package/src/styles/vaadin-context-menu-overlay-base-styles.js +28 -1
  4. package/src/vaadin-context-menu-item.js +1 -1
  5. package/src/vaadin-context-menu-list-box.js +1 -1
  6. package/src/vaadin-context-menu-mixin.js +48 -76
  7. package/src/vaadin-context-menu-overlay.js +56 -1
  8. package/src/vaadin-context-menu.d.ts +48 -11
  9. package/src/vaadin-context-menu.js +98 -23
  10. package/src/vaadin-contextmenu-items-mixin.js +44 -30
  11. package/src/vaadin-menu-overlay-mixin.d.ts +0 -5
  12. package/src/vaadin-menu-overlay-mixin.js +23 -28
  13. package/vaadin-context-menu.js +1 -1
  14. package/web-types.json +10 -6
  15. package/web-types.lit.json +11 -4
  16. package/src/styles/vaadin-context-menu-item-core-styles.d.ts +0 -8
  17. package/src/styles/vaadin-context-menu-item-core-styles.js +0 -8
  18. package/src/styles/vaadin-context-menu-overlay-core-styles.d.ts +0 -8
  19. package/src/styles/vaadin-context-menu-overlay-core-styles.js +0 -9
  20. package/src/styles/vaadin-menu-overlay-core-styles.d.ts +0 -8
  21. package/src/styles/vaadin-menu-overlay-core-styles.js +0 -32
  22. package/theme/lumo/vaadin-context-menu-item-styles.d.ts +0 -6
  23. package/theme/lumo/vaadin-context-menu-item-styles.js +0 -45
  24. package/theme/lumo/vaadin-context-menu-list-box-styles.d.ts +0 -5
  25. package/theme/lumo/vaadin-context-menu-list-box-styles.js +0 -47
  26. package/theme/lumo/vaadin-context-menu-overlay-styles.d.ts +0 -4
  27. package/theme/lumo/vaadin-context-menu-overlay-styles.js +0 -35
  28. package/theme/lumo/vaadin-context-menu.d.ts +0 -4
  29. package/theme/lumo/vaadin-context-menu.js +0 -4
@@ -8,9 +8,9 @@ import './vaadin-context-menu-item.js';
8
8
  import './vaadin-context-menu-list-box.js';
9
9
  import './vaadin-context-menu-overlay.js';
10
10
  import { css, html, LitElement } from 'lit';
11
+ import { ifDefined } from 'lit/directives/if-defined.js';
11
12
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
12
13
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
13
- import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
14
14
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
15
15
  import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
16
16
  import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
@@ -175,18 +175,30 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
175
175
  *
176
176
  * ### Styling
177
177
  *
178
- * `<vaadin-context-menu>` uses `<vaadin-context-menu-overlay>` internal
179
- * themable component as the actual visible context menu overlay.
178
+ * The following shadow DOM parts are available for styling:
180
179
  *
181
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay)
182
- * documentation for `<vaadin-context-menu-overlay>` stylable parts.
180
+ * Part name | Description
181
+ * -----------------|-------------------------------------------
182
+ * `backdrop` | Backdrop of the overlay
183
+ * `overlay` | The overlay container
184
+ * `content` | The overlay content
185
+ *
186
+ * ### Custom CSS Properties
187
+ *
188
+ * The following custom CSS properties are available for styling:
189
+ *
190
+ * Custom CSS property | Description
191
+ * --------------------------------------|-------------
192
+ * `--vaadin-context-menu-offset-top` | Used as an offset when using `position` and the context menu is aligned vertically below the target
193
+ * `--vaadin-context-menu-offset-bottom` | Used as an offset when using `position` and the context menu is aligned vertically above the target
194
+ * `--vaadin-context-menu-offset-start` | Used as an offset when using `position` and the context menu is aligned horizontally after the target
195
+ * `--vaadin-context-menu-offset-end` | Used as an offset when using `position` and the context menu is aligned horizontally before the target
183
196
  *
184
197
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
185
198
  *
186
199
  * ### Internal components
187
200
  *
188
- * When using `items` API, in addition `<vaadin-context-menu-overlay>`, the following
189
- * internal components are themable:
201
+ * When using `items` API the following internal components are themable:
190
202
  *
191
203
  * - `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
192
204
  * - `<vaadin-context-menu-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
@@ -198,22 +210,17 @@ import { ContextMenuMixin } from './vaadin-context-menu-mixin.js';
198
210
  * ---------- |-------------
199
211
  * `expanded` | Expanded parent item.
200
212
  *
201
- * Note: the `theme` attribute value set on `<vaadin-context-menu>` is
202
- * propagated to the internal components listed above.
203
- *
204
213
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
205
214
  * @fires {CustomEvent} item-selected - Fired when an item is selected when the context menu is populated using the `items` API.
215
+ * @fires {CustomEvent} closed - Fired when the context menu is closed.
206
216
  *
207
217
  * @customElement
208
218
  * @extends HTMLElement
209
219
  * @mixes ElementMixin
210
220
  * @mixes ContextMenuMixin
211
- * @mixes OverlayClassMixin
212
221
  * @mixes ThemePropertyMixin
213
222
  */
214
- class ContextMenu extends ContextMenuMixin(
215
- OverlayClassMixin(ElementMixin(ThemePropertyMixin(PolylitMixin(LitElement)))),
216
- ) {
223
+ class ContextMenu extends ContextMenuMixin(ElementMixin(ThemePropertyMixin(PolylitMixin(LitElement)))) {
217
224
  static get is() {
218
225
  return 'vaadin-context-menu';
219
226
  }
@@ -230,19 +237,87 @@ class ContextMenu extends ContextMenuMixin(
230
237
  `;
231
238
  }
232
239
 
240
+ static get properties() {
241
+ return {
242
+ /**
243
+ * Position of the overlay with respect to the target.
244
+ * Supported values: null, `top-start`, `top`, `top-end`,
245
+ * `bottom-start`, `bottom`, `bottom-end`, `start-top`,
246
+ * `start`, `start-bottom`, `end-top`, `end`, `end-bottom`.
247
+ */
248
+ position: {
249
+ type: String,
250
+ },
251
+ };
252
+ }
253
+
233
254
  /** @protected */
234
255
  render() {
235
- return html`<slot id="slot"></slot>`;
256
+ const { _context: context, position } = this;
257
+
258
+ return html`
259
+ <slot id="slot"></slot>
260
+ <vaadin-context-menu-overlay
261
+ id="overlay"
262
+ .owner="${this}"
263
+ .opened="${this.opened}"
264
+ .model="${context}"
265
+ .modeless="${this._modeless}"
266
+ .renderer="${this.items ? this.__itemsRenderer : this.renderer}"
267
+ .position="${position}"
268
+ .positionTarget="${position ? context && context.target : this._positionTarget}"
269
+ .horizontalAlign="${this.__computeHorizontalAlign(position)}"
270
+ .verticalAlign="${this.__computeVerticalAlign(position)}"
271
+ ?no-horizontal-overlap="${this.__computeNoHorizontalOverlap(position)}"
272
+ ?no-vertical-overlap="${this.__computeNoVerticalOverlap(position)}"
273
+ .withBackdrop="${this._phone}"
274
+ ?phone="${this._phone}"
275
+ theme="${ifDefined(this._theme)}"
276
+ exportparts="backdrop, overlay, content"
277
+ @opened-changed="${this._onOverlayOpened}"
278
+ @vaadin-overlay-open="${this._onVaadinOverlayOpen}"
279
+ @vaadin-overlay-closed="${this._onVaadinOverlayClosed}"
280
+ >
281
+ <slot name="overlay"></slot>
282
+ <slot name="submenu" slot="submenu"></slot>
283
+ </vaadin-context-menu-overlay>
284
+ `;
236
285
  }
237
286
 
238
- /**
239
- * @protected
240
- * @override
241
- */
242
- createRenderRoot() {
243
- const root = super.createRenderRoot();
244
- root.appendChild(this._overlayElement);
245
- return root;
287
+ /** @private */
288
+ __computeHorizontalAlign(position) {
289
+ if (!position) {
290
+ return 'start';
291
+ }
292
+
293
+ return ['top-end', 'bottom-end', 'start-top', 'start', 'start-bottom'].includes(position) ? 'end' : 'start';
294
+ }
295
+
296
+ /** @private */
297
+ __computeNoHorizontalOverlap(position) {
298
+ if (!position) {
299
+ return !!this._positionTarget;
300
+ }
301
+
302
+ return ['start-top', 'start', 'start-bottom', 'end-top', 'end', 'end-bottom'].includes(position);
303
+ }
304
+
305
+ /** @private */
306
+ __computeNoVerticalOverlap(position) {
307
+ if (!position) {
308
+ return false;
309
+ }
310
+
311
+ return ['top-start', 'top-end', 'top', 'bottom-start', 'bottom', 'bottom-end'].includes(position);
312
+ }
313
+
314
+ /** @private */
315
+ __computeVerticalAlign(position) {
316
+ if (!position) {
317
+ return 'top';
318
+ }
319
+
320
+ return ['top-start', 'top-end', 'top', 'start-bottom', 'end-bottom'].includes(position) ? 'bottom' : 'top';
246
321
  }
247
322
 
248
323
  /**
@@ -16,14 +16,14 @@ export const ItemsMixin = (superClass) =>
16
16
  * @typedef ContextMenuItem
17
17
  * @type {object}
18
18
  * @property {string} text - Text to be set as the menu item component's textContent
19
- * @property {union: string | object} component - The component to represent the item.
19
+ * @property {string | HTMLElement} component - The component to represent the item.
20
20
  * Either a tagName or an element instance. Defaults to "vaadin-context-menu-item".
21
21
  * @property {boolean} disabled - If true, the item is disabled and cannot be selected
22
22
  * @property {boolean} checked - If true, the item shows a checkmark next to it
23
23
  * @property {boolean} keepOpen - If true, the menu will not be closed on item selection
24
24
  * @property {string} className - A space-delimited list of CSS class names to be set on the menu item component.
25
- * @property {union: string | string[]} theme - If set, sets the given theme(s) as an attribute to the menu item component, overriding any theme set on the context menu.
26
- * @property {MenuItem[]} children - Array of child menu items
25
+ * @property {string | string[]} theme - If set, sets the given theme(s) as an attribute to the menu item component, overriding any theme set on the context menu.
26
+ * @property {ContextMenuItem[]} children - Array of child menu items
27
27
  */
28
28
 
29
29
  /**
@@ -60,6 +60,12 @@ export const ItemsMixin = (superClass) =>
60
60
  type: Array,
61
61
  sync: true,
62
62
  },
63
+
64
+ /** @protected */
65
+ _positionTarget: {
66
+ type: Object,
67
+ sync: true,
68
+ },
63
69
  };
64
70
  }
65
71
 
@@ -116,10 +122,10 @@ export const ItemsMixin = (superClass) =>
116
122
  /** @protected */
117
123
  __forwardFocus() {
118
124
  const overlay = this._overlayElement;
119
- const child = overlay.getFirstChild();
125
+ const child = overlay._contentRoot.firstElementChild;
120
126
  // If parent item is not focused, do not focus submenu
121
127
  if (overlay.parentOverlay) {
122
- const parent = overlay.parentOverlay.querySelector('[expanded]');
128
+ const parent = overlay.parentOverlay._contentRoot.querySelector('[expanded]');
123
129
  if (parent && parent.hasAttribute('focused') && child) {
124
130
  child.focus();
125
131
  } else {
@@ -131,14 +137,12 @@ export const ItemsMixin = (superClass) =>
131
137
  }
132
138
 
133
139
  /** @private */
134
- __openSubMenu(subMenu, itemElement, overlayClass) {
140
+ __openSubMenu(subMenu, itemElement) {
141
+ // Update sub-menu items and position target
135
142
  this.__updateSubMenuForItem(subMenu, itemElement);
136
- subMenu.overlayClass = overlayClass;
137
143
 
138
144
  const parent = this._overlayElement;
139
-
140
145
  const subMenuOverlay = subMenu._overlayElement;
141
- subMenuOverlay.noHorizontalOverlap = true;
142
146
  // Store the reference parent overlay
143
147
  subMenuOverlay._setParentOverlay(parent);
144
148
 
@@ -165,7 +169,8 @@ export const ItemsMixin = (superClass) =>
165
169
  __updateSubMenuForItem(subMenu, itemElement) {
166
170
  subMenu.items = itemElement._item.children;
167
171
  subMenu.listenOn = itemElement;
168
- subMenu._overlayElement.positionTarget = itemElement;
172
+ subMenu._positionTarget = itemElement;
173
+ subMenu._overlayElement.requestContentUpdate();
169
174
  }
170
175
 
171
176
  /**
@@ -253,10 +258,20 @@ export const ItemsMixin = (superClass) =>
253
258
  // Open a submenu on click event when a touch device is used.
254
259
  // On desktop, a submenu opens on hover.
255
260
  overlay.addEventListener(isTouch ? 'click' : 'mouseover', (event) => {
261
+ // Ignore events from the submenus
262
+ if (event.composedPath().includes(this._subMenu)) {
263
+ return;
264
+ }
265
+
256
266
  this.__showSubMenu(event);
257
267
  });
258
268
 
259
269
  overlay.addEventListener('keydown', (event) => {
270
+ // Ignore events from the submenus
271
+ if (event.composedPath().includes(this._subMenu)) {
272
+ return;
273
+ }
274
+
260
275
  const { key } = event;
261
276
  const isRTL = this.__isRTL;
262
277
 
@@ -288,10 +303,6 @@ export const ItemsMixin = (superClass) =>
288
303
  subMenu._modeless = true;
289
304
  subMenu.openOn = 'opensubmenu';
290
305
 
291
- // Sub-menu doesn't have a target to wrap,
292
- // so there is no need to keep it visible.
293
- subMenu.setAttribute('hidden', '');
294
-
295
306
  // Close sub-menu when the parent menu closes.
296
307
  this.addEventListener('opened-changed', (event) => {
297
308
  if (!event.detail.value) {
@@ -361,27 +372,33 @@ export const ItemsMixin = (superClass) =>
361
372
  }
362
373
 
363
374
  const subMenu = this._subMenu;
375
+ const expandedItem = this._listBox.querySelector('[expanded]');
364
376
 
365
- if (item) {
377
+ if (item && item !== expandedItem) {
366
378
  const { children } = item._item;
367
379
 
368
380
  // Check if the sub-menu was focused before closing it.
369
- const child = subMenu._overlayElement.getFirstChild();
381
+ const child = subMenu._overlayElement._contentRoot.firstElementChild;
370
382
  const isSubmenuFocused = child && child.focused;
371
383
 
372
- if (subMenu.items !== children) {
384
+ // Mark previously expanded item as collapsed
385
+ if (expandedItem) {
386
+ this.__updateExpanded(expandedItem, false);
387
+ }
388
+
389
+ // Close sub-menu if there are no children for the new item
390
+ if (!children || !children.length) {
373
391
  subMenu.close();
374
392
  }
393
+
375
394
  if (!this.opened) {
376
395
  return;
377
396
  }
378
397
 
379
398
  if (children && children.length) {
399
+ // Open or update the submenu if the new item has children
380
400
  this.__updateExpanded(item, true);
381
-
382
- // Forward parent overlay class
383
- const { overlayClass } = this;
384
- this.__openSubMenu(subMenu, item, overlayClass);
401
+ this.__openSubMenu(subMenu, item);
385
402
  } else if (isSubmenuFocused) {
386
403
  // If the sub-menu item was focused, focus its parent item.
387
404
  subMenu.listenOn.focus();
@@ -394,27 +411,23 @@ export const ItemsMixin = (superClass) =>
394
411
 
395
412
  /** @protected */
396
413
  __getListBox() {
397
- return this._overlayElement.querySelector(`${this._tagNamePrefix}-list-box`);
414
+ return this._overlayElement._contentRoot.querySelector(`${this._tagNamePrefix}-list-box`);
398
415
  }
399
416
 
400
417
  /**
401
418
  * @param {!HTMLElement} root
402
419
  * @param {!ContextMenu} menu
403
- * @param {!ContextMenuRendererContext} context
404
420
  * @protected
405
421
  */
406
422
  __itemsRenderer(root, menu) {
407
423
  this.__initMenu(root, menu);
408
424
 
409
- const subMenu = root.querySelector(this.constructor.is);
410
- subMenu.closeOn = menu.closeOn;
411
-
412
- const listBox = this.__getListBox();
413
- listBox.innerHTML = '';
425
+ this._subMenu.closeOn = menu.closeOn;
426
+ this._listBox.innerHTML = '';
414
427
 
415
428
  menu.items.forEach((item) => {
416
429
  const component = this.__createComponent(item);
417
- listBox.appendChild(component);
430
+ this._listBox.appendChild(component);
418
431
  });
419
432
  }
420
433
 
@@ -455,8 +468,9 @@ export const ItemsMixin = (superClass) =>
455
468
  root.appendChild(listBox);
456
469
 
457
470
  const subMenu = this.__initSubMenu();
471
+ subMenu.slot = 'submenu';
458
472
  this._subMenu = subMenu;
459
- root.appendChild(subMenu);
473
+ this.appendChild(subMenu);
460
474
 
461
475
  requestAnimationFrame(() => {
462
476
  this.__openListenerActive = true;
@@ -18,9 +18,4 @@ export declare class MenuOverlayMixinClass {
18
18
  * Returns the adjusted boundaries of the overlay.
19
19
  */
20
20
  getBoundaries(): { xMax: number; xMin: number; yMax: number };
21
-
22
- /**
23
- * Returns the first element in the overlay content.
24
- */
25
- getFirstChild(): HTMLElement;
26
21
  }
@@ -3,7 +3,6 @@
3
3
  * Copyright (c) 2016 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { getClosestElement } from '@vaadin/component-base/src/dom-utils.js';
7
6
  import { OverlayFocusMixin } from '@vaadin/overlay/src/vaadin-overlay-focus-mixin.js';
8
7
  import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
9
8
 
@@ -37,6 +36,23 @@ export const MenuOverlayMixin = (superClass) =>
37
36
  return ['_themeChanged(_theme)'];
38
37
  }
39
38
 
39
+ /**
40
+ * Override method from OverlayFocusMixin to use slotted div as the content root.
41
+ * @protected
42
+ * @override
43
+ */
44
+ get _contentRoot() {
45
+ if (!this.__savedRoot) {
46
+ const root = document.createElement('div');
47
+ root.setAttribute('slot', 'overlay');
48
+ root.style.display = 'contents';
49
+ this.owner.appendChild(root);
50
+ this.__savedRoot = root;
51
+ }
52
+
53
+ return this.__savedRoot;
54
+ }
55
+
40
56
  /** @protected */
41
57
  ready() {
42
58
  super.ready();
@@ -45,7 +61,7 @@ export const MenuOverlayMixin = (superClass) =>
45
61
 
46
62
  this.addEventListener('keydown', (e) => {
47
63
  if (!e.defaultPrevented && e.composedPath()[0] === this.$.overlay && [38, 40].indexOf(e.keyCode) > -1) {
48
- const child = this.getFirstChild();
64
+ const child = this._contentRoot.firstElementChild;
49
65
  if (child && Array.isArray(child.items) && child.items.length) {
50
66
  e.preventDefault();
51
67
  if (e.keyCode === 38) {
@@ -58,15 +74,6 @@ export const MenuOverlayMixin = (superClass) =>
58
74
  });
59
75
  }
60
76
 
61
- /**
62
- * Returns the first element in the overlay content.
63
- *
64
- * @returns {HTMLElement}
65
- */
66
- getFirstChild() {
67
- return this.querySelector(':not(style):not(slot)');
68
- }
69
-
70
77
  /** @private */
71
78
  _themeChanged() {
72
79
  this.close();
@@ -106,7 +113,7 @@ export const MenuOverlayMixin = (superClass) =>
106
113
  _updatePosition() {
107
114
  super._updatePosition();
108
115
 
109
- if (this.positionTarget && this.parentOverlay) {
116
+ if (this.positionTarget && this.parentOverlay && this.opened) {
110
117
  // This overlay is positioned by a parent menu item,
111
118
  // adjust the position by the overlay content paddings
112
119
  const content = this.$.content;
@@ -149,9 +156,9 @@ export const MenuOverlayMixin = (superClass) =>
149
156
  }
150
157
 
151
158
  /**
152
- * Override method inherited from `OverlayFocusMixin` to return
153
- * true if the overlay contains the given node, including
154
- * those within descendant menu overlays.
159
+ * Override method inherited from `OverlayFocusMixin` to check if the
160
+ * node is contained within the overlay's owner element (the menu),
161
+ * where all content (overlay content, sub-menus, etc.) is slotted.
155
162
  *
156
163
  * @protected
157
164
  * @override
@@ -159,18 +166,6 @@ export const MenuOverlayMixin = (superClass) =>
159
166
  * @return {boolean}
160
167
  */
161
168
  _deepContains(node) {
162
- // Find the closest menu overlay for the given node.
163
- let overlay = getClosestElement(this.localName, node);
164
- while (overlay) {
165
- if (overlay === this) {
166
- // The node is inside a descendant menu overlay.
167
- return true;
168
- }
169
-
170
- // Traverse the overlay hierarchy to check parent overlays.
171
- overlay = overlay.parentOverlay;
172
- }
173
-
174
- return false;
169
+ return this.owner.contains(node);
175
170
  }
176
171
  };
@@ -1,2 +1,2 @@
1
- import './theme/lumo/vaadin-context-menu.js';
1
+ import './src/vaadin-context-menu.js';
2
2
  export * from './src/vaadin-context-menu.js';
package/web-types.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/context-menu",
4
- "version": "25.0.0-alpha8",
4
+ "version": "25.0.0-beta1",
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\n`<vaadin-context-menu>` uses `<vaadin-context-menu-overlay>` internal\nthemable component as the actual visible context menu overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-overlay)\ndocumentation for `<vaadin-context-menu-overlay>` stylable parts.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API, in addition `<vaadin-context-menu-overlay>`, the following\ninternal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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.0.0-alpha8/#/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.\n\nNote: the `theme` attribute value set on `<vaadin-context-menu>` is\npropagated to the internal components listed above.",
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.0.0-beta1/#/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.0.0-beta1/#/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": "selector",
@@ -40,8 +40,8 @@
40
40
  }
41
41
  },
42
42
  {
43
- "name": "overlay-class",
44
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
43
+ "name": "position",
44
+ "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`.",
45
45
  "value": {
46
46
  "type": [
47
47
  "string",
@@ -123,8 +123,8 @@
123
123
  }
124
124
  },
125
125
  {
126
- "name": "overlayClass",
127
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
126
+ "name": "position",
127
+ "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`.",
128
128
  "value": {
129
129
  "type": [
130
130
  "string",
@@ -135,6 +135,10 @@
135
135
  }
136
136
  ],
137
137
  "events": [
138
+ {
139
+ "name": "closed",
140
+ "description": "Fired when the context menu is closed."
141
+ },
138
142
  {
139
143
  "name": "item-selected",
140
144
  "description": "Fired when an item is selected when the context menu is populated using the `items` API."
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/context-menu",
4
- "version": "25.0.0-alpha8",
4
+ "version": "25.0.0-beta1",
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\n`<vaadin-context-menu>` uses `<vaadin-context-menu-overlay>` internal\nthemable component as the actual visible context menu overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/elements/vaadin-overlay)\ndocumentation for `<vaadin-context-menu-overlay>` stylable parts.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nWhen using `items` API, in addition `<vaadin-context-menu-overlay>`, the following\ninternal components are themable:\n\n- `<vaadin-context-menu-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha8/#/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.0.0-alpha8/#/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.\n\nNote: the `theme` attribute value set on `<vaadin-context-menu>` is\npropagated to the internal components listed above.",
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.0.0-beta1/#/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.0.0-beta1/#/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
  {
@@ -62,8 +62,15 @@
62
62
  }
63
63
  },
64
64
  {
65
- "name": ".overlayClass",
66
- "description": "A space-delimited list of CSS class names to set on the overlay element.\nThis property does not affect other CSS class names set manually via JS.\n\nNote, if the CSS class name was set with this property, clearing it will\nremove it from the overlay, even if the same class name was also added\nmanually, e.g. by using `classList.add()` in the `renderer` function.",
65
+ "name": ".position",
66
+ "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`.",
67
+ "value": {
68
+ "kind": "expression"
69
+ }
70
+ },
71
+ {
72
+ "name": "@closed",
73
+ "description": "Fired when the context menu is closed.",
67
74
  "value": {
68
75
  "kind": "expression"
69
76
  }
@@ -1,8 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2016 - 2025 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
- import type { CSSResult } from 'lit';
7
-
8
- export const contextMenuItemStyles: CSSResult;
@@ -1,8 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2016 - 2025 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
- import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-core-styles.js';
7
-
8
- export const contextMenuItemStyles = [itemStyles];
@@ -1,8 +0,0 @@
1
- /**
2
- * @license
3
- * Copyright (c) 2016 - 2025 Vaadin Ltd.
4
- * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
- */
6
- import type { CSSResult } from 'lit';
7
-
8
- export const contextMenuOverlayStyles: CSSResult;