menu item
The menu item is the smallest element of the Context Menu.
It can be either a link or a button. It has a mandatory label and optional icon and divider.
A link can be used for first level items.
A button can be used for:
- groups (with an arrow down icon)
- showing / hiding second level items (with an arrow right icon)
Ensure that an instance of this component is used inside a parent component with role 'menu', 'menubar' or 'group'.
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.
Mandatory and optional parts
The menu item dows have multiple parts that can be used, only the label is mandatory. Optional parts are:
- icon in front of the label
- secondary label
- badge
- arrow right or arrow down to indicate sub menus
- divider to separate multiple menu items
Indent variant
The indent variant of the component, can occur in two versions: with or without active indicator in form of an ui icon checkmark.
For the rest of the possible parts, the same rules apply as for the non-indent version.
table of content
- description
- component variations
- Default
- With icon
- With secondary label
- With badge
- With arrow right
- With arrow down
- With icon and secondary label
- With icon, secondary label and badge
- With icon, secondary label, badge and arrow right
- With icon, secondary label, badge and arrow down
- With icon, secondary label, badge, arrow down and divider
- With icon, secondary label, badge and arrow down disabled
- With icon, secondary label, badge, arrow down and divider disabled
- Active
- Indent
- Indent with divider
- Indent active
- Indent disabled
- Indent active disabled
- indent and selected
- indent, active and selected
- style scss
component variations
Default
<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>
With icon
<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>
</a>
</div>
</li>
With secondary label
<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 Label</span>
</a>
</div>
</li>
With badge
<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>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
</a>
</div>
</li>
With arrow right
<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"
>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</button>
</div>
</li>
With arrow down
<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-label="open group"
>
<span class="a-menu-item__label">Label</span>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
With icon and secondary label
<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 Label</span>
</a>
</div>
</li>
With icon, secondary label and badge
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
</a>
</div>
</li>
With icon, secondary label, badge and arrow right
<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"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-nosafe-lr-right-small"></i>
</button>
</div>
</li>
With icon, secondary label, badge and arrow down
<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-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
With icon, secondary label, badge, arrow down and divider
<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-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
<hr class="a-divider" />
With icon, secondary label, badge and arrow down disabled
<li class="a-menu-item -disabled" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="true"
tabindex="-1"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
With icon, secondary label, badge, arrow down and divider disabled
<li class="a-menu-item -disabled" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="true"
tabindex="-1"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
<hr class="a-divider" />
Active
<li class="a-menu-item -selected" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
Indent
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
Indent with divider
<li class="a-menu-item -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
<hr class="a-divider" />
Indent active
<li class="a-menu-item -indent -selected" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
Indent disabled
<li class="a-menu-item -disabled -indent" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="true"
tabindex="-1"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
Indent active disabled
<li class="a-menu-item -disabled -indent -selected" role="none">
<div class="a-menu-item__wrapper">
<button
type="button"
role="menuitem"
class="a-menu-item__group"
aria-disabled="true"
tabindex="-1"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
indent and selected
<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__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
indent, active and selected
<li class="a-menu-item -indent -selected" 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__group"
aria-disabled="false"
aria-label="open group"
>
<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 Label</span>
<div class="a-badge" role="status" aria-live="off" data-count="1">1</div>
<i class="a-icon ui-ic-down-small"></i>
</button>
</div>
</li>
additional content
styles SCSS
.a-menu-item {
margin: 0;
padding: 0;
width: 100%;
/* stylelint-disable a11y/content-property-no-static-value */
&::before {
content: unset;
}
/* stylelint-enable a11y/content-property-no-static-value */
&__wrapper {
position: relative;
display: grid;
grid-template-columns: 1fr;
grid-template-areas: 'label';
align-items: center;
height: auto;
justify-content: center;
background-color: var(--plain__enabled__fill__default);
color: var(--plain__enabled__front__default);
// interactive states
&:hover {
background-color: var(--plain__enabled__fill__hovered);
color: var(--plain__enabled__front__hovered);
text-decoration: none;
cursor: pointer;
}
&:active {
background-color: var(--plain__enabled__fill__pressed);
color: var(--plain__enabled__front__pressed);
}
&:has( > *:focus-visible) {
// @include focus-inside;
// margin: 1rem;
// Outline for keyboard navigation
&::before,
&::after {
position: absolute;
content: '';
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
}
&::before {
outline: 3px solid var(--plain__enabled__front__default);
outline-offset: -3px;
}
&::after {
outline: 3px solid var(--background);
outline-offset: -6px;
}
}
}
&.-disabled > .a-menu-item__wrapper {
background-color: var(--plain__disabled__fill__default);
color: var(--plain__disabled__front__default);
cursor: not-allowed;
.a-badge {
background-color: var(--major-accent__disabled__fill__default);
color: var(--major-accent__disabled__front__default);
}
}
// indent variant layout adjustments
&.-indent .a-menu-item__wrapper {
grid-template-columns: 2.875rem 1fr;
grid-template-areas: 'state label';
& .a-menu-item__link,
& .a-menu-item__button,
& .a-menu-item__group,
& .a-menu-item__side-menu {
padding-inline-start: 0;
}
&:has([class^="a-menu-item"] > .a-icon) {
grid-template-columns: 2.75rem 1fr;
}
}
// styles for each part of the menuItem
&__state {
display: grid;
place-content: center;
grid-area: state;
height: 3rem;
background-color: inherit;
color: inherit;
}
a,
a:visited {
text-decoration: none;
color: inherit;
background-color: inherit;
}
&__link,
&__button,
&__group,
&__side-menu {
grid-area: label;
text-align: left;
display: grid;
grid-auto-flow: column;
grid-auto-columns: auto;
align-items: center;
column-gap: 0.5rem;
width: 100%;
padding: 0.75rem 1rem;
border: 0;
background-color: inherit;
color: inherit;
// different grid layouts for each possible content
&:has(> .a-menu-item__label) {
grid-template-columns: 1fr;
}
&:has(> .a-menu-item__label + .a-menu-item__label) {
grid-template-columns: 2fr 1fr;
}
&:has(> .a-icon:first-child + .a-menu-item__label) {
grid-template-columns: auto 1fr;
}
&:has(> .a-icon:first-child + .a-menu-item__label + .a-menu-item__label) {
grid-template-columns: auto 2fr 1fr;
}
&:has(>.a-icon:first-child) {
padding-inline-start: 0.75rem;
}
// reset focus states of button and link
&:focus-visible {
outline: none;
&::after {
content: none;
}
}
.a-icon {
margin: unset;
}
}
&__label {
color: inherit;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
&__label:nth-of-type(2) {
text-decoration: none;
text-align: end;
@include size-s;
}
+ .a-divider {
margin-top: 0;
margin-bottom: 0;
margin-inline: 1rem;
}
}```