Menu
Menu widgets are Interactive Fields (Actions): a button that opens a list of actions, such as the actions of a row. When the user picks one, the menu emits its click event with the action’s value, and closes. Like a button, a menu has no path and puts nothing in the form data.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], label: 'Actions', uid: 'cardActions', onClick: () => 'menuPicked', }), gui.inputs.textInput('menuResult', { hint: 'Pick an action from the menu.', label: 'Last action', readonly: true, }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "cardActions", "label": "Actions", "on": { "click": "menuPicked" }, "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ] } }, { "kind": "input", "type": "textinput", "path": "menuResult", "label": "Last action", "readonly": true, "props": { "hint": "Pick an action from the menu." } } ]}Use these props to customize your Menu widget.
| prop | type | description |
|---|---|---|
items | array | Required. The menu’s items, in order: actions { label, value, disabled? } and separators { separator: true } |
ariaLabel | string | The button’s accessible name when it has no label, such as an icon-only button |
icon | string | An icon on the button, as on the Button |
iconPosition | 'left' | 'right' | The side of the label the icon is on. Defaults to 'left' |
placement | string | Where the menu opens next to its button. Defaults to 'bottom-start' |
variant | 'filled' | 'outlined' | 'link' | The button’s style. Defaults to 'filled' |
The item labels and ariaLabel accept a translation config.
Handling the picked action
Section titled “Handling the picked action”Wire the menu’s click event. In JSON, on: { "click": "<eventName>" } emits that event through your app’s formEvent, and event.detail.value is the picked item’s value. With the DX, onClick takes the event too: unlike a button’s onClick, which gets the form data, a menu’s gets the event, so it can read the value directly.
gui.actions.menu({ label: 'Actions', items: [ { label: 'Edit', value: 'edit' }, { label: 'Delete', value: 'delete' }, ], onClick: (event) => console.log(event.detail.value), // 'edit' or 'delete'});Inside a Repeater, the event also says which row the menu is in: see Events.
Variants
Section titled “Variants”Use the property variant to style the button as on the Button: filled, the default, outlined or link.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], variant: 'outlined', label: 'Outlined', uid: 'menuOutlined', }), gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], variant: 'link', label: 'Link', uid: 'menuLink', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "menuOutlined", "label": "Outlined", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ], "variant": "outlined" } }, { "kind": "action", "type": "menu", "uid": "menuLink", "label": "Link", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ], "variant": "link" } } ]}Use the properties icon and iconPosition to add an icon to the button.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], icon: 'more_vert', iconPosition: 'right', label: 'More', uid: 'menuIcon', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "menuIcon", "label": "More", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ], "icon": "more_vert", "iconPosition": "right" } } ]}Icon Only Menu
Section titled “Icon Only Menu”Leave out the label for an icon-only button, such as the “more” button of a row.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], icon: 'more_vert', variant: 'outlined', ariaLabel: 'Row actions', uid: 'rowActions', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "rowActions", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ], "icon": "more_vert", "variant": "outlined", "ariaLabel": "Row actions" } } ]}Placement
Section titled “Placement”Use the property placement to set where the menu opens: top, bottom, start or end of the button, centered on it, or with -start or -end to line it up with an edge of the button, such as bottom-start, the default, or top-end. Start and end follow the reading direction. When the menu doesn’t fit, it opens on the other side.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], placement: 'top-start', label: 'Opens above', uid: 'menuTop', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "menuTop", "label": "Opens above", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ], "placement": "top-start" } } ]}Disabled
Section titled “Disabled”An item with disabled: true shows in the menu, but the user can’t pick it, and the arrow keys skip it. A menu with disabled: true can’t be opened.
import { gui } from '@golemui/gui-shared';
export default [ gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Archive', value: 'archive', disabled: true, }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], label: 'Actions', uid: 'menuDisabledItem', }), gui.actions.menu({ items: [ { label: 'Edit', value: 'edit', }, { label: 'Duplicate', value: 'duplicate', }, { separator: true, }, { label: 'Delete', value: 'delete', }, ], label: 'Unavailable', disabled: true, uid: 'menuDisabled', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "action", "type": "menu", "uid": "menuDisabledItem", "label": "Actions", "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Archive", "value": "archive", "disabled": true }, { "separator": true }, { "label": "Delete", "value": "delete" } ] } }, { "kind": "action", "type": "menu", "uid": "menuDisabled", "label": "Unavailable", "disabled": true, "props": { "items": [ { "label": "Edit", "value": "edit" }, { "label": "Duplicate", "value": "duplicate" }, { "separator": true }, { "label": "Delete", "value": "delete" } ] } } ]}Keyboard
Section titled “Keyboard”The menu follows the menu button pattern: Enter, Space or ↓ on the button opens it on the first item, and ↑ on the last. In the menu, the arrow keys move between the items, Home and End go to the ends, and typing moves to the item that starts with the letters typed. Enter or Space picks an item, and Escape closes the menu. Both return the focus to the button.
Styling
Section titled “Styling”Menus can be styled as explained in the Styling Guide. The button takes the CSS Variables of the Button.
CSS Variables
Section titled “CSS Variables”Following you will find a list with the CSS Variables and a quick description of what you will style.
| CSS Variable | Description |
|---|---|
--gui-bg-default | Background of the menu |
--gui-border-default | Border of the menu, and the separators |
--gui-radius-md | Border radius of the menu |
--gui-shadow-md | Shadow of the menu |
--gui-bg-surface-hover | Background of the item under the pointer or focused |
--gui-border-focus | Focus outline of an item |
--gui-text-disabled | Text of a disabled item |
--gui-overlay-duration | How long the menu takes to fade in and out |
Anatomy
Section titled “Anatomy”This is the anatomy of the Menu widget in case you want to use your CSS styles.
<gui-menu-interactive class="gui-menu-button gui-field"> <div class="gui-widget"> <button type="button" id="fieldUid" class="gui-button gui-button-icon-left" popovertarget="fieldUid_menu" aria-haspopup="menu" > <span>Actions</span> </button> </div> <gui-menu placement="bottom-start"> <div popover id="fieldUid_menu" role="menu" aria-labelledby="fieldUid"> <button type="button" value="edit" role="menuitem" tabindex="-1">Edit</button> <button type="button" value="archive" disabled role="menuitem" tabindex="-1">Archive</button> <hr /> <button type="button" value="delete" role="menuitem" tabindex="-1">Delete</button> </div> </gui-menu></gui-menu-interactive>