Developer Programs

Learn

Docs

Context Menu

Components > Content Layout > Context Menu
Use this component to...
Present a popup menu with options scoped to one element in your content

Overview

Some actions in a view apply to the view as a whole. We place the buttons for those actions in the function toolbar. Other actions apply only to elements within a specific display block, so we place the buttons for those actions in the display block toolbar. Doing this helps scope each action so the user understands which elements in the view will be affected when they take that action.

But some actions apply to an individual element within the view. The context menu is a convenient way to provide a list of options scoped to a component, an area of the interface, or piece of data. This can help save time for the user since only the options specific to that element are displayed close to the element, making them easier to find and reach.

Context menus display on desktop when the user right-clicks it with a two-button mouse or presses a two-finger click on a trackpad. We currently do not support context menus on mobile devices.

While context menus can be useful, they are not discoverable. The user can’t easily tell which elements in your view have a context menu and which don’t without actually testing them out (or through documentation or training). Because of this, a context menu should not be the only way the user can perform any action; these actions should ideally be available through other means too.

Context menus should only include options related to the element the user is interacting with. List these items in order of importance to the user, with more frequently used options listed first.

Keep context menus manageable by including no more than about 10 options, otherwise you can overwhelm the user with too many choices.

Context menus support multiple levels, however you should try to keep context menus 1 level deep and should never go more than 2 levels deep, since manipulating fly-out menus can be tricky.

If you need to attach a context menu to a button, consider using a dropdown button instead. The arrow in the dropdown button makes the dropdown menu more discoverable to users than a context menu.

Do not attach a context menu to any element that already displays a dropdown menu, such as a dropdown button.

Scope each context menu so that it doesn’t overreach its bounds.

  • Add each context menu at the smallest level of scope.
  • Never attach a context menu anywhere outside of a view’s function content. You typically will not attach a context anywhere menu outside of a display block.
  • Remember that attaching a context menu to any element for which the browser displays its own context menu — anchors, inputs, text blocks, etc — will override the browser’s built-in context menu for the element and for any children of the element.
  • Test each context menu at all levels of the view to verify that it doesn’t overreach in scope or hide a browser-specific menu that may be needed (e.g. for an anchor element).
Context menu that displays when you right-click the display block background
Context menu that displays when you right-click the display block background
A second context menu displays when you right-click an element in the templated list
A second context menu displays when you right-click an element in the templated list

Development

Web component development

Component reference

p-contextmenu
p-contextmenu
Module: ContextMenuModule - Package: primeng
⚠️ This component requires the use of Angular and will not work in non-Angular applications.

Displays a list of options scoped to a component, an area of the interface, or piece of data

View the p-contextmenu reference doc

If you're adding PrimeNG to your solution for the first time, reference their setup documentation. It's important to note that the inclusion of the nova-light theme css is not necessary to work with Responsive UI. Styling for the PrimeNG components is provided by Responsive UI's theming.

Implementation

In this example, we’re going to set up two context menus in a view: one for a display block and the other for items in a templated list in the same display block.

Begin by importing the ContextMenuModule module into your application.

Import the module
// import into app.module
import { ContextMenuModule } from 'primeng/contextmenu';

@NgModule({
    imports: [
        ...
        ContextMenuModule,
        ...
    ]
})

export class AppModule(){}

Add the following imports in the view’s controller.

Imports in controller
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { ContextMenu } from 'primeng/contextmenu';

Next declare variables for the two context menus.

Variables for the context menus
public displayBlockMenuItems: MenuItem[];
public templateMenuItems: MenuItem[];

Then define the options for each context menu in ngOnInit(). We do not add icons for these context menu items; the enterprise theming would hide these anyways.

Defining the context menu options
ngOnInit() {
    this.displayBlockMenuItems = [
        {
            label: 'Link Item',
            items: [
                {label: 'RouterLink Item', routerLink: ['/Home']},
                {label: 'URL Item', url: 'http://www.google.com'}
            ]
        },
        {
            label: 'Event Item',
            items: [
                {label: 'Click Event Item', command: (event) => {
                    alert('Context Menu Item Clicked');
                }}
            ]
        },
        {
            separator: true,
        },
        {
            label: 'Menu Item',
            routerLink: ['/Home']
        },
        {
            label: 'Disabled Item',
            disabled: true,
            command: (event) => {
                alert('Context Menu Item Clicked');
            }
        }
    ];

    this.templateMenuItems = [
        {
            label: 'Update Account',
            items: [
                {label: 'Save Account', command: (event) => {
                    alert('Saved ' + this.selectedAccountType + ' Account #' + this.selectedAccountNumber);
                }},
                {label: 'Delete Account', command: (event) => {
                    alert('Deleted ' + this.selectedAccountType + ' Account #' + this.selectedAccountNumber);
                }}
            ]
        },
        {
            separator: true,
        },
        {label: 'Router Link Item', routerLink: ['/Home']},
        {label: 'URL Item', url: 'http://www.google.com'}
    ];
}

