Menu

Menus display a list of up to 15 options when launched by an action or UI element like an icon or button.

yarn add @workday/canvas-kit-react
Install
yarn add @workday/canvas-kit-react

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.

Menu (Preview) Documentation

Anatomy

Image of a Popup Menu sample showing different possible states.

  1. Container: Rectangular container that houses the icon and text for menu list items.
  2. 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.
  3. 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.

KeyAction
Enter or SpaceActivates the menu item and then closes the menu
EscapeCloses the menu
Up ArrowMoves focus to the previous menu item – if focus is on first menu item, it moves focus to the last menu item
Down ArrowMoves focus to the next menu item – if focus is on last menu item, it moves focus to the first menu item
HomeMoves focus to the first menu item
EndMoves focus to the last menu item

Context Menu

Selected:

Icons

Menu supports more complex children, including icons, but the text of the item will no longer be known. In this case, add a data-text attribute to inform the collection system what the text of the item is. The text is used for components that filter based on text. For example, a Select component will jump to an item based on the keys the user types. If the user types "C", the component will jump to the first item that starts with a "C". This functionality requires knowledge about the text of the item.

Selected:

Component API

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 extend from . If a model is passed, props from MenuModelConfig are ignored.

NameTypeDescriptionDefault
childrenReactNode

The contents of the Menu. Can be Menu children or any valid elements.

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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 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 extend from . Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

refReact.Ref<R = >

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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"   },
  
)

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.

Menu.Card supports all props from thelayout component.

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode

Children of the Card. Should contain a <Card.Body> and an optional <Card.Heading>

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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.

useMenuCard

(
  model: ,
  elemProps: {},
  ref: React.Ref
) => {}

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 data-id={item.id}>{item.text}</Menu.Item>}
</Menu.List>
</Menu>
)
}

Menu.List supports all props from thelayout component.

Props extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
children ReactNode ((item: T) => ReactNode)

The label text of the MenuList.

cs

The cs prop takes in a single value or an array of values. You can pass the CSS class name returned by , or the result of and . If you're extending a component already using cs, you can merge that prop in as well. Any style that is passed to the cs prop will override style props. If you wish to have styles that are overridden by the css prop, or styles added via the styled API, use wherever elemProps is used. If your component needs to also handle style props, use instead.

import {handleCsProp} from '@workday/canvas-kit-styling';
import {mergeStyles} from '@workday/canvas-kit-react/layout';
// ...
// `handleCsProp` handles compat mode with Emotion's runtime APIs. `mergeStyles` has the same
// function signature, but adds support for style props.
return (
<Element
{...handleCsProp(elemProps, [
myStyles,
myModifiers({ size: 'medium' }),
myVars({ backgroundColor: 'red' })
])}
>
{children}
</Element>
)
columnCountnumber

If this is set it will cause a wrapping of a list that will turn it into a grid

0
idstring

IDREF of the list. Children ids can be derived from this id

select(data: {
  id: string;
}) => void

Select a specific item by its identifier.

navigation

Controls the state changes when the user sends navigation events to the model. For example, when the user hits the "right" arrow, a behavior hook will determine directionality (left-to-right or right-to-left) and call the correct navigation method. In our example, a left-to-right language would send a getNext. The navigation manager may return the next item in the list. Different managers can be created for slightly different use cases. The default navigation manager will accept orientation and directionality to determine mapping.

An example override might be a tab list with an overflow menu that is meant to be transparent to screen reader users. This would require the overflow menu to accept both up/down keys as well as left/right keys to give a more consistent experience to all users.

getId(item: ) => string

Optional function to return an id of an item. If not provided, the default function will return the id property from the object of each item. If you did not provide items, do not override this function. If you don't provided items and instead provide static items via JSX, the list will create an internal array of items where id is the only property and the default getId will return the desired result.

getTextValue(item: ) => string

Optional function to return the text representation of an item. If not provided, the default function will return the text property of the object of each item or an empty string if there is no text property. If you did not provide items, do not override this function.

nonInteractiveIdsstring[]

Array of all ids which are currently disabled. This is used for navigation to skip over items which are not focusable.

