import {
  Story,
  Canvas,
  ArgsTable,
  Meta,
  SourceState,
} from "@storybook/blocks";
import { Accessibility, ComponentHeading } from "../../storybook-components";
import { useDisclosure, useStep } from "../../hooks";
import { JUSTIFY } from "../../types";
import { EnumTable } from "../../storybook-components/EnumTable";
import { Box } from "../Box";
import { Flex } from "../Flex";
import { Button, BUTTON_SIZE, BUTTON_VARIANT } from "../Button";
import { FormGroup } from "../FormGroup";
import { Label } from "../Label";
import { Input } from "../Input";
import { Paragraph } from "../Paragraph";
import { Stack } from "../Stack";
import { Checkbox } from "../Checkbox";
import { Tab } from "../Tab";
import { Table } from "../Table";
import { Select } from "../Select";
import { Modal, MODAL_SIZE } from "./Modal";
import { ExampleModalContent } from "./_story";

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

<ComponentHeading
  componentName="Modal (Dialog)"
  description="An overlay to show content that prevents interaction with the rest of the application"
  sourcePath="src/components/Modal/Modal.tsx"
/>

The modal contains a portal by default, so there is no need to wrap it in one in
the application.

## Installation

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

## Basic usage

<Canvas>
  <Story name="Default">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Default Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            disableOutsideClick={false}
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

## API

<ArgsTable of={Modal} />
<EnumTable enums={{ MODAL_SIZE }} />

<Accessibility
  keyboardInteractions={[
    {
      key: "Escape",
      description: "Dismisses the modal.",
    },
  ]}
/>

## Demos

## Custom implementation

Components of Modal can be composed to create a custom implementation. The idea
is that the consuming app can build its own implementation of a modal by having
access to every individual component.

When building a custom modal, there are minimal styles included; mainly those
required for positioning and layering. This gives the consuming app complete
control over how the modal looks without resorting to workarounds.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Custom implementation">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Default Modal</Button>
          <Modal.Root
            isOpen={isOpen}
            onClose={onClose}
            disableOutsideClick={false}
            disableEscClose={false}
          >
            <Modal.Portal>
              <Modal.Overlay autoFocus>
                <Flex className="absolute inset-0 items-center justify-center">
                  <Modal.Content className="bg-white p-8 rounded w-2/5">
                    <Box>Modal</Box>
                    <Box>
                      <Modal.Close>Close</Modal.Close>
                    </Box>
                  </Modal.Content>
                </Flex>
                <Modal.Screen />
              </Modal.Overlay>
            </Modal.Portal>
          </Modal.Root>
        </>
      );
    }}
  </Story>
</Canvas>

### Sizes

Modals can be one of three sizes: “default”, “large” or “full”.

All modals have a maximum height of 100vh - 88px margin.

| Size      | Width                |
| --------- | -------------------- |
| `default` | 640px                |
| `large`   | 818px                |
| `full`    | 100vw - 88 px margin |

<Canvas>
  <Story name="Default size modal">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Default Size Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            size={MODAL_SIZE.DEFAULT}
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
  <Story name="Large size modal">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Large Size Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            size={MODAL_SIZE.LARGE}
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
  <Story name="Full size modal">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Full Size Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            size={MODAL_SIZE.FULL}
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### With secondary title

You can add a secondary title to the modal which will be displayed in the
header.

<Canvas>
  <Story name="With secondary title">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Modal with Secondary Title</Button>
          <Modal
            title="Modal component"
            secondaryTitle="An optional secondary title"
            isOpen={isOpen}
            onClose={onClose}
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Button.Group justify={JUSTIFY.END}>
                <Button autoFocus onClick={onClose} size={BUTTON_SIZE.LARGE}>
                  Cancel and close
                </Button>
              </Button.Group>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### With scrolling body

The body of the modal scrolls when there is too much content to display in view.
No prop is required. This example is just to illustrate the behavior.

<Canvas>
  <Story name="With scrolling body">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Modal with Scrolling Body</Button>
          <Modal title="Modal component" isOpen={isOpen} onClose={onClose}>
            <Modal.Body>
              <ExampleModalContent />
              <ExampleModalContent />
              <ExampleModalContent />
              <ExampleModalContent />
              <ExampleModalContent />
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Non-closable modal

For mandatory workflows and notifications where specific actions must be taken,
all methods to close the modal can be removed. In these instances, the modal is
usually dimissed by a button within the modal footer.

Non-closable modals use a combination of props to establish this pattern. Each
of the props can be used on their own as well, depending on which close
functionality you need to disable.

For example, if a modal contains a select component, you may want to disable
the escape-to-close feature as the escape key is also used to dismiss the
select popover menu.