In the HTML below, we have a display block that contains two paragraphs of intro text, a templated list, and two context menus.

We set up the context menu for the display block by defining a p-contextmenu whose model is the display block menu definition we set up in the controller. We then attach that context menu to the display block using the contextmenu method on the jha-display-block, which calls the “onBlockContextMenuClick” method in the controller, sending the event and the context menu associated with it. (Don’t use the target attribute in the p-contextmenu to attach the context menu to the display block; p-contextmenu doesn’t allow you to target custom components directly.)

We set up the context menu for each templated item by defining a p-contextmenu within the template, whose model is the template menu definition we set up in the controller. We then attach that context menu to each templated item using the contextmenu method on the template, which in turn calls the “onAccountContextMenuClick” method in the controller. This method call passes information from the current templated item to the controller (account name and account type); passing info from the template to the context menu method is a critical part of using context menus in templated lists. We don’t need to call the “show” method for the appropriate context menu because we wired up the connection between the context menu and the templated item using the target attribute in the p-contextmenu.

We nest each templated item within a separate div here because you cannot attach a p-contextmenu directly to any element that uses *ngFor.
Defining the context menu options
<rui-display-block (contextmenu)="onBlockContextMenuClick($event, displayBlockContextMenu);$event.stopPropagation()">
    <p>
        This page contains two context menus. Right-click inside the display block content to see one context menu.
    </p>

    <p>
        Right-click inside each template below to see a context menu for that templated item.
    </p>

    <div id="account-container-wrapper">
        <div *ngFor="let account of accountList" class="rui-template account-container">
            <div class="account-wrapper" #templateList (contextmenu)="onAccountContextMenuClick($event, account.name, account.type)">
                <rui-icon [iconType]="account.iconType" jhaSize="28px" class="account-icon"></rui-icon>
                <div class="account-info">
                    <div class="rui-bright-text-label">Account {{account.name}}</div>
                    <div class="rui-regular-text-label">{{account.type}}</div>
                </div>
                <p class="rui-regular-text-label account-balance">
                    {{account.balance | jhaCurrency}}
                </p>
            </div>

            <p-contextMenu #templateContextMenu [target]="templateList" [model]="templateMenuItems" appendTo="body">
            </p-contextMenu>
        </div>
    </div>

    <p-contextMenu #displayBlockContextMenu [model]="displayBlockMenuItems" appendTo="body"></p-contextMenu>

</rui-display-block>

Finally, set up the onBlockContextMenuClick and onAccountContextMenuClick methods in the controller. The display block context menu is more complex in this case because triggering the templated item menu will also trigger the display block menu (since the template list is a child of the display block). So in this example, if the onBlockContextMenuClick is called, we first see if the target was the templated item list, and if so, we don’t show the display block menu.

Defining the click event handlers
public onBlockContextMenuClick(event: Event, contextMenu: any): void {
    let templateWrapper = document.getElementById('account-container-wrapper');
    let target = event.target as HTMLElement
    if (target !== templateWrapper && !templateWrapper.contains(target)) {
        contextMenu.show(event);
    } else {
        contextMenu.hide();
    }
}

public onAccountContextMenuClick(event: Event, accountNumber: string, accountType: string): void {
    this.selectedAccountNumber = accountNumber;
    this.selectedAccountType = accountType;
}

Angular component development

Component reference

p-contextmenu
p-contextmenu
Module: ContextMenuModule - Package: primeng
⚠️ This component requires the use of Angular and will not work in non-Angular applications.

Displays a list of options scoped to a component, an area of the interface, or piece of data

View the p-contextmenu reference doc

If you're adding PrimeNG to your solution for the first time, reference their setup documentation. It's important to note that the inclusion of the nova-light theme css is not necessary to work with Responsive UI. Styling for the PrimeNG components is provided by Responsive UI's theming.

Implementation

In this example, we’re going to set up two context menus in a view: one for a display block and the other for items in a templated list in the same display block.

Begin by importing the ContextMenuModule module into your application.

Import the module
// import into app.module
import { ContextMenuModule } from 'primeng/contextmenu';

@NgModule({
    imports: [
        ...
        ContextMenuModule,
        ...
    ]
})

export class AppModule(){}

Add the following imports in the view’s controller.

Imports in controller
import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { MenuItem } from 'primeng/api';
import { ContextMenu } from 'primeng/contextmenu';

Next declare variables for the two context menus.

Variables for the context menus
public displayBlockMenuItems: MenuItem[];
public templateMenuItems: MenuItem[];

Then define the options for each context menu in ngOnInit(). We do not add icons for these context menu items; the enterprise theming would hide these anyways.

Defining the context menu options
ngOnInit() {
    this.displayBlockMenuItems = [
        {
            label: 'Link Item',
            items: [
                {label: 'RouterLink Item', routerLink: ['/Home']},
                {label: 'URL Item', url: 'http://www.google.com'}
            ]
        },
        {
            label: 'Event Item',
            items: [
                {label: 'Click Event Item', command: (event) => {
                    alert('Context Menu Item Clicked');
                }}
            ]
        },
        {
            separator: true,
        },
        {
            label: 'Menu Item',
            routerLink: ['/Home']
        },
        {
            label: 'Disabled Item',
            disabled: true,
            command: (event) => {
                alert('Context Menu Item Clicked');
            }
        }
    ];

    this.templateMenuItems = [
        {
            label: 'Update Account',
            items: [
                {label: 'Save Account', command: (event) => {
                    alert('Saved ' + this.selectedAccountType + ' Account #' + this.selectedAccountNumber);
                }},
                {label: 'Delete Account', command: (event) => {
                    alert('Deleted ' + this.selectedAccountType + ' Account #' + this.selectedAccountNumber);
                }}
            ]
        },
        {
            separator: true,
        },
        {label: 'Router Link Item', routerLink: ['/Home']},
        {label: 'URL Item', url: 'http://www.google.com'}
    ];
}

In the HTML below, we have a display block that contains two paragraphs of intro text, a templated list, and two context menus.

We set up the context menu for the display block by defining a p-contextmenu whose model is the display block menu definition we set up in the controller. We then attach that context menu to the display block using the contextmenu method on the jha-display-block, which calls the “onBlockContextMenuClick” method in the controller, sending the event and the context menu associated with it. (Don’t use the target attribute in the p-contextmenu to attach the context menu to the display block; p-contextmenu doesn’t allow you to target custom components directly.)

We set up the context menu for each templated item by defining a p-contextmenu within the template, whose model is the template menu definition we set up in the controller. We then attach that context menu to each templated item using the contextmenu method on the template, which in turn calls the “onAccountContextMenuClick” method in the controller. This method call passes information from the current templated item to the controller (account name and account type); passing info from the template to the context menu method is a critical part of using context menus in templated lists. We don’t need to call the “show” method for the appropriate context menu because we wired up the connection between the context menu and the templated item using the target attribute in the p-contextmenu.

We nest each templated item within a separate div here because you cannot attach a p-contextmenu directly to any element that uses *ngFor.
Defining the context menu options
<jha-display-block (contextmenu)="onBlockContextMenuClick($event, displayBlockContextMenu);">
    <p>
        This page contains two context menus. Right-click inside the display block content to see one context menu.
    </p>

    <p>
        Right-click inside each template below to see a context menu for that templated item.
    </p>

    <div id="account-container-wrapper">
        <div *ngFor="let account of accountList" class="jha-template account-container">
            <div class="account-wrapper" #templateList (contextmenu)="onAccountContextMenuClick($event, account.name, account.type)">
                <jha-icon [jhaIconType]="account.iconType" jhaSize="28px" class="account-icon"></jha-icon>
                <div class="account-info">
                    <div class="jha-bright-text-label">Account {{account.name}}</div>
                    <div class="jha-regular-text-label">{{account.type}}</div>
                </div>
                <p class="jha-regular-text-label account-balance">
                    {{account.balance | jhaCurrency}}
                </p>
            </div>

            <p-contextMenu #templateContextMenu [target]="templateList" [model]="templateMenuItems" appendTo="body">
            </p-contextMenu>
        </div>
    </div>

    <p-contextMenu #displayBlockContextMenu [model]="displayBlockMenuItems" appendTo="body"></p-contextMenu>

</jha-display-block>

Finally, set up the onBlockContextMenuClick and onAccountContextMenuClick methods in the controller. The display block context menu is more complex in this case because triggering the templated item menu will also trigger the display block menu (since the template list is a child of the display block). So in this example, if the onBlockContextMenuClick is called, we first see if the target was the templated item list, and if so, we don’t show the display block menu.