orientation

The orientation of a list of items. Values are either vertical or horizontal. This value will effect which ids activate progression through a list. For example, horizontal will activate with left and right arrows while vertical will activate with up and down arrows.

'vertical'
defaultItemHeightnumber

Best guess to the default item height for virtualization. Getting this number correct avoids a rerender while the list is initializing.

50
shouldVirtualizetrue
items[]

Optional array of items. If provided, use a render prop for list children instead of static children. If the shape of each item object does not have an id property or uses a different property to uniquely identify each item, a getId must also be supplied.

registerItem(data: {
  item: ;
  textValue: string;
}) => void

Register an item to the list. Takes in an identifier, a React.Ref and an optional index. This should be called on component mount. This event is only called for static rendering.

unregisterItem(data: {
  id: string;
}) => void

Unregister an item by its identifier. This should be called when the component is unmounted. This event is only called for static rendering.

updateItemHeight(data: {
  value: number;
}) => void

Updates the default item height. This should only be called when item height is measured. Calling this with a different default item height than previous will cause a virtual list to recalculate the overall height of the list and invalidate any height caching. Doing this only on the first item may save the user from experiencing odd scrolling behavior where the scrollbar updates while scrolling. If the user uses the mouse to drag the bar, it can become "detached" since the browser recalculates scroll bar position while the overflow container is updated.

registerItem(data: {
  item: ;
  textValue: string;
}) => void

Register an item to the list. Takes in an identifier, a React.Ref and an optional index. This should be called on component mount. This event is only called for static rendering.

unregisterItem(data: {
  id: string;
}) => void

Unregister an item by its identifier. This should be called when the component is unmounted. This event is only called for static rendering.

updateItemHeight(data: {
  value: number;
}) => void

Updates the default item height. This should only be called when item height is measured. Calling this with a different default item height than previous will cause a virtual list to recalculate the overall height of the list and invalidate any height caching. Doing this only on the first item may save the user from experiencing odd scrolling behavior where the scrollbar updates while scrolling. If the user uses the mouse to drag the bar, it can become "detached" since the browser recalculates scroll bar position while the overflow container is updated.

initialCursorIdstring

Initial cursor position. If not provided, the cursor will point to the first item in the list

pageSizenumber

Controls how much a pageUp/pageDown navigation request will jump. If not provided, the size of the list and number of items rendered will determine this value.

goTo(data: {
  id: string;
}) => void

Directly sets the cursor to the list item by its identifier.

goToNext() => void

Set the cursor to the "next" item in the list. This event delegates to the getNext method of the navigation manager. For a list, the default navigation manager will wrap if cursor is currently on the last item. For a grid, the default navigation manager will stay on the last item in a row.

goToPrevious() => void

Set the cursor to the "previous" item in the list. If the beginning of the list is detected, it will wrap to the last item

goToPreviousRow() => void

Previous item perpendicular to the orientation of a list, or the previous row in a grid. For example, if a list is horizontal, the previous row would describe an up direction. This could be ignored by the navigation manager, or return the same result as previous(). In a grid, this would be the previous row (current position - column count).

goToNextRow() => void

Next item perpendicular to the orientation of a list, or the next row in a grid. For example, if a list is horizontal, the next row would describe a down direction. This could be ignored by the navigation manager, or return the same result as next(). In a grid, this would be the next row (current position + column count).

goToFirst() => void

Set the cursor to the first item in the list

goToLast() => void

Set the cursor to the last item in the list

goToFirstOfRow() => void
goToLastOfRow() => void
goToNextPage() => void
goToPreviousPage() => void
goTo(data: {
  id: string;
}) => void

Directly sets the cursor to the list item by its identifier.

goToNext() => void

Set the cursor to the "next" item in the list. This event delegates to the getNext method of the navigation manager. For a list, the default navigation manager will wrap if cursor is currently on the last item. For a grid, the default navigation manager will stay on the last item in a row.

goToPrevious() => void

Set the cursor to the "previous" item in the list. If the beginning of the list is detected, it will wrap to the last item

goToPreviousRow() => void

