Soracom

Design System
  1. Home
  2. Design system
  3. Elements
  4. Menubutton

Menubutton

Menubutton is for dynamically displaying navigation menus

Overview

The ds-menubutton component displays a navigation or action menu from a button-like trigger. It supports native popover or details and summary implementations and uses ds-menu for the menu content.

Native details and popover menus do not require JavaScript. Action menus may require additional JavaScript to implement W3C WAI-ARIA accessibility recommendations.

Options

Basic usage

ds-menubutton can use either a div and button with native popover state, or native HTML details and summary elements. The popover implementation is recommended for new menubuttons.

ds-menu content uses the available options of ds-menu. See ds-menu for additional documentation on menu items.

Using popover

The native Popover API is the recommended way to open and close the menu. Match the button’s popovertarget value to the menu’s id, and add the popover attribute to the menu. The browser manages the expanded state, light dismissal, and Escape key behavior without additional JavaScript.

Using popovertarget provides the implicit aria-expanded state and relationship between the button and popover, so these do not need to be added or synchronized manually. Retain aria-haspopup="menu" to identify the type of popup. See Role and ARIA attributes.

Basic usage - popover menubutton styled as a button

Basic usage - popover menubutton styled as text

Basic usage - popover menubutton styled as a label and small icon

Using details/summary elements

The popover implementation is recommended for new menubuttons. The details and summary implementation remains supported for existing uses.

When using a details element, clicking the summary element toggles the ds-menu content without JavaScript.

Basic usage - details element with menubutton styled as a button

Basic usage - details element with menubutton styled as text

Basic usage - details element with menubutton styled as label and a small icon

Using JavaScript

Assign popoverTargetElement when application logic needs to connect the trigger and menu programmatically. This is the JavaScript equivalent of the popovertarget attribute, so the browser still manages the expanded state and native popover behavior.

Basic usage - JavaScript Popover API

html
Copy

Position

By default the menubutton menu is displayed below and aligned to the left of the button element.

As an alternative, the following positions are supported:

  • --right
  • --fixed-left
  • --fixed-top-left
  • --fixed-right
  • --fixed-top-right
Menubuttons used inside a ds-header__controls element will automatically display aligned right.

Menu position - right using popover

Menu position - right using details

Menu position - fixed left using popover

Menu position - fixed left using details

Menu position - fixed top-left using popover

Menu position - fixed top-left using details

Menu position - fixed right using popover

Menu position - fixed right using details

Menu position - fixed top right using popover

Menu position - fixed top right using details

Component colors

Adding a color the to the top-level ds-menubutton element will color the button and the drop down menu.

If you need to only color the button (and not the drop down menu), add the color to the ds-button element.

Color the button and menu

Full color popover example

Full color details example

Color the button only

Color popover button example

Color details button example

Width

Narrow, mid, wide, full

--full width sets the menu to be the same width of the menubutton

Popover ds-menu at default, narrow, mid, wide and full sizes (click buttons to view)

Details ds-menu at default, narrow, mid, wide and full sizes (click buttons to view)

Height

By default the menu will be the height of the menu contents. You can also restrict the overall height of the menu and cause the contents to scroll. If the menu can scroll, a shadow will be added at the bottom/top of the menu to indicate the menu is scrollable.

You can apply these settings to either a ds-menubutton or to a standalone ds-menu component.

There are two ways to restrict the height.

Restrict the height to the viewport

Adding the class --viewport to the menu will restrict the height to 100vh - --ds-header-height (usually 100vh - 60px) and force the menu to scroll.

Using viewport height with popover - if the browser height is less than the menu height, the menu will scroll

Using viewport height with details - if the browser height is less than the menu height, the menu will scroll

Restrict the height to a specific size

You can restrict the height by changing the --ds-menu-height value (either in a css file, inline style tag or via javascript).

let myCustomMenu = document.getElementById('customMenu');
myCustomMenu.style.setProperty('--ds-menu-height', '400px');

Setting a popover height using an inline style tag

Setting a details height using an inline style tag

Styles

Variants

No dismiss

To prevent clicking outside the menu from closing it, use popover="manual" with the popover implementation. Use the class --no-dismiss with the details implementation.

No dismiss using popover

No dismiss using details

No background

To not show the background modal tint, use the class --no-background.

No background using popover

No background using details

Inline

To show the open menu in the normal document flow, use the class --inline.

--inline is only supported with the details and summary implementation. It cannot be used with popover, because an open popover is rendered in the top layer and does not expand the surrounding layout.

Inline menubutton

Addon menubutton

The --addon styles slightly modify the menubutton to ‘join’ the containing component.

Native popover addon menubuttons

html
Copy

Details addon menubuttons

html
Copy

Accessibility

References

Implementation