Defining the click event handlers
public onBlockContextMenuClick(event: Event, contextMenu: any): void {
    let templateWrapper = document.getElementById('account-container-wrapper');
    let target = event.target as HTMLElement
    if (target !== templateWrapper && !templateWrapper.contains(target)) {
        contextMenu.show(event);
    } else {
        contextMenu.hide();
    }
}

public onAccountContextMenuClick(event: Event, accountNumber: string, accountType: string): void {
    this.selectedAccountNumber = accountNumber;
    this.selectedAccountType = accountType;
}

Design

Figma design

Figma design info
You can find this component in the Components - Dropdown / Popup Menus page in the Figma UI Kit.
Dev ComponentDesign Component Name
Dropdown menuRUI / Menu / Dropdown Menu
Menu option - enabledAdd text and apply the “rui-regular” text style and “rui-pacific/text-regular” color style.
Menu option - disabledAdd text and apply the “rui-regular” text style and “rui-pacific/text-disabled” color style.
Dropdown menu separatorRUI / Menu / Dropdown Menu Separator
Background behind a hovered menu optionRUI / Menu / Dropdown Menu Hover Background
Submenu indicatorRUI / Icon / WindowDropdown, rotated 90°

If you want to show a context menu in the content area of your design:

  • First add a dropdown menu element to the artboard. This provides the menu background, border, and shadow.
  • For each menu option, add text then apply the “rui-regular” text style and “rui-pacific/text-regular” color style.
  • If you want to separate different sets of menu options, add a dropdown menu separator element between the separated menu options.
  • If this is a dropdown menu for another element such as a dropdown button, split button, or grid “more” button, position the dropdown menu below that element. The menu is typically aligned with the left edge of the button, but can be right aligned if aligning the dropdown menu to the left would push it off the screen. If this is just a context menu, you can position the context menu anywhere since it displays wherever the user right-clicks.
  • If you want to show a submenu for a menu option, add a WindowDropdown icon at the right edge of the menu option and rotate it 90° to have it point to the right. Then layer a separate menu for the submenu, just to the right of the first menu, with the top of the submenu aligned with the top of the menu option in the first menu. You can also optionally display a hover background element behind the item text and arrow for more realism, since submenus display when the user hovers the menu item.
These context/dropdown menus are only meant to be used within display blocks in the content area. See the design sections of documents in the Application Layout section to learn how to create dropdown menus in the navigation bar or header.

Adobe XD design

Adobe XD design info
You can find this component in these artboards in the Adobe XD design samples:
  • Sample App - Context/Dropdown Menu
Dev ComponentDesign Component Name
Dropdown menuJHA / Menu / Dropdown Menu
Menu option - enabledAdd text and apply the “JHA / Text / Regular” character style.
Menu option - disabledAdd text and apply the “JHA / Text / Disabled” character style.
Dropdown menu separatorJHA / Menu / Dropdown Menu Separator
Background behind a hovered menu optionJHA / Menu / Dropdown Menu Hover Background

If you want to show a context menu in the content area of your design:

  • First add a dropdown menu element to the artboard. This provides the menu background, border, and shadow.
  • For each menu option, add text then apply the “JHA / Text / Regular” character style. Add the “JHA / Text / Disabled” character style for disabled menu options.
  • If you want to separate different sets of menu options, add a dropdown menu separator element between the separated menu options.
  • If this is a dropdown menu for another element such as a dropdown button, split button, or grid “more” button, position the dropdown menu below that element. The menu is typically aligned with the left edge of the button, but can be right aligned if aligning the dropdown menu to the left would push it off the screen. If this is just a context menu, you can position the context menu anywhere since it displays wherever the user right-clicks.
  • If you want to show a submenu for a menu option, add a WindowDropdown icon at the right edge of the menu option and rotate it 90° to have it point to the right. Then layer a separate menu for the submenu, just to the right of the first menu, with the top of the submenu aligned with the top of the menu option in the first menu. You can also optionally display a hover background element behind the item text and arrow for more realism, since submenus display when the user hovers the menu item.
These context/dropdown menus are only meant to be used within display blocks in the content area. See the design sections of documents in the Application Layout section to learn how to create dropdown menus in the navigation bar or header.

Support options
Have questions on this topic?
Join the Responsive UI team in Microsoft Teams to connect with the community.
See something in this page that needs to change?
Send us feedback on this page.
Last updated Wed Apr 19 2023