<Canvas>
  <Story name="Non-closable modal">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Non-closable Modal</Button>
          <Modal
            title="Please confirm this action"
            isOpen={isOpen}
            onClose={onClose}
            hideCloseButton
            disableEscClose
            disableOutsideClick
          >
            <Modal.Body>
              <Paragraph>
                Duis vulputate dui quis commodo cursus. In fermentum efficitur
                vehicula. Integer nec felis varius, ultrices erat ac, volutpat
                lectus. Proin eu dolor sed magna accumsan blandit a ac nisl.
              </Paragraph>
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE} onClick={onClose}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Enable auto focus

Setting the autoFocus prop on the modal will automatically add focus to the
first focusable element, which in many cases is the close button. This behavior
is acceptable when the modal doesn't have a form.

<Canvas>
  <Story name="Enable auto focus">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Auto Focus Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            autoFocus
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button size={BUTTON_SIZE.LARGE}>Confirm</Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Center modal

The modal can be centered vertically.

<Canvas>
  <Story name="Modal center">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Center Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            center
          >
            <Modal.Body>
              <ExampleModalContent />
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button autoFocus size={BUTTON_SIZE.LARGE}>
                  Confirm
                </Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Wizard example

The modal can be used to display a set up wizard or any kind of UI where
multiple steps are involved. To do this, you would use the `useStep` hook.

You can also use the `Modal.FooterMultiStep` component in place of the regular
`Modal.Footer`. The multi-step footer provides some additional UI; a progress
indicator and optional next / previous button labels.

