Menu
Menus display a list of up to 15 options when launched by an action or UI element like an icon or button.
Menu (Main) vs. Menu (Preview)
We recommend you use the Menu in the Main package (@workday/canvas-kit-react
) documented here on
this page. The Menu in the Preview package (@workday/canvas-kit-preview-react
) has been
marked for soft-deprecation in
Canvas Kit v8 and will be removed in v9.
Anatomy
- Container: Rectangular container that houses the icon and text for menu list items.
- Text: Text for indicating where the link leads to when the menu is clicked on. Text can overflow to the next line but avoid going over more than two lines of text.
- Icons: Icons are optional and can be positioned before or after the text.
Usage Guidance
- Popup Menus can appear next to, in front of, above, or below the element that launched them, such as Dropdown Buttons, Dropdown Icons, icon only Primary/Secondary/Tertiary Button variants or by right-clicking a contextual item.
- Popup Menus should overlap and visually look like they are in front of other UI elements. They should always be positioned within the viewable areas of the screen and be 8px away from the element that launched them.
- Popup Menus should always contain a list of menu selections, which are options users can choose from. The list should be scannable, kept as concise as possible, and written in title case instead of sentences.
- Consider how important each option is. The list of options should be sorted in a logical order, such as alphabetical, chronological, order of importance, and so on.
When to Use
- In most cases, as with Overflow Menus, where there aren't enough space on screen to show all the actions, there could be between 1-7 items to choose from. However, there shouldn't be more than 15 items listed at once on a single Popup Menu.
- When users must make a single selection from the list of options.
When to Use Something Else
- Consider using a Switch if the only options are yes or no.
- For a list between 2 to 7 predefined options, consider using a Radio input to select one option or Checkboxes to select multiple options. Radio and Checkbox groups display all options upfront and do not require the user to interact with the input to view the list of options.
- Use a Prompt when the number of list items is large or unknown. Prompts have search capabilities and folders which provide users with the means to browse options. Prompts can be configured to support single or multi-select.
Examples
Basic Example
Menu
is typically triggered by an action such as pressing a button. The Menu
comes with a
Target
subcomponent and a Popup.
Selected:
Menu
will automatically focus on the cursor item (first item by default). The Menu
uses a menu
model which composes a list model and a popup model and sets up accessibility features for you.
Menu
follows the
Actions Menu pattern
using roving tabindex. Below is table of supported keyboard shortcuts and associated actions.
Key | Action |
---|---|
Enter or Space | Activates the menu item and then closes the menu |
Escape | Closes the menu |
Up Arrow | Moves focus to the previous menu item – if focus is on first menu item, it moves focus to the last menu item |
Down Arrow | Moves focus to the next menu item – if focus is on last menu item, it moves focus to the first menu item |
Home | Moves focus to the first menu item |
End | Moves focus to the last menu item |
Context Menu
Selected:
Icons
Selected:
Component API
Menu
Menu
is a combination of a popup and a list. It usually has some type of target element that
expands/collapses the menu and a menu
role and and several menuitem
roles. Focus is managed
using roving tabindex for maximum
compatibility. A Menu
can have two modes: single
and multiple
. This mode determines both
how many items can be selected as well as the default behavior when a menuitem
is clicked. For
the single
mode, selecting a menuitem
will select and close the menu. For the multiple
mode, clicking a menuitem
will toggle selection and will not close the menu.
<Menu><Menu.Target>Open</Menu.Target><Menu.Popper><Menu.Card><Menu.List><Menu.Item data-id="first">First Item</Menu.Item><Menu.Item data-id="second">Second Item</Menu.Item></Menu.List></Menu.Card></Menu.Popper></Menu>
Props
Props extend from . If a model
is passed, props from MenuModelConfig
are ignored.
Name | Type | Description | Default |
---|---|---|---|
children | ReactNode | The contents of the Menu. Can be | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
Menu.Target
Menu.Target
is similar to all types. The component only
provides behavior and no styling. The
as
prop is used to determine which component is
rendered. This component should forward the ref
and apply any additional props directly to
an element. The default as
is a . Any Canvas Kit component should
work with an
as
.
An example changing to a
<Menu.Target as={PrimaryButton}>Primary Button Text</Menu.Target>
This element will apply aria-haspopup
and aria-expanded
to inform screen readers there's
a popup associated with the element.
Props
Props extend from . Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
children | ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. |
|
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
useMenuTarget
(
  unknown {
  "kind": "unknown",
  "value": "unknown",
  "text": "useMenuTargetBase"
  },
 Â
)
Menu.Card
The menu card is a non-semantic element used to give the dropdown menu its distinct visual cue that the dropdown menu is floating above other content. A menu card usually contains a menu list, but can also contain other elements like a header or footer.
Layout Component
Menu.Card
supports all props from thelayout component.
Props
Props extend from div. Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
children | ReactNode | Children of the Card. Should contain a | |
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
Menu.List
The menu list follows the Collections API. A list can either contain static items
or a render prop and items
to the model.
const MyComponent = () => {const model = useMenuModel({items: [{ id: 'first', text: 'First Item' },{ id: 'second', text: 'Second Item' },]})return (<Menu model={model}><Menu.List>{(item) => <Menu.Item name={item.id}>{item.text}</Menu.Item>}</Menu.List></Menu>)}
Layout Component
Menu.List
supports all props from thelayout component.
Props
Props extend from div. Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
children | ReactNode |Â ((item:Â T)Â =>Â ReactNode) | The label text of the MenuList. | |
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
useMenuList
(
  model: ,
  elemProps: {},
  ref: React.Ref
)Â =>Â {
  role: string;
  aria-labelledby: string;
}
Menu.Item
A menu item has an optional name
prop that identifies the item in the menu list and will be
passed to the optional onSelect
callback of the menu model. A menu item can contain any
HTML. If more complex HTML is provided, consider
Props
Props extend from button. Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
index | number | Optionally pass index to menu item. This should be done if | |
children | ReactNode | The label text of the MenuItem. | |
data-id | string | The name of the menu item. This name will be used in the | |
aria-disabled | boolean | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | button |
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
useMenuItem
(
  (
    model: ,
    elemProps: {
      data-id: string;
    },
    ref: React.Ref
  ) => {
    ref: (instance: | null) => void;
    role: string;
    onClick: ((event: SyntheticEvent) => void) | undefined;
  },
  ,
  ,
 Â
)
Menu.Divider
Props
Props extend from hr. Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
children | React.ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | hr |
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If |
Menu.TargetContext
A Menu.TargetContext
is the same as a , except it adds a
context
event handler instead of a click
handler to trigger context menus.
Props
Props extend from . Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
children | ReactNode | ||
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. |
|
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
useMenuTargetContext
(
  unknown {
  "kind": "unknown",
  "value": "unknown",
  "text": "useMenuTargetBase"
  },
 Â
)
Menu.Popper
The "Popper" of a menu. The popper will appear around the . It
renders a
div
element that is portalled to the document.body
which is controlled by the
. The
PopupStack
is not part of React. This means no extra props given to
this component will be forwarded to the div
element, but the ref
will be forwarded.
Props
Props extend from div. Changing the as
prop will change the element interface.
Name | Type | Description | Default |
---|---|---|---|
anchorElement | <Element> |Â Element |Â null | The reference element used to position the Popper. Popper content will try to follow the
| |
children | ((props:Â { | The content of the Popper. If a function is provided, it will be treated as a Render Prop and
pass the | |
getAnchorClientRect | ()Â =>Â | When provided, this optional callback will be used to determine positioning for the Popper element
instead of calling | |
open | boolean | Determines if | true |
placement |
| The placement of the |
|
fallbackPlacements | [] | Define fallback placements by providing a list of | |
onPlacementChange | (placement:Â )Â =>Â void | A callback function that will be called whenever PopperJS chooses a placement that is different
from the provided | |
popperOptions | <PopperOptions> | The additional options passed to the Popper's | |
portal | boolean | If false, render the Popper within the
DOM hierarchy of its parent. A non-portal Popper will constrained by the parent container
overflows. If you set this to | true |
popperInstanceRef | Ref | Reference to the PopperJS instance. Useful for making direct method calls on the popper
instance like | |
as | React.ElementType | Optional override of the default element used by the component. Any valid tag or Component. If you provided a Component, this component should forward the ref using Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care. | div |
ref | React.Ref | Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If | |
model |
| Optional model to pass to the component. This will override the default model created for the component. This can be useful if you want to access to the state and events of the model, or if you have nested components of the same type and you need to override the model provided by React Context. | |
elemPropsHook | ( | Optional hook that receives the model and all props to be applied to the element. If you use this, it is your responsibility to return props, merging as appropriate. For example, returning an empty object will disable all elemProps hooks associated with this component. This allows finer control over a component without creating a new one. |
usePopupPopper
Adds the necessary props to a component. Used by the
subcomponent.
(
  model: ,
  elemProps: {},
  ref: React.Ref
)Â =>Â {
  open: boolean;
  anchorElement: <>;
  ref: (instance: | null) => void;
  onPlacementChange: (placement: ) => void;
}
Model
useMenuModel
useMenuModel (config: ):
Specifications
Given | When | Then |
---|---|---|
the Basic story is rendered |
| |
the Basic story is rendered |
| |
the Basic story is rendered |
| |
the Basic story is rendered |
| |
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the Basic story is rendered |
|
|
the MenuWithFallbackPlacements example is rendered |
|
|
the MenuWithFallbackPlacements example is rendered |
|
|
the MenuWithFallbackPlacements example is rendered |
|
|
Accessibility Guidelines
- When the Menu is displayed, the focus should move onto the first option in the Menu.
- The Menu as a whole should only receive one focus stop on each list item.
- Up and down arrows must be used to navigate the Menu.
Content Guidelines
- When writing Menu list items, refer to the Menus section of the Content Style Guide.
Can't Find What You Need?
Check out our FAQ section which may help you find the information you're looking for.
FAQ Section