Options
Basic usage
ds-menubutton can use either an html details
and summary
element; or div
and button
.
__content
content uses the available options of ds-menu
. See ds-menu for additional documentation on menu items.
Using details/summary elements
When using a details
element, the summary
element when clicked will toggle the contents of __content
- the menu container, without the need for any javascript.
<details class="ds-menubutton">
<summary class="ds-text">Text content</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton">
<summary>
<span class="ds-button --label --icon-settings"><span>Text content</span></span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
Using div and button elements
When using a div
element, the button
element requires additional javascript to open and close the menu.
At minimum, the javascript should:
- Set the
button
attributearia-expanded="true"
to show the menu contents. - Add the class
--open
to menubutton container –<div class="ds-menubutton --open">
to correctly set the menubuttons z-index.
<div class="ds-menubutton">
<button class="ds-button --primary --icon-settings">
<span>Button label</span>
</button>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</div>
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
ds-header__controls
element will automatically display aligned right.
<details class="ds-menubutton --right">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton --fixed-left">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton --fixed-top-left">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton --fixed-right">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton --fixed-top-right">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton --constrain-vh --fixed-top-right">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
Width
Narrow, mid, wide, full
--full
width sets the menu to be the same width of the menubutton
<!-- 1. Default -->
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<!-- 2. ds-menu --narrow -->
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu --narrow">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<!-- 3. ds-menu --mid -->
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu --mid">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<!-- 4. ds-menu --wide -->
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu --wide">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
<!-- 5. ds-menu --full -->
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label which is quite wide</span>
</span>
</summary>
<div class="ds-menu --full">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
1. Default
2. ds-menu --narrow
3. ds-menu --mid
4. ds-menu --wide
5. ds-menu --full
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.
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu --viewport" >
<ul>
<li>
<a href="#">Details</a>
</li>
<li>
<a href="#">Activate</a>
</li>
<li>
<a href="#">Deactivate</a>
</li>
</ul>
<ul>
<li>
<a href="#">Add subscription...</a>
</li>
</ul>
<ul>
<li>
<a href="#">Delete session</a>
</li>
</ul>
<ul>
<li>
<a href="#">Change group</a>
</li>
<li>
<a href="#">Change speed class</a>
</li>
<li>
<a href="#">Change expiry</a>
</li>
<li>
<a href="#">Enable IMEI lock</a>
</li>
<li>
<a href="#">Unset IMEI lock</a>
</li>
</ul>
<ul>
<li>
<a href="#">Check logs</a>
</li>
<li>
<a href="#">Harvest data</a>
</li>
<li>
<a href="#">Send SMS</a>
</li>
</ul>
<ul>
<li>
<a href="#">On-demand Remote Access</a>
</li>
<li>
<a href="#">Packet capture</a>
</li>
<li>
<a href="#">Send ping message</a>
</li>
</ul>
<ul>
<li>
<a href="#">Run diagnostics</a>
</li>
</ul>
<ul>
<li>
<a href="#">Change termination protection</a>
</li>
<li>
<a href="#">Set to Standby</a>
</li>
<li>
<a href="#">Suspend</a>
</li>
<li>
<a href="#">Terminate</a>
</li>
</ul>
<ul>
<li>
<a href="#">Transfer to another operator</a>
</li>
<li>
<a href="#">Cancel transfer</a>
</li>
</ul>
</div>
</details>
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")
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu" style="--ds-menu-height: 400px;">
<ul>
<li>
<a href="#">Details</a>
</li>
<li>
<a href="#">Activate</a>
</li>
<li>
<a href="#">Deactivate</a>
</li>
</ul>
<ul>
<li>
<a href="#">Add subscription...</a>
</li>
</ul>
<ul>
<li>
<a href="#">Delete session</a>
</li>
</ul>
<ul>
<li>
<a href="#">Change group</a>
</li>
<li>
<a href="#">Change speed class</a>
</li>
<li>
<a href="#">Change expiry</a>
</li>
<li>
<a href="#">Enable IMEI lock</a>
</li>
<li>
<a href="#">Unset IMEI lock</a>
</li>
</ul>
<ul>
<li>
<a href="#">Check logs</a>
</li>
<li>
<a href="#">Harvest data</a>
</li>
<li>
<a href="#">Send SMS</a>
</li>
</ul>
<ul>
<li>
<a href="#">On-demand Remote Access</a>
</li>
<li>
<a href="#">Packet capture</a>
</li>
<li>
<a href="#">Send ping message</a>
</li>
</ul>
<ul>
<li>
<a href="#">Run diagnostics</a>
</li>
</ul>
<ul>
<li>
<a href="#">Change termination protection</a>
</li>
<li>
<a href="#">Set to Standby</a>
</li>
<li>
<a href="#">Suspend</a>
</li>
<li>
<a href="#">Terminate</a>
</li>
</ul>
<ul>
<li>
<a href="#">Transfer to another operator</a>
</li>
<li>
<a href="#">Cancel transfer</a>
</li>
</ul>
</div>
</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
<details class="ds-menubutton --color-magenta">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
Color the button only
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings --color-magenta">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<div class="ds-text --label">Account</div>
<ul>
<li>
<a href="#" class="ds-text --icon-settings">Account settings<span>Manage account settings and features</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-signin">Change email<span>Update your login email</span></a>
</li>
<li>
<a href="#" class="ds-text --icon-user">Contact information</a>
</li>
</ul>
<div class="ds-text --label">Payment</div>
<ul>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
<ul>
<li>
<a href="#">Logout</a>
</li>
</ul>
</div>
</details>
No dismiss
To prevent clicking outside the menu closing the menu, use the class --no-dismiss
.
<details class="ds-menubutton --no-dismiss">
<summary class="ds-text">Text content</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
No background
To not show the background modal tint, use the class --no-background
.
<details class="ds-menubutton --no-background">
<summary class="ds-text">Text content</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
Inline
To show the open menu inline (instead of a popup menu), use the class --inline
.
<div class="ds-menubutton --inline">
<button class="ds-button --primary --icon-settings">
<span>Button label</span>
</button>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</div>
<details class="ds-menubutton --inline">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
Additional menu options
See ds-menu for additional options for menu items.
Menubutton inside other components
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.
<!-- Inside ds-input -->
<div class="ds-input">
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-input ds-button primary -->
<div class="ds-input">
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-input ds-button plain -->
<div class="ds-input">
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select -->
<div class="ds-select">
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select ds-button primary-->
<div class="ds-select">
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select ds-button plain-->
<div class="ds-select">
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-range -->
<div class="ds-range">
<input type="range">
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<div class="ds-range">
<details class="ds-menubutton">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="range">
</div>
<!-- Inside ds-range ds-button primary-->
<div class="ds-range">
<input type="range">
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<div class="ds-range">
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="range">
</div>
<!-- Inside ds-range ds-button plain-->
<div class="ds-range">
<input type="range">
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<div class="ds-range">
<details class="ds-menubutton">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="range">
</div>
Addon menubutton
The --addon
styles slightly modify the menubutton to ‘join’ the containing component.
Addon style
<!-- Inside ds-input -->
<div class="ds-input">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-input ds-button primary-->
<div class="ds-input">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-input ds-button plain-->
<div class="ds-input">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<input type="text"/>
</div>
<div class="ds-input">
<input type="text"/>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select -->
<div class="ds-select">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select ds-button primary -->
<div class="ds-select">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --primary">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
<!-- Inside ds-select ds-button plain -->
<div class="ds-select">
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
</div>
<div class="ds-select">
<select>
<option value="AU">Australia</option>
<option value="JP">Japan</option>
<option value="US">United States of America</option>
</select>
<details class="ds-menubutton --addon">
<summary>
<span class="ds-button --plain">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
</ul>
</div>
</details>
</div>
Javascript
The following example code improves functionality by only allowing one menubutton menu to be open at once.
if (NodeList.prototype.forEach) {
const menuButtons = document.querySelectorAll(
'[class*="ds-menubutton"] > summary, [class*="ds-menubutton"] > button'
);
menuButtons.forEach(button => {
button.addEventListener("click", () => {
// Keep ARIA attribute in sync with the menu state when toggling
// the menu open or closed. When using div/button, the aria-expanded
// attribute controls visibility of the menu.
let menuState = button.parentElement.open || button.getAttribute("aria-expanded") == "true";
button.setAttribute("aria-expanded", !menuState);
button.parentElement.classList.toggle("--open");
// Only allow one menubutton to be open at once
// When clicked, close all other menubutton instances
menuButtons.forEach(otherButton => {
if (otherButton !== button) {
otherButton.parentElement.open = false;
otherButton.setAttribute("aria-expanded", false);
otherButton.parentElement.classList.remove("--open");
}
});
});
});
}
Accessibility
Implementation
There are two primary usage cases for ds-menubutton
- Navigation menu buttons
- Action menu buttons
Navigation menubutton
Navigation menu buttons primarily contain lists of links that will change the url and essentially display a different page or context. When used in this scenario - no specific W3C-ARIA attributes or custom keyboard functionality should be implemented.
This component is accessible by default when used for navigation menus.
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, it requires the addition of the full aria attributes, and aria specific interactions via javascript.
Role and ARIA attributes
Recommendations for implementing ds-menubutton to meet W3C WAI-ARIA guidelines are as follows:
<summary aria-haspopup="true" aria-expanded="[true|false]">Text content</summary>
<button aria-haspopup="true" aria-expanded="[true|false]">Text content</button>
Element | Attribute | Required | Type | Description |
---|---|---|---|---|
<summary> or <button> |
aria-haspopup="true" |
Required | Static | Indicates the button opens a menu |
aria-expanded="true" |
Required | Dynamic | 1. Set to true when the menu is open 2. Removed or set to false when the menu is closed |
<div role="menu" class="ds-menu">
<ul role="none">
<li role="none"><a role="menuitem" tabindex="-1" href="#">Change email</a>
</li>
<li role="none"><a role="menuitem" tabindex="-1" href="#">Contact information</a>
</li>
<li role="none"><a role="menuitem" tabindex="-1" href="#">Billing</a>
</li>
<li role="none"><a role="menuitem" tabindex="-1" href="#">Payment settings</a>
</li>
</ul>
</div>
Element | Attribute | Required | Type | Description |
---|---|---|---|---|
<div> |
role="menu" |
Required | Static | Indicates the element is a menu |
<ul> |
role="none" |
Required | Static | Hides implied semantics from assistive technologies |
<li> |
role="none" |
Required | Static | Hides implied semantics from assistive technologies |
<a> |
role="menuitem" |
Required | Static | Indicates the element is a menuitem |
tabindex="-1" |
Required | Static | Prevents list items being selected using the tab keyboard command |
Keyboard access
By default this component can be selected using the browsers native tab
keyboard command; space
or enter
to open or close the menu when the menu button is selected; and tab
, shift-tab
to move through the menu items.
When used as an action menubutton - to improve accessibility for assistive technology, additional Role, ARIA attributes and javascript is required. The following keyboard controls must be implemented to provide accessible keyboard access.
Menu button - the closed menu button is selected:
Key | Required | Support | Description |
---|---|---|---|
Enter |
Required | _Native_ | 1. Opens the menu 2. Places focus on the first menu item |
Space |
Required | _Native_ | 1. Opens the menu 2. Places focus on the first menu item |
Tab |
Required | _Native_ | Move to the next element in the page tab sequence |
Down Arrow |
_Optional_ | Javascript | 1. Opens the menu 2. Moves focus to the first menu item |
Up Arrow |
_Optional_ | Javascript | 1. Opens the menu 2. Moves focus to the last menu item |
Menu items - the menubutton menu is open:
Key | Required | Support | Description |
---|---|---|---|
Enter |
Required | _Native_ | Activates the selected menu item |
Escape |
Required | Javascript | 1. Closes the menu 2. Moves focus back to the menu button |
Tab |
Required | Javascript | 1. Closes the menu 2. Move to the next element in the page tab sequence |
Down Arrow |
_Optional_ | Javascript | Moves focus to the next menu item |
Up Arrow |
_Optional_ | Javascript | Moves focus to the previous menu item |
Examples
Header example
<header class="ds-header">
<aside class="ds-header__controls">
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary">
<span>First menu</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Language settings</a>
</li>
<li>
<a href="#">Region Setting</a>
</li>
</ul>
</div>
</details>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Second menu</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
</aside>
</header>
Menu item button with alert visual state
<details class="ds-menubutton">
<summary>
<span class="ds-button --icon-settings">
<span>Actions</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<button class="ds-text --icon-clipboard-copy-to">
Copy algorithm URL
</button>
</li>
<li>
<button class="ds-text --icon-delete --alert">
Delete model
</button>
</li>
</ul>
</div>
</details>
ds-menubutton inside ds-datatable
<table class="ds-datatable">
<thead>
<tr>
<th>Heading one</th>
<th>Heading two</th>
<th>Heading three</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content</td>
<td>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Billing</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
</td>
<td>Content</td>
</tr>
<tr>
<td>Content</td>
<td>
<details class="ds-menubutton">
<summary>
<span class="ds-button --primary --icon-settings">
<span>Button label</span>
</span>
</summary>
<div class="ds-menu">
<ul>
<li>
<a href="#">Change email</a>
</li>
<li>
<a href="#">Contact information</a>
</li>
<li>
<a href="#">Payment settings</a>
</li>
</ul>
</div>
</details>
</td>
<td>Content</td>
</tr>
</tbody>
</table>
Heading one | Heading two | Heading three |
---|---|---|
Content | Content | |
Content | Content |
ui-menu example
<ui-menu>
<details class="ds-menubutton ui-menu__root" role="menu">
<summary>
<span class="ds-button">
<span>Actions</span>
<i class="ds-icon --icon-ui-arrow-down"></i>
</span>
</summary>
<div class="ds-menu ui-menu__content" style="min-width: 8em;">
<details>
<summary class="ds-text --label">SORACOM Air for cellular</summary>
<ul>
<li>
<a class="--icon-sim" href="#">SIM Management</a>
</li>
<li>
<a class="--icon-email" href="#">Groups</a>
</li>
<li>
<a class="--icon-visible" href="#">Event handler</a>
</li>
<li>
<a class="--icon-light" href="#">VPG</a>
</li>
</ul>
</details>
<div class="ui-menu__section">
<ul class="ui-menu__list" role="none">
<li class="ui-menu__item ui-menu__item-index__0-0">
<button type="button" class="ui-menu__item ui-menu__item-index__0-0">
<ui-span><span>
<ui-text-content><span>Update permissions</span></ui-text-content>
</span></ui-span>
</button>
</li>
<li class="ui-menu__item ui-menu__item-index__0-1">
<button type="button" class="ui-menu__item ui-menu__item-index__0-1">
<ui-span><span>
<ui-text-content><span>Update email address</span></ui-text-content>
</span></ui-span>
</button>
</li>
<li class="ui-menu__item ui-menu__item-index__0-2">
<button type="button" class="ui-menu__item ui-menu__item-index__0-2" disabled="">
<ui-span><span>
<ui-text-content><span>Update password</span></ui-text-content>
</span></ui-span>
</button>
</li>
<li>
<button type="button" class="ui-menu__item ui-menu__item-index__0-3" disabled="">
<ui-span><span>
<ui-text-content><span>Delete</span></ui-text-content>
</span></ui-span>
</button>
</li>
</ul>
</div>
</div>
</details>
</ui-menu>
References
FAQ
Open the menu using javascript
This Boolean attribute indicates whether or not the details — that is, the contents of the <details>
element — are currently visible. The default, false, means the details are not visible.
var details = document.getElementById('my-details');
details.open = true;
Toggle the menu using javascript
In addition to the usual events supported by HTML elements, the <details>
element supports the toggle event, which is dispatched to the <details>
element whenever its state changes between open and closed. It is sent after the state is changed, although if the state changes multiple times before the browser can dispatch the event, the events are coalesced so that only one is sent.
var details = document.getElementById('my-details');
details.addEventListener("toggle", event => {
if (details.open) {
/_ the element was toggled open _/
} else {
/_ the element was toggled closed _/
}
});
Change the width of the menu content
By default - that menu will be as wide as the content - up-to a maximum of 240px
. (So if the content is less than 240px
it will be smaller). You can set a specific size by overriding the class .ds-menu
or by adding an inline style tag.
To override: