Context Menu
Examples
Positioning | Screenshot |
---|---|
Container position: below Container justify to caret: left Caret justify to trigger: center | |
Container position: above Container justify to caret: right Caret justify to trigger: center | |
Container position: left Container align to caret: start Caret align to trigger: end | |
Container position: right Container align to caret: end Caret align to trigger: center | |
Container position: left Container align to caret: center Caret align to trigger: center |
Usage
Dos:
- Use short and precise labels for menu items.
- Use as few menu items as possible.
Donts:
- Don’t overwhelm users with expansive lists of menu items. Keep the list length manageable by including fewer than 10–12 items, to avoid choice overload.
Implementation notes
The Context Menu involves 2 main elements:
trigger
: typically a button, which is intended to open thecontainer
when clicked.container
: the menu itself, which is hidden until activated by thetrigger
.
To initialize interactive behavior and make the component accessible, we use JavaScript that will identify triggers by querying for the bux-context-menu__trigger
class, then looking for each trigger's corresponding container by finding the first element occuring after the trigger in the DOM order that has the bux-context-menu__container
class. This allows for some flexibility in your DOM structure, but typically it's easiest to put the container element immediately after its trigger.
The Twig template relies on the JavaScript and CSS portions of the component to fill in several important attributes -- see the Accessibility section for more information.
Keeping the menu open on clicks outside the container
By default, the menu will collapse if the user clicks outside of the container. To override this behavior and keep the menu open until the user clicks the trigger again or presses Escape
, you can add the data-stay-open="true"
attribute to the trigger
element. This can also be passed in as the stay_open
variable in the Twig template.
Positioning
By default, the container
will open beneath the trigger element, with the caret justified to the trigger
's center, and the container
justified to the start of the caret. This is powered by an underlying popover system, and you can adjust it with classes on the trigger
and container
.
First, on the container element, specify:
- how to position the container relative to the trigger
- Above:
container--position-above-trigger
- Below:
container--position-below-trigger
- Left of:
container--position-left-of-trigger
- Right of:
container--position-right-of-trigger
- Above:
- and how to justify or align the container to the caret:
- If the container is above or below the trigger, the caret will be on the bottom or top of the container, respectively, so you'll justify the container and caret.
- Left:
container--justify-caret-left
- Center:
container--justify-caret-center
- Right:
container--justify-caret-right
- Left:
- If the container is left of or right of the trigger, the caret will be on the right or left side of the container, respectively, so you'll align the container and caret.
- Top/start:
container--align-caret-start
- Center:
container--align-caret-center
- Bottom/end:
container--align-caret-end
- Top/start:
- If the container is above or below the trigger, the caret will be on the bottom or top of the container, respectively, so you'll justify the container and caret.
Then, on the caret element, you can specify how the caret should align or justify to the trigger
- If the container is above or below the trigger, the caret will be pointing to the top or bottom of the trigger, respectively, so you'll justify the caret and trigger.
- Left:
caret--justify-trigger-left
- Center:
caret--justify-trigger-center
- Right:
caret--justify-trigger-right
- Left:
- If the container is right of or left of the trigger, the caret will be pointing to the right or left side of the trigger, respectively, so you'll align the caret and trigger.
- Top/start:
caret--align-trigger-start
- Center:
caret--align-trigger-center
- Bottom/end:
caret--align-trigger-end
- Top/start:
Accessibility
Relationships
On page load, the JavaScript for this component will set up the relationship between the trigger
by generating a unique DOM ID, assigning it to the container
, and setting the trigger
's aria-owns
to it. On expand and collapse, the trigger
gets updated with aria-expanded="true"
and aria-expanded="false"
, respectively.
Hiding when collapsed
When collapsed, the container
is hidden visually, from find-in-page behavior, and from accessible technology with inert
and display: none
. The trigger
element should have a descriptive label. For instance, in an icon button, this could be visually hidden text inside the button.
Focus management
When collapsed, the container
's items are not focusable due to display: none
and inert
. When expanded, the JavaScript will set focus to the first item in the list. From there, focus is trapped in the component by keydown listeners, and will move from the last item in the menu back up to the trigger.
Keyboard navigation
Tab
andArrowDown
: moves focus to the next item in the menu. Will move back to the trigger button if pressed from the last item in the menu.Shift+Tab
andArrowUp
: moves focus to the previous item in the menu. Will move to the last item in the menu if pressed from the trigger button.Home
: moves focus to the first item in the menu.End
: moves focus to the last item in the menu.Escape
: closes the menu.