Context Menu
The context menu offers users additional interactions for an element using a popover and menu items.
This component works with all its features only in browsers that have support for the
If you need to run this component in a browser with no support for the
:has
CSS selector. Please refer to the
reference on MDN.
If you need to run this component in a browser with no support for the
:has
CSS selector, please use the
FROK Release 3.6.x.
It comes with two types:
- Default (permanently located in one position relative to its button. The popover can only be called here.)
- Free (The Free Context Menu refers to a freely selectable element.)
Parts
- The popover can be built up by combining different variants of the menu items.
Behaviour
- The navigation can be opened and closed by clicking the trigger menu icon.
- A click on a First Level Page menu item opens the corresponding page.
- Selecting a group opens or closes it, and closes a previous opened group.
- The group's variant on the side will show the sub items on hover.
How to use the 'Free' Variant
It's up to the user how to position the Free variant relatively to an element.
The demo below used the following position: top: 0
, left: 0
along with z-index: 999
.
table of content
component variations
Default
<nav
class="o-context-menu"
aria-label="Context Menu Navigation Default"
aria-hidden="false"
>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="open"
aria-haspopup="true"
aria-label="Open Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-options"></i>
</button>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="close"
aria-haspopup="false"
aria-label="Close Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-close"></i>
</button>
<div class="m-popover">
<div class="a-box -floating">
<div class="m-popover__content">
<ul class="m-menu-group" role="menubar" aria-orientation="vertical">
<div class="m-menu-group__section-header">
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">5</div>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<div class="m-menu-group__section-header">
<hr class="a-divider" />
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">new</div>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
</ul>
</div>
</div>
</div>
</nav>
Without section header
<nav
class="o-context-menu"
aria-label="Context Menu Navigation Without section header"
aria-hidden="false"
>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="open"
aria-haspopup="true"
aria-label="Open Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-options"></i>
</button>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="close"
aria-haspopup="false"
aria-label="Close Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-close"></i>
</button>
<div class="m-popover">
<div class="a-box -floating">
<div class="m-popover__content">
<ul class="m-menu-group" role="menubar" aria-orientation="vertical">
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">5</div>
</a>
</div>
</li>
<hr class="a-divider" />
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<hr class="a-divider" />
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">new</div>
</a>
</div>
</li>
</ul>
</div>
</div>
</div>
</nav>
Side menu
<nav
class="o-context-menu"
aria-label="Context Menu Navigation Side menu"
aria-hidden="false"
>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="open"
aria-haspopup="true"
aria-label="Open Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-options"></i>
</button>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="close"
aria-haspopup="false"
aria-label="Close Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-close"></i>
</button>
<div class="m-popover">
<div class="a-box -floating">
<div class="m-popover__content">
<ul class="m-menu-group" role="menubar" aria-orientation="vertical">
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">5</div>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">new</div>
</a>
</div>
</li>
<div class="m-menu-group__section-header">
<hr class="a-divider" />
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__side-menu"
aria-disabled="false"
aria-controls="group-id-1"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</button>
</div>
<ul
id="group-id-1"
class="m-menu-group__flyout -floating"
role="menu"
>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⇧⌘ 4</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+N</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+T</span>
</button>
</div>
</li>
</ul>
</li>
<li class="a-menu-item -disabled" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="true"
tabindex="-1"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label disabled</span>
</a>
</div>
</li>
<div class="m-menu-group__section-header">
<hr class="a-divider" />
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__side-menu"
aria-disabled="false"
aria-controls="group-id-2"
>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</button>
</div>
<ul
id="group-id-2"
class="m-menu-group__flyout -floating"
role="menu"
>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⇧⌘ 4</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+N</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Link</span>
<div class="a-badge" role="status" aria-live="off">1</div>
</a>
</div>
</li>
<hr class="a-divider" />
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+T</span>
</button>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</nav>
Group menu
<nav
class="o-context-menu"
aria-label="Context Menu Navigation Group menu"
aria-hidden="false"
>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="open"
aria-haspopup="true"
aria-label="Open Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-options"></i>
</button>
<button
type="button"
class="a-button a-button--integrated -without-label o-context-menu__trigger"
data-frok-action="close"
aria-haspopup="false"
aria-label="Close Context Menu"
>
<i class="a-icon a-button__icon boschicon-bosch-ic-close"></i>
</button>
<div class="m-popover">
<div class="a-box -floating">
<div class="m-popover__content">
<ul class="m-menu-group" role="menubar" aria-orientation="vertical">
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">5</div>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
<div class="a-badge" role="status" aria-live="off">new</div>
</a>
</div>
</li>
<div class="m-menu-group__section-header">
<hr class="a-divider" />
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-controls="group-id-3"
aria-label="open group"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
<ul id="group-id-3" class="m-menu-group__group" role="menu">
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<div class="a-badge" role="status" aria-live="off">7</div>
</a>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
</ul>
</li>
<li class="a-menu-item -disabled" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="true"
tabindex="-1"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label disabled</span>
</a>
</div>
</li>
<div class="m-menu-group__section-header">
<hr class="a-divider" />
<span class="highlight -size-s">Section header</span>
</div>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-controls="group-id-4"
aria-label="open group"
>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
<ul id="group-id-4" class="m-menu-group__group" role="menu">
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<a
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Link</span>
</a>
</div>
</li>
<hr class="a-divider" />
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<a
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</nav>
Demo for Free version
<div class="frontend-kit-example_context-menu">
<div class="example-text-context-menu -size-m">
Click me to show the context menu
</div>
<nav
class="o-context-menu"
aria-label="Context Menu Navigation undefined"
aria-hidden="false"
>
<div class="m-popover -without-arrow">
<div class="a-box -floating">
<div class="m-popover__content">
<ul class="m-menu-group" role="menubar" aria-orientation="vertical">
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__side-menu"
aria-disabled="false"
aria-controls="group-id-5"
>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</button>
</div>
<ul
id="group-id-5"
class="m-menu-group__flyout -floating"
role="menu"
>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⇧⌘ 4</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+N</span>
</button>
</div>
</li>
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<a
href="#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Link</span>
</a>
</div>
</li>
<hr class="a-divider" />
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<i class="a-icon a-menu-item__state ui-ic-checkmark"></i>
<button
type="button"
role="menuitem"
class="a-menu-item__button"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">⌘+T</span>
</button>
</div>
</li>
</ul>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<i class="a-icon boschicon-bosch-ic-emoji-happy"></i>
<span class="a-menu-item__label">Label</span>
<span class="a-menu-item__label">Secondary text</span>
</a>
</div>
</li>
<li class="a-menu-item" role="none">
<div class="a-menu-item__wrapper">
<a
href="/#"
role="menuitem"
class="a-menu-item__link"
aria-disabled="false"
>
<span class="a-menu-item__label">Label</span>
</a>
</div>
</li>
</ul>
</div>
</div>
</div>
</nav>
</div>
additional content
demo
export default (): void => {
const contextMenuExamples = document.getElementsByClassName(
'frontend-kit-example_context-menu',
);
[...contextMenuExamples].forEach((container) => {
const componentContainer =
container.getElementsByClassName('o-context-menu')[0];
const exampleTexts = container.getElementsByClassName(
'example-text-context-menu',
)[0];
const popovers = container.getElementsByClassName('m-popover')[0];
popovers.style.top = '0';
popovers.style.left = '0';
popovers.style.zIndex = '999';
exampleTexts.addEventListener('click', () => {
if (componentContainer.classList.contains('-visible')) {
componentContainer.classList.remove('-visible');
} else {
componentContainer.classList.add('-visible');
}
});
popovers.addEventListener('mouseleave', () => {
componentContainer.classList.remove('-visible');
});
});
};
styles SCSS
/* stylelint-disable a11y/no-display-none */
.o-context-menu {
position: relative;
&__trigger[data-frok-action="close"] {
display: none;
}
.m-popover__content {
padding: 0;
width: 15rem;
}
&.-open {
.o-context-menu__trigger {
&[data-frok-action="open"] {
display: none;
}
&[data-frok-action="close"] {
display: flex;
}
}
.m-popover {
display: block;
z-index: 999;
}
}
&.-visible .m-popover {
display: block;
}
// Move the popover's arrow (which is made as a square) in the background
.m-menu-group > .a-menu-item:nth-of-type(1) {
z-index: 1;
}
}
/* stylelint-enable a11y/no-display-none */