Previous item perpendicular to the orientation of a list, or the previous row in a grid. For example, if a list is horizontal, the previous row would describe an up direction. This could be ignored by the navigation manager, or return the same result as previous(). In a grid, this would be the previous row (current position - column count).

goToNextRow() => void

Next item perpendicular to the orientation of a list, or the next row in a grid. For example, if a list is horizontal, the next row would describe a down direction. This could be ignored by the navigation manager, or return the same result as next(). In a grid, this would be the next row (current position + column count).

goToFirst() => void

Set the cursor to the first item in the list

goToLast() => void

Set the cursor to the last item in the list

goToFirstOfRow() => void
goToLastOfRow() => void
goToNextPage() => void
goToPreviousPage() => void
initialSelectedIds
initialUnselectedIdsstring[]
selection
selectAll() => void

Select all items. This will set selectedIds to 'all' and remove all unselectedIds. This is especially useful for virtual lists where not all items are loaded in memory.

unselectAll() => void

Unselect all items.

select(data: {
  id: string;
}) => void

Select a specific item by its identifier.

selectAll() => void

Select all items. This will set selectedIds to 'all' and remove all unselectedIds. This is especially useful for virtual lists where not all items are loaded in memory.

unselectAll() => void

Unselect all items.

asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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;
  },
  ,
  
)

A Menu.Item has an optional data-id 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, add data-text to the Menu.Item component if using the static API. If you're using the dynamic API, pass getTextValue to the model.

Props extend from button. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
indexnumber

Optionally pass index to menu item. This should be done if Menu.Item components were created via a Array::map function. This index will ensure keyboard navigation works even if items are inserted out of order.

childrenReactNode

The label text of the MenuItem.

data-idstring

The name of the menu item. This name will be used in the onSelect callback in the model. If this property is not provided, it will default to a string representation of the the zero-based index of the Tab when it was initialized.

aria-disabledboolean
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

button
refReact.Ref<R = button>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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;
  },
  ,
  ,
  
)

Props extend from hr. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReact.ReactNode
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

hr
refReact.Ref<R = hr>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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 extend from . Changing the as prop will change the element interface.

NameTypeDescriptionDefault
childrenReactNode
asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

refReact.Ref<R = >

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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"   },
  
)

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 extend from div. Changing the as prop will change the element interface.

NameTypeDescriptionDefault
anchorElement <Element> Element null

The reference element used to position the Popper. Popper content will try to follow the anchorElement if it moves and will reposition itself if there is no longer room in the window.

children ((props: {
    placement: ;
  }) => ReactNode)
ReactNode

The content of the Popper. If a function is provided, it will be treated as a Render Prop and pass the placement chosen by PopperJS. This placement value is useful if your popup needs to animate and that animation depends on the direction of the content in relation to the anchorElement.

getAnchorClientRect() => 

When provided, this optional callback will be used to determine positioning for the Popper element instead of calling getBoundingClientRect on the anchorElement prop. Use this when you need complete control over positioning. When this prop is specified, it is safe to pass null into the anchorElement prop. If null is passed into the anchorElement prop, an owner will not be provided for the PopupStack.

openboolean

Determines if Popper content should be rendered. The content only exists in the DOM when open is true

true
placement

The placement of the Popper contents relative to the anchorElement. Accepts auto, top, right, bottom, or left. Each placement can also be modified using any of the following variations: -start or -end.

fallbackPlacements[]

Define fallback placements by providing a list of in array (in order of preference). The default preference is following the order of top, right, bottom, and left. Once the initial and opposite placements are not available, the fallback placements will be in use. Use an empty array to disable the fallback placements.

onPlacementChange(placement: ) => void

A callback function that will be called whenever PopperJS chooses a placement that is different from the provided placement preference. If a placement preference doesn't fit, PopperJS will choose a new one and call this callback.

popperOptions<PopperOptions>

The additional options passed to the Popper's popper.js instance.

portalboolean

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 false, you may experience issues where you content gets cut off by scrollbars or overflow: hidden

true
popperInstanceRefRef<>

Reference to the PopperJS instance. Useful for making direct method calls on the popper instance like update.