<Canvas>
  <Story name="Wizard example">
    {() => {
      const wizardSteps = [
        {
          id: "1",
          title: "Create a Procedure",
          label: "Step 1. This is text for the first step",
          content: (
            <>
              <Box>Step 1</Box>
              <ExampleModalContent />
            </>
          ),
        },
        {
          id: "2",
          title: "Select some options",
          label: "Step 2. This is text for the second step",
          content: (
            <>
              <Box>Step 2</Box>
              <ExampleModalContent />
            </>
          ),
        },
        {
          id: "3",
          title: "Add configuration",
          label: "Step 3. This is text for the third step",
          content: (
            <>
              <Box>Step 3</Box>
              <ExampleModalContent />
            </>
          ),
        },
        {
          id: "4",
          title: "Finish up",
          label: "Step 4. This is text for the fourth step",
          content: (
            <>
              <Box>Step 4</Box>
              <ExampleModalContent />
            </>
          ),
        },
      ];
      const totalSteps = wizardSteps.length;
      const { isOpen, onOpen, onClose } = useDisclosure();
      const {
        step,
        goToNextStep,
        goToPreviousStep,
        goToStep,
        currentStepIndex,
        nextStepIndex,
        previousStepIndex,
        isFirstStep,
        isLastStep,
      } = useStep({
        steps: totalSteps,
      });
      return (
        <>
          <Button onClick={onOpen}>Show Wizard Modal</Button>
          <Modal
            title={wizardSteps[currentStepIndex].title}
            secondaryTitle={`Step ${step} of ${totalSteps}`}
            isOpen={isOpen}
            onClose={onClose}
          >
            <Modal.Body>{wizardSteps[currentStepIndex].content}</Modal.Body>
            <Modal.FooterMultiStep
              steps={totalSteps}
              currentStep={step}
              leftButtonLabel={
                isFirstStep ? "" : wizardSteps[previousStepIndex].label
              }
              rightButtonLabel={
                isLastStep ? "" : wizardSteps[nextStepIndex].label
              }
            >
              <Button.Group justify={JUSTIFY.END}>
                {!isFirstStep && (
                  <Button.Group className="mr-auto">
                    <Button
                      size={BUTTON_SIZE.LARGE}
                      variant={BUTTON_VARIANT.SECONDARY}
                      onClick={goToPreviousStep}
                    >
                      Previous
                    </Button>
                  </Button.Group>
                )}
                {isLastStep ? (
                  <Button
                    size={BUTTON_SIZE.LARGE}
                    onClick={() => {
                      onClose();
                      goToStep(1);
                    }}
                  >
                    Create
                  </Button>
                ) : (
                  <Button size={BUTTON_SIZE.LARGE} onClick={goToNextStep}>
                    Next
                  </Button>
                )}
              </Button.Group>
            </Modal.FooterMultiStep>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Form example

One of the main use cases for the modal is to show a form. In these cases, the
first input of the form should be focused by adding `autoFocus` to the input.

<Canvas>
  <Story name="Form example">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      const onSubmit = (event) => {
        console.log("onSubmit");
        event.preventDefault();
        return false;
      };
      return (
        <>
          <Button onClick={onOpen}>Show Form Modal</Button>
          <Modal title="Modal component" isOpen={isOpen} onClose={onClose}>
            <form onSubmit={onSubmit}>
              <Modal.Body>
                <FormGroup>
                  <Label htmlFor="name">Name</Label>
                  <Input name="name" id="name" type="text" autoFocus />
                </FormGroup>
                <FormGroup>
                  <Label htmlFor="email">Email</Label>
                  <Input name="email" id="email" type="email" />
                </FormGroup>
                <FormGroup>
                  <Label htmlFor="email">Favorite ice cream</Label>
                  <Select
                    options={[
                      { value: "chocolate", label: "Chocolate" },
                      { value: "strawberry", label: "Strawberry" },
                      { value: "vanilla", label: "Vanilla" },
                    ]}
                    menuInPortal
                  />
                </FormGroup>
              </Modal.Body>
              <Modal.Footer>
                <Stack reverse>
                  <Button type="submit" size={BUTTON_SIZE.LARGE}>
                    Submit
                  </Button>
                  <Button
                    size={BUTTON_SIZE.LARGE}
                    variant={BUTTON_VARIANT.SECONDARY}
                    onClick={onClose}
                  >
                    Cancel
                  </Button>
                </Stack>
              </Modal.Footer>
            </form>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### With tabs

This example shows how you can use tabbed content inside of a modal.

<Canvas>
  <Story name="With tabs">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      const [tab, setTab] = React.useState(0);
      return (
        <>
          <Button onClick={onOpen}>Show Tabs Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={() => {
              onClose();
              setTab(0);
            }}
          >
            <Modal.Tabs>
              <Tab active={tab === 0} autoFocus onClick={() => setTab(0)}>
                First Tab
              </Tab>
              <Tab active={tab === 1} onClick={() => setTab(1)}>
                Second Tab
              </Tab>
            </Modal.Tabs>
            {tab === 0 && (
              <>
                <Modal.Body>
                  <ExampleModalContent />
                </Modal.Body>
                <Modal.Footer>
                  <Stack reverse>
                    <Button size={BUTTON_SIZE.LARGE}>Confirm</Button>
                    <Button
                      size={BUTTON_SIZE.LARGE}
                      variant={BUTTON_VARIANT.SECONDARY}
                      onClick={onClose}
                    >
                      Cancel
                    </Button>
                  </Stack>
                </Modal.Footer>
              </>
            )}
            {tab === 1 && (
              <>
                <Modal.Body>
                  <Stack spacing={6}>
                    <ExampleModalContent />
                    <ExampleModalContent />
                    <ExampleModalContent />
                  </Stack>
                </Modal.Body>
                <Modal.Footer>
                  <Stack reverse>
                    <Button size={BUTTON_SIZE.LARGE}>
                      Some other important action
                    </Button>
                  </Stack>
                </Modal.Footer>
              </>
            )}
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### With table

Show a table in a modal. Set Modal.Body padding to false.

<Canvas>
  <Story name="With table">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      const [filters, setFilters] = React.useState({
        number: [],
        evenOrOdd: [],
      });
      const [
        numberFilterOptionSearch,
        setNumberFilterOptionSearch,
      ] = React.useState("");
      const rowData = [];
      for (let i = 0; i < 10; i += 1) {
        rowData.push({ number: i, evenOrOdd: i % 2 === 0 ? "even" : "odd" });
      }
      const handleFilterOptionChange = (e, column) => {
        if (e.target.checked) {
          setFilters({
            ...filters,
            [column]: [...filters[column], e.target.value],
          });
        } else {
          const index = filters[column].indexOf(e.target.value);
          if (index > -1) {
            const filterColumnCopy = [...filters[column]];
            filterColumnCopy.splice(index, 1);
            setFilters({ ...filters, [column]: filterColumnCopy });
          }
        }
      };
      const FilterOption = ({ option, column, ...rest }) => (
        <Checkbox
          label={option}
          onChange={(e) => handleFilterOptionChange(e, column)}
          value={option}
          {...rest}
        />
      );
      const getReducedFilterOptions = (column) =>
        rowData.reduce((acc, row) => {
          if (numberFilterOptionSearch) {
            if (!`${row[column]}`.includes(numberFilterOptionSearch)) {
              return acc;
            }
          }
          return acc.some((item) => row[column] === item)
            ? acc
            : [...acc, row[column]];
        }, []);
      const getVisibleFilterOptions = (column) => {
        return getReducedFilterOptions(column)
          .slice(0, 7)
          .map((option) => (
            <FilterOption
              option={`${option}`}
              key={option}
              column={column}
              checked={filters[column].some((filter) => filter === `${option}`)}
            />
          ));
      };
      const handleSelectAllNumberFilters = () => {
        setFilters({
          ...filters,
          number: rowData.map((row) => `${row.number}`),
        });
      };
      const handleClearAllNumberFilters = () => {
        setFilters({ ...filters, number: [] });
      };
      return (
        <>
          <Button onClick={onOpen}>Show Table Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            size={MODAL_SIZE.FULL}
          >
            <Modal.Body padded={false}>
              <Table renderInModal>
                <Table.Head>
                  <Table.Row>
                    <Table.HeaderCell
                      visibleFilterOptions={getVisibleFilterOptions("number")}
                      totalFilterOptions={
                        getReducedFilterOptions("number").length
                      }
                      filterApplied={filters.number.length !== 0}
                      onSelectAllFilters={handleSelectAllNumberFilters}
                      onClearFilters={handleClearAllNumberFilters}
                      searchInputValue={numberFilterOptionSearch}
                      onSearchInputChange={setNumberFilterOptionSearch}
                      sortable={false}
                    >
                      Number
                    </Table.HeaderCell>
                    <Table.HeaderCell
                      sortable={false}
                      visibleFilterOptions={getVisibleFilterOptions(
                        "evenOrOdd",
                      )}
                      totalFilterOptions={
                        getReducedFilterOptions("evenOrOdd").length
                      }
                      filterApplied={filters.evenOrOdd.length !== 0}
                      hideFilterSearch
                    >
                      Even or Odd
                    </Table.HeaderCell>
                  </Table.Row>
                </Table.Head>
                <Table.Body>
                  {rowData
                    .filter((row) => {
                      if (
                        filters.number.length === 0 &&
                        filters.evenOrOdd.length === 0
                      ) {
                        return true;
                      }
                      const filterMatch = { number: false, evenOrOdd: false };
                      Object.keys(row).forEach((column) => {
                        if (
                          filters[column].length === 0 ||
                          filters[column].some(
                            (filter) => filter === `${row[column]}`,
                          )
                        ) {
                          filterMatch[column] = true;
                        }
                      });
                      return filterMatch.number && filterMatch.evenOrOdd;
                    })
                    .map((row) => {
                      return (
                        <Table.Row key={row.number}>
                          <Table.Cell>{row.number}</Table.Cell>
                          <Table.Cell>{row.evenOrOdd}</Table.Cell>
                        </Table.Row>
                      );
                    })}
                </Table.Body>
              </Table>
            </Modal.Body>
            <Modal.Footer>
              <Stack reverse>
                <Button size={BUTTON_SIZE.LARGE}>Confirm</Button>
                <Button
                  size={BUTTON_SIZE.LARGE}
                  variant={BUTTON_VARIANT.SECONDARY}
                  onClick={onClose}
                >
                  Cancel
                </Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Without a header

Hide the header to create a custom layout.

<Canvas>
  <Story name="Without a header">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <>
          <Button onClick={onOpen}>Show Modal without a header</Button>
          <Modal isOpen={isOpen} onClose={onClose} noHeader>
            <Box className="p-10 relative">
              <Modal.CloseButton className="absolute top-0 right-0" />
              <Box>
                I am not using any of the modal subcomponents. I am a custom
                layout.
              </Box>
            </Box>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>

### Dynamically controlling disableEscClose prop

There are times when you might want to use <kbd>escape</kbd> to control a
component inside of a modal. Previously, you would need to set `disableEscClose`
to false in order to preserve <kbd>escape</kbd> for the component instead of
closing the modal.

Here’s an example showing a Select component inside of a modal and how you can
control both the Select and Modal with <kbd>escape</kbd>.

To do so, we need to track the open state of the select. Then we can pass that
state variable to the `disableEscClose` prop.

When the select menu is open, the first <kbd>escape</kbd> keypress closes the
select menu. The second <kbd>escape</kbd> keypress closes the modal.

<Canvas>
  <Story name="Dynamically controlling disableEscClose prop">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      const [isSelectOpen, setIsSelectOpen] = React.useState(false);
      return (
        <>
          <Button onClick={onOpen}>Show Modal</Button>
          <Modal
            title="Modal component"
            isOpen={isOpen}
            onClose={onClose}
            disableEscClose={isSelectOpen}
          >
            <Modal.Body>
              <Box style={{ height: "400px" }}>
                <Select
                  autoFocus
                  placeholder="Favorite ice cream?"
                  options={[
                    { value: "chocolate", label: "Chocolate" },
                    { value: "strawberry", label: "Strawberry" },
                    { value: "vanilla", label: "Vanilla" },
                  ]}
                  onMenuOpen={() => {
                    setIsSelectOpen(true);
                  }}
                  onMenuClose={() => {
                    setIsSelectOpen(false);
                  }}
                  menuInPortal
                />
              </Box>
            </Modal.Body>
          </Modal>
        </>
      );
    }}
  </Story>
</Canvas>
