import {ExampleCodeBlock, SymbolDoc, Specifications} from '@workday/canvas-kit-docs';
import Basic from './examples/Basic';
import ContextMenu from './examples/ContextMenu';
import Icons from './examples/Icons';
import SelectableMenu from './examples/SelectableMenu';
import Grouping from './examples/Grouping';
import Nested from './examples/Nested';
import NestedDynamic from './examples/NestedDynamic';


# Canvas Kit Menu

`Menu` displays a list of options when triggered by an action or UI element like an icon or button.

[> Workday Design Reference](https://design.workday.com/components/popups/menus)

## Installation

```sh
yarn add @workday/canvas-kit-react
```

## Usage

### Basic Example

`Menu` is typically triggered by an action such as pressing a button. The `Menu` comes with a
`Target` subcomponent and a Popup.

<ExampleCodeBlock code={Basic} />

`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.

### Context Menu

<ExampleCodeBlock code={ContextMenu} />

> **Accessibility Note**: This variation relies on the `contextmenu` browser event, which has
> varying levels of support across different operating systems. On Windows, this feature is better
> supported and users can typically trigger context menus using the **Shift + F10** keyboard
> shortcut or the dedicated **Context Menu** key (if available on their keyboard). However, on
> macOS, context menu support is limited and may require users to enable specific accessibility
> settings in their system preferences to function properly. Consider providing alternative access
> methods for critical functionality.

### 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.

<ExampleCodeBlock code={Icons} />

> **Accessibility Note**: Icons in menu items do not inherently provide text alternatives to
> assistive technologies. However, in most cases, icons are used decoratively alongside text labels,
> and additional text alternatives are not necessary since the menu item text itself provides the
> accessible name.

### Grouping

Grouping adds hierarchy and categorization to menu items. Group headers do not represent menu items
and are not selectable with the keyboard or mouse.

> **Note**: Grouping is not supported in virtual rendering. Menus by default have `shouldVirtualize`
> set to `false`. Setting to `true` results in unspecified behavior. We use `react-virtual` which
> doesn't support nested virtualization.

<ExampleCodeBlock code={Grouping} />

> **Accessibility Note**: Menu groups use `role="group"` with appropriate labeling to provide
> semantic structure for assistive technologies. When navigating through grouped menu items, screen
> readers will announce the group label when users enter a new group, providing important context
> about the organization of the menu. Group headers are not part of the keyboard navigation
> sequence, allowing users to efficiently move between actionable menu items. This semantic grouping
> helps all users, including those using assistive technologies, understand the hierarchy and
> categorization of menu options.

### Nested

Menus support nesting. If you only have a few items and not very many nesting levels, the menu can
be defined statically using JSX. A submenu is defined using the `<Menu.Submenu>` component. The
`Submenu` is implemented as a special `Menu` subcomponent. The API of the submenu is the same as the
`Menu` except the submenu's target is also a menu item. The component is named `TargetItem` to
indicate this dual role.

<ExampleCodeBlock code={Nested} />

> **Accessibility Note**: When a menu item has an attached submenu, the `<Menu.Submenu.TargetItem>`
> includes `aria-haspopup="true"` and `aria-expanded={true | false}` properties. These properties
> will alert screen reader users to the available submenu systems.

### Nested Dynamic Items

Menu nesting is simpler with the dynamic API. In this example, a `renderItem` function is defined to
allow recursive nesting of items using a data structure you define. A submenu will inherit the
`getId` and `getTextValue` functions of the parent menu. While you can pass a specialize `getId` or
`getTextValue` function to each submenu, it may be simpler to use the same one for the menu and
submenus.

<ExampleCodeBlock code={NestedDynamic} />

## Accessibility

Our Menu component is based on the Menu Button pattern on the ARIA Authoring Practices Guide from
the W3C and relies on the roving tabindex technique for managing focus within the opened menu. This
means that the minimum requirements for screen reader support and keyboard navigation are included
in the component.

[Menu Button Pattern | APG | WAI | W3C](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/)

- The `<Menu.Target>` sub-component uses `aria-haspopup="true"` and `aria-expanded={true | false}`
  properties. This benefits screen reader users by indicating when a button element has an attached
  menu.
- The `<Menu.List>` sub-component uses `role="menu"` and `<Menu.Item>` uses `role="menuitem"` ARIA
  roles. These roles allow screen readers to pass through arrow key events to the web application.
- The `<Menu.List>` sub-component includes an `aria-labelledby` ID reference to the `<Menu.Target>`
  sub-component. This assigns a label to the menu for context.

### Navigation

- **Enter or Space**: When focused on the menu button, opens the menu and moves focus to the first
  menu item. When focused on a menu item, activates the item and closes the menu
- **Escape**: Closes the menu and returns focus to the menu button
- **Up & Down Arrow**: Moves focus up and down the menu items
- **Home & End**: Moves focus to the first or last menu item
- **Right & Left Arrow**: When focused on a menu item with a submenu, opens the submenu and moves
  focus to the first item in the submenu or closes the submenu and returns focus to the parent menu
  item

### Screen Reader Experience

- The menu button will be announced with its label text followed by the button role, a notification
  that it has a popup menu, and the current state of the menu (For example: "Actions, button, menu
  popup, collapsed")
- **Opening the Menu:** When the menu button is activated, screen readers will announce the menu
  opening, the number of menu items available, and the currently focused item (For example:
  "Actions, menu, First Action, menu item, 1 of 4.")
- **Navigating Menu Items:** As focus moves between menu items, screen readers will announce the
  item name and its position in the list (For example: "Second Action, menu item, 2 of 4.")
- **Menu Items with Submenus:** When focused on a menu item that has a submenu, screen readers will
  announce that it has a submenu and provide the expanded/collapsed state (For example: "More
  Actions, menu item, has submenu, collapsed, 3 of 4.")

## Component API

<SymbolDoc name="Menu" fileName="/react/" />

## Specifications

<Specifications file="Menu.spec.ts" name="Menu" />