asReact.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 React.forwardRefand spread extra props to a root element.

Note: Not all elements make sense and some elements may cause accessibility issues. Change this value with care.

div
refReact.Ref<R = div>

Optional ref. If the component represents an element, this ref will be a reference to the real DOM element of the component. If as is set to an element, it will be that element. If as is a component, the reference will be to that component (or element if the component uses React.forwardRef).

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(
  model: ,
  elemProps: TProps
) => HTML Attributes

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;
}

useMenuModel

useMenuModel (config: ):

Specifications

GivenWhenThen
the Basic story is rendered
    • it should pass axe checks
    the Basic story is rendered
      • it should have aria-haspopup set to true
      the Basic story is rendered
        • it should have aria-expanded set to false
        the Basic story is rendered
          • it should not show a menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • it should set aria-expanded to true
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • it should show menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • it should transfer focus to the first menu item
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • it should have aria-disabled=true
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN escape key is pressed
          • it should have aria-expanded set to false
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN escape key is pressed
          • it should not show a menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN escape key is pressed
          • return focus to the "Open Menu" button
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN down arrow key is pressed
          • it should transfer focus to the second item
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN down arrow key is pressed
          • AND THEN the enter key is pressed
          • it should have aria-expanded set to false
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN down arrow key is pressed
          • AND THEN the enter key is pressed
          • it should not show a menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN down arrow key is pressed
          • AND THEN the enter key is pressed
          • it should select the second item
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the second item is clicked
          • it should have aria-expanded set to false
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the second item is clicked
          • it should not show a menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the second item is clicked
          • it should select the second item
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the fourth item is clicked
          • it should not close the menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the fourth item is clicked
          • it should have aria-expanded set to true
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the fourth item is clicked
          • it should not select the fourth item
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the tab key is pressed
          • it should have aria-expanded set to false
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN the tab key is pressed
          • it should not show a menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN up arrow key is pressed
          • it should focus on the last option
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN up arrow key is pressed
          • AND THEN the enter key is pressed
          • it should not close the menu
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN up arrow key is pressed
          • AND THEN the enter key is pressed
          • it should have aria-expanded set to true
          the Basic story is rendered
          • the "Open Menu" button is clicked
          • AND THEN up arrow key is pressed
          • AND THEN the enter key is pressed
          • it should not select the fourth item
          the MenuWithFallbackPlacements example is rendered
          • check the fallback placements the preferred placement is set to top
          • it should show the fallback placement: bottom
          the MenuWithFallbackPlacements example is rendered
          • check the fallback placements the preferred placement is set to right
          • it should show the fallback placement: left
          the MenuWithFallbackPlacements example is rendered
          • check the fallback placements the preferred placement is set to right
          • it should show the fallback placement: bottom
          Source: Menu.spec.ts

          Accessibility Guidelines

          Keyboard Interaction

          Each menu item must have a focus indicator that is highly visible against the background and against the non-focused state. Refer to Accessible Colors for more information.

          Menus must support the following keyboard interactions:

          • Enter or Space: activates the focused menu item
          • Esc: dismisses the opened menu and returns focus to the button that invoked the menu
          • Up Arrow or Down Arrow: navigates among the menu items cyclically
          • Home or End: navigates to the first menu item, or the last menu item respectively

          Screen Reader Interaction

          Menus must communicate the following to users:

          • A button will invoke a menu or popup
          • Focus has been moved into an opened menu
          • The correct number of items in the menu
          • The name of the focused menu item

          Design Annotations Needed

          • Write an accessible name for icon-only button variants invoking menus.
          • Declare whether any icons used in menu items are decorative, or require additional text alternatives.

          Implementation Markup Needed

          • For buttons invoking menus, anaria-haspopup=”true” property and an aria-expanded attribute must be added.
          • [Included in component] The menu container must have an ARIA `role=”menu” attribute.
          • [Included in component] All child elements inside the menu container must have an ARIA `role=”menuitem” attribute.
          • [Included in component] Use “roving tabindex” technique for managing focus inside the menu. Set tabindex=”0” on the focused menu item, and set to ”-1” on remaining menu items.

          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