Skip to content

Commit

Permalink
docs: custom item data for context menu and menu bar
Browse files Browse the repository at this point in the history
  • Loading branch information
sissbruecker committed Feb 28, 2025
1 parent ed987ef commit ece0f8b
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 1 deletion.
29 changes: 29 additions & 0 deletions articles/components/context-menu/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,35 @@ include::{root}/frontend/demo/component/contextmenu/react/context-menu-left-clic
endif::[]
--


== Custom Item Data

Context Menu allows you to attach custom data to menu items. This can be useful for storing additional information about the item, such as an item type or a value. The data can then be used to trigger actions when an item is selected.

[.example]
--
ifdef::lit[]
[source,typescript]
----
include::{root}/frontend/demo/component/contextmenu/context-menu-custom-item-data.ts[render,tags=snippet,indent=0,group=Lit]
----
endif::[]

ifdef::flow[]
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/contextmenu/ContextMenuCustomItemData.java[render,tags=snippet,indent=0,group=Flow]
----
endif::[]

ifdef::react[]
[source,tsx]
----
include::{root}/frontend/demo/component/contextmenu/react/context-menu-custom-item-data.tsx[render,tags=snippet,indent=0,group=React]
----
endif::[]
--

== Best Practices

Context Menu is used to provide shortcuts to the user.
Expand Down
30 changes: 29 additions & 1 deletion articles/components/menu-bar/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,35 @@ endif::[]
ifdef::react[]
[source,tsx]
----
include::{root}/frontend/demo/component/menubar/react/menu-bar-internationalization.tsx[render,tags=snippet,indent=0,group=React]
include::{root}/frontend/demo/component/menubar/react/menu-bar-internationalization.tsx[tags=snippet,indent=0,group=React]
----
endif::[]
--

== Custom Item Data

Menu Bar allows you to attach custom data to menu items. This can be useful for storing additional information about the item, such as an item type or a value. The data can then be used to trigger actions when an item is selected.

[.example]
--
ifdef::lit[]
[source,typescript]
----
include::{root}/frontend/demo/component/menubar/menu-bar-custom-item-data.ts[render,tags=snippet,indent=0,group=Lit]
----
endif::[]

ifdef::flow[]
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/menubar/MenuBarCustomItemData.java[render,tags=snippet,indent=0,group=Flow]
----
endif::[]

