import { MenuExamples, MDXLayoutNext } from '@/components';

export const meta = {
  templateTitle: 'Menu',
  description:
    'Get started with creating dynamic and intuitive menus using Fluid Design. Learn how to use the menu component to improve navigation and user experience.',
  date: '2023-02-01',
  author: 'Oliver Pan',
  tags: [
    'fluid ui',
    'react',
    'framer motion',
    'headless ui',
    'tailwindcss',
    'button',
  ],
};

export default (props) => (
  <MDXLayoutNext meta={meta} components={MenuExamples} {...props} />
);

# Menu

Menus are used to display a list of items using a dropdown components.
Embeded with headless UI, they support a11y features such as keyboard navigation and screen reader support.

<CodeFrame title='Menu Example'>
  <MenuExamples.Default />
</CodeFrame>

```jsx
// @heroicons/react v2
import { Menu } from '@fluid-design/fluid-ui';
import {
  ArrowRightOnRectangleIcon,
  BellIcon,
  CogIcon,
  UserIcon,
} from '@heroicons/react/24/outline';

function Example() {
  return (
    <Menu
      label='Settings'
      color='gray'
      weight='clear'
      iconStart={CogIcon}
      iconEndPosition='between'
      menuPositionY='bottom'
      header='Hi, User'
      className='absolute right-4 top-4'
      menus={[
        {
          label: 'Profile',
          iconStart: UserIcon,
        },
        {
          role: 'separator',
        },
        {
          label: 'Notifications',
          iconStart: BellIcon,
          role: 'info',
        },
      ]}
    />
  );
}
```

## Basic Example

<CodeFrame title='Basic Example'>
  <MenuExamples.Basic />
</CodeFrame>

```jsx
// @heroicons/react v2
import { Menu } from '@fluid-design/fluid-ui';
import { BellIcon, CogIcon, UserIcon } from '@heroicons/react/24/outline';

function Example() {
  return (
    <Menu
      label='Settings'
      color='gray'
      weight='outline'
      iconStart={CogIcon}
      iconEndPosition='between'
      menuPositionY='bottom'
      header='Hi, User'
      menus={[
        {
          label: 'Profile',
          iconStart: UserIcon,
          onClick: () => null,
        },
        {
          role: 'separator',
        },
        {
          label: 'Notifications',
          role: 'info',
          iconStart: BellIcon,
          onClick: () => null,
        },
      ]}
    />
  );
}
```

## Use as component

Menu can also be used as a component to render custom content.
And instead of using the `menus` prop, you can use the `<Menu.Item />` component to render the menu items.
This is useful when you want to render a custom menu.

```jsx
import { Menu } from '@fluid-design/fluid-ui';
import { Fragment } from 'react';

function Example() {
  const avatarImage =
    'https://images.unsplash.com/photo-1626544827763-d516dce335e2?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=80&q=80';
  return (
    <Menu
      className='inline-block'
      color='indigo'
      iconEnd={ChevronRightIcon}
      iconEndPosition='between'
      label='Options'
      menuClassName='w-40'
      menuPositionX='end'
      menuPositionY='center'
      weight='light'
    >
      <Fragment>
        <div className='flex flex-col items-center justify-center gap-2 px-3.5 py-2'>
          <img
            alt='avatar'
            className='h-12 w-12 rounded-full'
            src={avatarImage}
          />
          <p>Custom Menu</p>
        </div>
        <Menu.Item
          className='justify-between'
          isLoading={isEditing}
          role='info'
          loadingOptions={{
            animation: 'pulse',
          }}
        >
          <span>Edit</span>
          <PencilIcon className='h-4 w-4' />
        </Menu.Item>
        <Menu.Item
          className='justify-between'
          disabled={true}
          role='destructive'
        >
          <span>Delete</span>
          <TrashIcon className='h-4 w-4' />
        </Menu.Item>
      </Fragment>
    </Menu>
  );
}
```

## Rendering additional content

You can add custom content to the `<Menu />` component by passing a `children` prop.
However, according to A11y standars and <a href='https:headlessui.com/react/menu#rendering-additional-content' target='_blank' referrerPolicy='no-referrer'>Headless UI</a>,
it is recommended to use the `<Popover />` component instead.

