import {
  Meta,
  Canvas,
  ArgsTable,
  Story,
  SourceState,
} from "@storybook/blocks";
import { ComponentHeading } from "../../storybook-components";
import { Box } from "../Box";
import { Button } from "../Button";
import { PopoverMenu } from "../PopoverMenu";
import { MenuRenderer } from "./MenuRenderer";

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

<ComponentHeading
  componentName="MenuRenderer"
  description="Used to build menu components"
  sourcePath="src/components/MenuRenderer/MenuRenderer.tsx"
  hideDemosLink
/>

## Installation

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

## Basic usage

<Canvas withSource={SourceState.OPEN}>
  <Story name="MenuRenderer">
    <Box className="pb-20">
      <MenuRenderer
        hasPortal
        trigger={(triggerProps, { isOpen }) => (
          <Button {...triggerProps}>{isOpen ? "Close" : "Open"}</Button>
        )}
      >
        {({ listProps, itemProps, onClose }) => (
          <PopoverMenu className="w-56" {...listProps}>
            {["Item one", "Item two"].map((item) => (
              <Box
                key={item}
                className="px-4 py-3 rounded-sm"
                onClick={() => {
                  console.log(item);
                  if (typeof onClose === "function") {
                    onClose();
                  }
                }}
                {...itemProps}
              >
                {item}
              </Box>
            ))}
          </PopoverMenu>
        )}
      </MenuRenderer>
    </Box>
  </Story>
</Canvas>

[`Menu`](/?path=/docs/components-menu--menu) uses `MenuRenderer` internally.

Implementations of this component must provide a `trigger` that can accept event
handlers and ARIA properties used to manage the interactions.

In addition, the `triggerProps` that are provided within the trigger render
function must be spread onto the desired trigger element. The state object
`{ isOpen, onClose }` use is optional depending on your implementation.

The list and options are rendered inside of a render function with access to the
interal state which is detailed below:

```jsx
listProps: {
  id: string;
  role: string;
  tabIndex: number;
  "aria-labelledby": string;
};
itemProps: {
  tabIndex: number;
  role: string;
};
isOpen?: boolean;
onClose?: () => void;
buttonId?: string;
menuId?: string;
onToggle?: (event: Event | React.MouseEvent<HTMLButtonElement>) => void;
onOpen?: () => void;
placement?: PopperPlacement;
```

## API

These are the custom props that extend [`BoxProps`](/?path=/docs/components-box--box#all-props).

<ArgsTable of={MenuRenderer} />

## Demos

### Controlled example

To control the menu visibility with extenal state, pass `isMenuOpen` and
`openMenu` props.

<Canvas withSource={SourceState.OPEN}>
  <Story name="MenuRenderer controlled">
    {() => {
      const [open, setOpen] = React.useState(false);
      return (
        <Box className="pb-20">
          <MenuRenderer
            hasPortal
            isMenuOpen={open}
            openMenu={setOpen}
            trigger={(triggerProps) => (
              <button
                type="button"
                {...triggerProps}
                onClick={() => setOpen(!open)}
              >
                Control
              </button>
            )}
          >
            {({ listProps, itemProps, onClose }) => (
              <PopoverMenu className="w-56" {...listProps}>
                {["Item one", "Item two"].map((item) => (
                  <Box
                    key={item}
                    className="px-4 py-3 rounded-sm"
                    onClick={() => {
                      console.log(item);
                      if (typeof onClose === "function") {
                        onClose();
                      }
                    }}
                    {...itemProps}
                  >
                    {item}
                  </Box>
                ))}
              </PopoverMenu>
            )}
          </MenuRenderer>
        </Box>
      );
    }}
  </Story>
</Canvas>