ifdef::react[]
[source,tsx]
----
include::{root}/frontend/demo/component/menubar/react/menu-bar-custom-item-data.tsx[render,tags=snippet,indent=0,group=React]
----
endif::[]
--
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'Frontend/demo/init'; // hidden-source-line
import '@vaadin/context-menu';
import { html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import type { ContextMenuItem, ContextMenuItemSelectedEvent } from '@vaadin/context-menu';
import { applyTheme } from 'Frontend/generated/theme';

@customElement('context-menu-custom-item-data')
export class Example extends LitElement {
protected override createRenderRoot() {
const root = super.createRenderRoot();
// Apply custom theme (only supported if your app uses one)
applyTheme(root);
return root;
}

// tag::snippet[]
@state()
private items: Array<ContextMenuItem<{ value: string }>> = [
{
text: 'Copy as plain text',
value:
'Context Menu\n\nContext Menu is a component that you can attach to any component to display a context menu.',
},
{
text: 'Copy as HTML',
value:
'<h1>Context Menu</h1><p>Context Menu is a component that you can attach to any component to display a context menu.</p>',
},
{
text: 'Copy as Markdown',
value:
'# Context Menu\n\nContext Menu is a component that you can attach to any component to display a context menu.',
},
];

protected override render() {
return html`
<vaadin-context-menu .items="${this.items}" @item-selected="${this.itemSelected}">
<h1>Context Menu</h1>
<p>
Context Menu is a component that you can attach to any component to display a context
menu.
</p>
</vaadin-context-menu>
`;
}

itemSelected(e: ContextMenuItemSelectedEvent<ContextMenuItem<{ value?: string }>>) {
const value = e.detail.value.value;
if (value) {
navigator.clipboard.writeText(value);
}
}

// end::snippet[]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { reactExample } from 'Frontend/demo/react-example'; // hidden-source-line
import React from 'react';
import { ContextMenu, type ContextMenuItem } from '@vaadin/react-components';

function Example() {
// tag::snippet[]
const items: Array<ContextMenuItem<{ value: string }>> = [
{
text: 'Copy as plain text',
value:
'Context Menu\n\nContext Menu is a component that you can attach to any component to display a context menu.',
},
{
text: 'Copy as HTML',
value:
'<h1>Context Menu</h1><p>Context Menu is a component that you can attach to any component to display a context menu.</p>',
},
{
text: 'Copy as Markdown',
value:
'# Context Menu\n\nContext Menu is a component that you can attach to any component to display a context menu.',
},
];

return (
<ContextMenu
items={items}
onItemSelected={(event) => {
const value = event.detail.value.value;
if (value) {
navigator.clipboard.writeText(value);
}
}}
>
<h1>Context Menu</h1>
<p>
Context Menu is a component that you can attach to any component to display a context menu.
</p>
</ContextMenu>
);
// end::snippet[]
}

export default reactExample(Example); // hidden-source-line
58 changes: 58 additions & 0 deletions frontend/demo/component/menubar/menu-bar-custom-item-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'Frontend/demo/init'; // hidden-source-line
import '@vaadin/menu-bar';
import { html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import type { MenuBarItem, MenuBarItemSelectedEvent } from '@vaadin/menu-bar';
import { applyTheme } from 'Frontend/generated/theme';

@customElement('menu-bar-custom-item-data')
export class Example extends LitElement {
protected override createRenderRoot() {
const root = super.createRenderRoot();
// Apply custom theme (only supported if your app uses one)
applyTheme(root);
return root;
}

// tag::snippet[]
@state()
private items: Array<MenuBarItem<{ value?: string }>> = [
{
text: 'Copy',
children: [
{
text: 'Copy as plain text',
value:
'Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.',
},
{
text: 'Copy as HTML',
value:
'<h1>Menu Bar</h1><p>Menu Bar is a horizontal button bar with hierarchical drop-down menus.</p>',
},
{
text: 'Copy as Markdown',
value:
'# Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.',
},
],
},
];

protected override render() {
return html`
<vaadin-menu-bar
.items="${this.items}"
@item-selected="${this.itemSelected}"
></vaadin-menu-bar>
`;
}

itemSelected(e: MenuBarItemSelectedEvent<MenuBarItem<{ value?: string }>>) {
const value = e.detail.value.value;
if (value) {
navigator.clipboard.writeText(value);
}
}
// end::snippet[]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { reactExample } from 'Frontend/demo/react-example'; // hidden-source-line
import React from 'react';
import { MenuBar, type MenuBarItem } from '@vaadin/react-components';

function Example() {
// tag::snippet[]
const items: Array<MenuBarItem<{ value?: string }>> = [
{
text: 'Copy',
children: [
{
text: 'Copy as plain text',
value:
'Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.',
},
{
text: 'Copy as HTML',
value:
'<h1>Menu Bar</h1><p>Menu Bar is a horizontal button bar with hierarchical drop-down menus.</p>',
},
{
text: 'Copy as Markdown',
value:
'# Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.',
},
],
},
];

return (
<MenuBar
items={items}
onItemSelected={(event) => {
const value = event.detail.value.value;
if (value) {
navigator.clipboard.writeText(value);
}
}}
/>
);
// end::snippet[]
}

export default reactExample(Example); // hidden-source-line
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.vaadin.demo.component.contextmenu;

import com.vaadin.demo.DemoExporter; // hidden-source-line
import com.vaadin.flow.component.contextmenu.ContextMenu;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H1;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.router.Route;

@Route("context-menu-custom-item-data")
public class ContextMenuCustomItemData extends Div {

public ContextMenuCustomItemData() {
// tag::snippet[]
Div wrapper = new Div(
new H1("Context Menu"),
new Paragraph("Menu Bar is a horizontal button bar with hierarchical drop-down menus.")
);

ContextMenu menu = new ContextMenu();
menu.setTarget(wrapper);

menu.addItem("Copy as plain text", event -> {
// Provide a custom value by adding a click listener that holds a reference to that value
String value = "Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.";
copyToClipboard(value);
});

menu.addItem("Copy as HTML", event -> {
String value = "<h1>Menu Bar</h1><p>Menu Bar is a horizontal button bar with hierarchical drop-down menus.</p>";
copyToClipboard(value);
});

menu.addItem("Copy as Markdown", event -> {
String value = "# Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.";
copyToClipboard(value);
});
// end::snippet[]

add(wrapper);
}

private void copyToClipboard(String value) {
getUI().ifPresent(ui -> ui.getPage().executeJs("window.navigator.clipboard.writeText($0);", value));
}

public static class Exporter extends DemoExporter<ContextMenuCustomItemData> { // hidden-source-line
} // hidden-source-line
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.vaadin.demo.component.menubar;

import com.vaadin.demo.DemoExporter; // hidden-source-line
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.contextmenu.SubMenu;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.router.Route;

@Route("menu-bar-custom-item-data")
public class MenuBarCustomItemData extends Div {

public MenuBarCustomItemData() {
// tag::snippet[]
MenuBar menuBar = new MenuBar();
MenuItem copy = menuBar.addItem("Copy");
SubMenu copySubMenu = copy.getSubMenu();

copySubMenu.addItem("Copy as plain text", event -> {
// Provide a custom value by adding a click listener that holds a reference to that value
String value = "Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.";
copyToClipboard(value);
});

copySubMenu.addItem("Copy as HTML", event -> {
String value = "<h1>Menu Bar</h1><p>Menu Bar is a horizontal button bar with hierarchical drop-down menus.</p>";
copyToClipboard(value);
});

copySubMenu.addItem("Copy as Markdown", event -> {
String value = "# Menu Bar\n\nMenu Bar is a horizontal button bar with hierarchical drop-down menus.";
copyToClipboard(value);
});
// end::snippet[]

add(menuBar);
}

private void copyToClipboard(String value) {
getUI().ifPresent(ui -> ui.getPage().executeJs("window.navigator.clipboard.writeText($0);", value));
}

public static class Exporter extends DemoExporter<MenuBarCustomItemData> { // hidden-source-line
} // hidden-source-line
}

0 comments on commit ece0f8b

Please sign in to comment.