## Component API

### Menu

| Prop                  | Default     | Description                                                                                                                                                                                      |
| --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `badge`               | `undefined` | `string \| number` <Table.D>Badge to be rendered on the right side of the button.</Table.D>                                                                                                      |
| `badgeClassName`      | `undefined` | `string` <Table.D>Class name to be applied to the badge.</Table.D>                                                                                                                               |
| `header`              | `undefined` | `JSX.Element \| string;` <Table.D>Header to be rendered on the top of the menu.</Table.D>                                                                                                        |
| `className`           | `undefined` | `string` <Table.D>Class name to be applied to the menu.</Table.D>                                                                                                                                |
| `menuClassName`       | `undefined` | `string` <Table.D>Class name to be applied to the menu list.</Table.D>                                                                                                                           |
| `buttonClassName`     | `undefined` | `string` <Table.D>Class name to be applied to the button.</Table.D>                                                                                                                              |
| `menuButtonClassName` | `undefined` | `string` <Table.D>Class name to be applied to the menu button.</Table.D>                                                                                                                         |
| `menuPositionX`       | `'start'`   | `'start' \| 'center' \| 'end'` <Table.D>Position of the menu on the X axis.</Table.D>                                                                                                            |
| `menuPositionY`       | `'bottom'`  | `'top' \| 'center' \| 'bottom'` <Table.D>Position of the menu on the Y axis.</Table.D>                                                                                                           |
| `horizontal`          | `false`     | `boolean` <Table.D>Whether the menu should be rendered horizontally.</Table.D>                                                                                                                   |
| `menus`               | `undefined` | `MenuItems[]` <Table.D>Array of menu items to be rendered. Use this prop if you want to render the menu items as a list. Otherwise, use the `children` prop as it will have no effect.</Table.D> |
| `sr`                  | `undefined` | `string` <Table.D>Screen reader text.</Table.D>                                                                                                                                                  |
|                       |

### Menu.Item

| Prop        | Default     | Description                                                                                                                            |
| ----------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `label`     | `undefined` | `string` <Table.D>Label of the menu item.</Table.D>                                                                                    |
| `role`      | `undefined` | `"separator" \| "destructive" \| "default" \| "info" \| "success" \| "warning" \| "primary"` <Table.D>Role of the menu item.</Table.D> |
| `iconStart` | `undefined` | `JSX.Element` <Table.D>Icon to be rendered on the left side of the menu item.</Table.D>                                                |
| `iconEnd`   | `undefined` | `JSX.Element` <Table.D>Icon to be rendered on the right side of the menu item.</Table.D>                                               |

### Menu.Button (Embeded)

Menu button uses `Button` component as a base. You can pass all the props that `Button` component accepts.

| Prop                 | Default     | Description                                                                                                                       |
| -------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `label`              | `undefined` | `string` <Table.D>Label of the button.</Table.D>                                                                                  |
| `labelClassName`     | `undefined` | `string` <Table.D>Class name to be applied to the label.</Table.D>                                                                |
| `icon`               | `undefined` | `JSX.Element` <Table.D>Icon to be rendered on the left side of the button.</Table.D>                                              |
| `iconClassName`      | `undefined` | `string` <Table.D>Class name to be applied to the icon.</Table.D>                                                                 |
| `iconStart`          | `undefined` | `JSX.Element` <Table.D>Icon to be rendered on the left side of the button.</Table.D>                                              |
| `iconStartClassName` | `undefined` | `string` <Table.D>Class name to be applied to the icon start.</Table.D>                                                           |
| `iconEnd`            | `undefined` | `JSX.Element` <Table.D>Icon to be rendered on the right side of the button.</Table.D>                                             |
| `iconEndClassName`   | `undefined` | `string` <Table.D>Class name to be applied to the icon end.</Table.D>                                                             |
| `iconStartPosition`  | `'flex'`    | `'flex' \| 'between'` <Table.D>Position of the icon start. `'between'` will create a gap between the icon and the label</Table.D> |
| `iconEndPosition`    | `'flex'`    | `'flex' \| 'between'` <Table.D>Position of the icon end. `'between'` will create a gap between the icon and the label</Table.D>   |