There are two primary usage cases for ds-menubutton

  • Navigation menu buttons
  • Action menu buttons

Navigation menu buttons primarily contain lists of links that change the URL and display a different page or context. Retain the native list and link semantics rather than adding menu and menuitem roles.

Native details and popover implementations provide their own expanded state. A scripted button must maintain its aria-expanded state as described below.

Action menubutton

Action menu buttons are a menu that performs a task on the page, such as opening a modal, changing the status of a feature etc.

This component is not fully accessible by default when used for action menus. Action menus require the complete ARIA menu roles and keyboard interactions described by the WAI-ARIA Menu Button Pattern.

Role and ARIA attributes

The trigger attributes depend on the state mechanism used by the menubutton.

Native popover state

Match popovertarget to the popover menu’s id. The browser manages the expanded state, so do not add a duplicate aria-expanded attribute.

Popover menu button

html
Copy

Native details state

Do not add aria-expanded or button roles to summary. The browser exposes the expanded state of the native details element.

Native details menu button

html
Copy

Scripted button state

Set aria-expanded to match the visible menu state. aria-controls references the menu content by id.

Scripted menu button

html
Copy
AttributeRequiredTypeDescription
aria-haspopup=“menu”RequiredStaticIndicates that the button opens a menu
aria-expandedRequiredDynamicSet to true when the menu is open and false when it is closed
aria-controlsOptionalStaticReferences the menu content controlled by the button

The following additional roles apply when implementing the complete ARIA action-menu interaction pattern:

Menu items

html
Copy
ElementAttributeRequiredTypeDescription
<div>role=“menu”RequiredStaticIndicates the element is a menu
<ul>role=“none”RequiredStaticHides implied semantics from assistive technologies
<li>role=“none”RequiredStaticHides implied semantics from assistive technologies
<a>role=“menuitem”RequiredStaticIndicates the element is a menuitem
tabindex=“-1”RequiredStaticPrevents list items being selected using the tab keyboard command

Keyboard access

The trigger can be reached with the browser’s native Tab behavior. Native details and popover triggers open with Space or Enter; a scripted trigger must implement that state change. Opening a native details or popover menu does not automatically move focus to its first menu item.

When used as an action menubutton, additional roles, ARIA attributes, focus management, and JavaScript keyboard handling are required.

Menu button - the closed menu button is selected:

KeyRequiredSupportDescription
EnterRequiredNative details/popover; JavaScript for scripted state and focusOpens the menu; action-menu implementations move focus to the first menu item
SpaceRequiredNative details/popover; JavaScript for scripted state and focusOpens the menu; action-menu implementations move focus to the first menu item
TabRequiredNativeMoves to the next element in the page tab sequence
Down ArrowOptionalJavaScriptOpens the menu and moves focus to the first menu item
Up ArrowOptionalJavaScriptOpens the menu and moves focus to the last menu item

Menu items - the menubutton menu is open:

KeyRequiredSupportDescription
EnterRequiredNativeActivates the selected menu item
EscapeRequiredNative popover; JavaScript otherwise1. Closes the menu
2. Moves focus back to the menu button
TabRequiredJavaScript1. Closes the menu
2. Move to the next element in the page tab sequence
Down ArrowOptionalJavaScriptMoves focus to the next menu item
Up ArrowOptionalJavaScriptMoves focus to the previous menu item

JavaScript

Use showPopover(), hidePopover(), and togglePopover() to control a menu from application logic. Passing the trigger as source preserves its relationship with the popover when it is shown programmatically.

const trigger = document.querySelector('[popovertarget="account-menu"]');
const menu = trigger.popoverTargetElement;

function openMenu() {
  menu.showPopover({ source: trigger });
}

function closeMenu() {
  menu.hidePopover();
}

function toggleMenu() {
  return menu.togglePopover({ source: trigger });
}

Examples

When ds-menubutton is used inside ds-select, ds-input, or ds-range it will be displayed next to the element and will not wrap when the window is scaled.

Native popover menubuttons inside other components

html
Copy

Details menubuttons inside other components

html
Copy

Alert menu item using popover

html
Copy

Alert menu item using details

html
Copy
Actions

Header example

Header menus using popover

Header menus using details

ds-menubutton inside ds-datatable

Datatable menus using popover

html
Copy
Heading one Heading two Heading three
Content Content
Content Content

Datatable menus using details

html
Copy
Heading one Heading two Heading three
Content
Button label
Content
Content
Button label
Content

Manifest

The component manifest describes this component's API: its modifiers, structure, data attributes, CSS custom properties, accessibility notes, and example markup. It is consumed by tooling such as AI assistants and code generators.

Latest version: https://assets.soracom.io/sds/3.39.6/ds-menubutton/manifest.json?v=3.39.6

manifest.json
Copy