import { Meta, Canvas, ArgsTable, Story, SourceState } from "@storybook/blocks";
import { ComponentHeading } from "../../storybook-components";
import { JUSTIFY } from "../../types";
import { Box } from "../Box";
import { Button, BUTTON_VARIANT } from "../Button";
import { Stack } from "../Stack";
import { ICON_TYPE } from "../Icon";
import { PopoverMenu } from "../PopoverMenu";
import { Menu } from "./Menu";

<Meta title="Components/Popovers/Menu" component={Menu} />

<ComponentHeading
  componentName="Menu"
  description="Create a dropdown menu from a given trigger element"
  sourcePath="src/components/Menu/Menu.tsx"
/>

## Installation

```jsx
import { Menu } from "@conveyorhq/arrow-ds";
```

## Basic usage

<Canvas>
  <Story name="Menu">
    <Box className="pb-20 inline-block">
      <Menu
        trigger={(triggerProps, { isOpen }) => (
          <Button {...triggerProps}>{isOpen ? "Close" : "Open"}</Button>
        )}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Box>
  </Story>
</Canvas>

`Menu` uses [`MenuRenderer`](/?path=/docs/components-menurenderer--menu-renderer).
It can be used to create menus with different kinds of buttons. However, the
menu list UI will always remain the same.

If you need a custom designed menu, create a custom implementation of
`MenuRenderer`.

## API

`Menu` uses the same props provided by [`MenuRenderer`](/?path=/docs/components-menurenderer--menu-renderer)
and has no custom props of its own.

<ArgsTable of={Menu} />

## Demos

### Open by default

The menu list / options can be open by default.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Menu button open default">
    <Box className="pb-20 inline-block">
      <Menu
        isOpen
        trigger={(triggerProps, { isOpen }) => {
          return <Button {...triggerProps}>{isOpen ? "Close" : "Open"}</Button>;
        }}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Box>
  </Story>
</Canvas>

### Focus the first option

The first option can have focus when the menu list appears.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Menu button autoFocus">
    <Box className="pb-20 inline-block">
      <Menu
        autoFocus
        trigger={(triggerProps, { isOpen }) => {
          return <Button {...triggerProps}>{isOpen ? "Close" : "Open"}</Button>;
        }}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Box>
  </Story>
</Canvas>

### With portal

The menu list / options will be rendered inside of a portal. This scenario is
useful when dealing with competing z-index values.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Menu button portal">
    <Box className="pb-20 inline-block">
      <Menu
        hasPortal
        trigger={(triggerProps, { isOpen }) => {
          return <Button {...triggerProps}>{isOpen ? "Close" : "Open"}</Button>;
        }}
      >
        <Menu.Item onClick={() => console.log("First item was clicked")}>
          First item
        </Menu.Item>
        <Menu.Item onClick={() => console.log("Second item was clicked")}>
          Second item
        </Menu.Item>
        <Menu.Item onClick={() => console.log("Third item was clicked")}>
          Third item
        </Menu.Item>
      </Menu>
    </Box>
  </Story>
</Canvas>

### Split-button example

<Canvas withSource={SourceState.OPEN}>
  <Story name="Menu split button">
    <Stack className="pb-20">
      <Menu
        placement="bottom-start"
        trigger={(triggerProps, { isOpen, onClose }) => (
          <Button.Group isSegmented>
            <Button
              variant={BUTTON_VARIANT.SECONDARY}
              onClick={() => {
                console.log("Primary Action");
                onClose();
              }}
            >
              Primary Action
            </Button>
            <Button
              variant={BUTTON_VARIANT.SECONDARY}
              icon={isOpen ? ICON_TYPE.CARET_UP : ICON_TYPE.CARET_DOWN}
              depressed={isOpen}
              {...triggerProps}
            />
          </Button.Group>
        )}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Stack>
  </Story>
</Canvas>

### Split-button right-aligned example

<Canvas withSource={SourceState.OPEN}>
  <Story name="Menu split button right aligned">
    <Stack className="pb-20" justify={JUSTIFY.END}>
      <Menu
        placement="bottom-end"
        trigger={(triggerProps, { isOpen, onClose }) => (
          <Button.Group isSegmented>
            <Button
              variant={BUTTON_VARIANT.SECONDARY}
              onClick={() => {
                console.log("Primary Action");
                onClose();
              }}
            >
              Primary Action
            </Button>
            <Button
              variant={BUTTON_VARIANT.SECONDARY}
              icon={isOpen ? ICON_TYPE.CARET_UP : ICON_TYPE.CARET_DOWN}
              depressed={isOpen}
              {...triggerProps}
            />
          </Button.Group>
        )}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Stack>
  </Story>
</Canvas>

### Overflow menu example

<Canvas withSource={SourceState.OPEN}>
  <Story name="Overflow menu">
    <Stack className="pb-20">
      <Menu
        placement="bottom-start"
        trigger={(triggerProps) => (
          <Button
            className="text-brandGreen-400"
            variant={BUTTON_VARIANT.MINIMAL}
            icon={ICON_TYPE.ELLIPSIS_V}
            {...triggerProps}
          />
        )}
      >
        <Menu.Item>First item</Menu.Item>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Stack>
  </Story>
</Canvas>

### Nested menu

To create a nested menu, use the `Menu.ItemMenu` component where you would normally use `Menu.Item`.

The following example shows a nested menu with two levels of depth, but there is no limit to the depth of nested menus.

```jsx
<Menu {...props}>
  <Menu.ItemMenu
    referenceElement={
      <Menu.ItemMenuReference>
        First item
        <Menu.ItemMenuCaretIcon />
      </Menu.ItemMenuReference>
    }
  >
    <PopoverMenu className="w-full">
      <Menu.Item>First nested item</Menu.Item>
      <Menu.Item>Second nested item</Menu.Item>
      <Menu.Item>Third nested item</Menu.Item>
    </PopoverMenu>
  </Menu.ItemMenu>
  <Menu.Item>Second item</Menu.Item>
  <Menu.Item>Third item</Menu.Item>
</Menu>
```

<Canvas withSource={SourceState.OPEN}>
  <Story name="Nested menu">
    <Stack className="pb-20">
      <Menu
        placement="bottom-start"
        trigger={(triggerProps) => (
          <Button
            className="text-brandGreen-400"
            variant={BUTTON_VARIANT.MINIMAL}
            icon={ICON_TYPE.ELLIPSIS_V}
            {...triggerProps}
          />
        )}
      >
        <Menu.ItemMenu
          referenceElement={
            <Menu.ItemMenuReference>
              First item
              <Menu.ItemMenuCaretIcon />
            </Menu.ItemMenuReference>
          }
        >
          <PopoverMenu className="w-full">
            <Menu.Item>First nested item</Menu.Item>
            <Menu.Item>Second nested item</Menu.Item>
            <Menu.Item>Third nested item</Menu.Item>
          </PopoverMenu>
        </Menu.ItemMenu>
        <Menu.Item>Second item</Menu.Item>
        <Menu.Item>Third item</Menu.Item>
      </Menu>
    </Stack>
  </Story>
</Canvas>
