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.

`Menu` follows the
[Actions Menu pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button/examples/menu-button-actions/)
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

<ExampleCodeBlock code={ContextMenu} />

### 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} />

### Selectable Menu

The `Menu.Item` renders a `role=menuitem` element which does not have `aria-selected` and thus no
selected state. If you wish your menu to have selectable menu items, use `Menu.Option` instead of
`Menu.Item`. The `Menu.Option` is meant to be used when the `Menu.Card` has a role of `listbox` and
is controlled via `aria-activedescendant`. This example uses `Menu.Option` to should what the
checkmark looks like, but the example is not keyboard or screen reader accessible. There are many
other behaviors that need to be composed into the `Menu.Target` and `Menu.List` components and the
behaviors depend on many other things. To see a full example of all these behaviors, look at the
`<Combobox>` and `<Select>` component source code as examples.

<ExampleCodeBlock code={SelectableMenu} />

### 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} />

### 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} />

### 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} />

## Component API

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

## Specifications

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