import {
  Story,
  Canvas,
  ArgsTable,
  Meta,
  SourceState,
} from "@storybook/blocks";
import classNames from "classnames";
import { ComponentHeading } from "../../storybook-components";
import { useDisclosure } from "../../hooks";
import { JUSTIFY } from "../../types";
import { Box } from "../Box";
import { Button, BUTTON_SIZE } from "../Button";
import { Modal } from "../Modal";
import { Stack } from "../Stack";
import { Flex } from "../Flex";
import { Icon, ICON_TYPE } from "../Icon";
import { Text } from "../Text";
import { OptionButton } from "./OptionButton";

<Meta title="Components/Buttons/Option Button" component={OptionButton} />

<ComponentHeading
  componentName="Option Button"
  description="The option button component is a fancy radio button used as an option selector"
  sourcePath="src/components/OptionButton/OptionButton.tsx"
/>

## Installation

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

## Basic usage

<Canvas withSource={SourceState.OPEN}>
  <Story name="OptionButton">
    <OptionButton
      heading="Manual"
      description="Don’t create any tickets for me, I’ll make them myself."
    />
  </Story>
</Canvas>

## API

### OptionButton

Extends `React.HTMLProps<HTMLInputElement>`

<ArgsTable of={OptionButton} />

### OptionButton.Group

Extends `StackProps`

<ArgsTable of={OptionButton.Group} />

### OptionButton.Root

Extends `React.HTMLProps<HTMLLabelElement>`

### OptionButton.Content

Extends `BoxProps`

### OptionButton.Heading

Extends `TextProps`

### OptionButton.Description

Extends `TextProps`

### OptionButton.Input

Extends `React.HTMLProps<HTMLInputElement>`

### OptionButton.Backdrop

Extends `BoxProps`

### OptionButton.SelectedIcon

Extends `BoxProps`

## Component tree

Each piece of the `OptionButton` component can be used individually to create a
component with a custom layout. You’ll also be able to control the style of each
individual element.

The component tree is as follows:

```jsx
<OptionButton.Root>
  <OptionButton.Content>
    <OptionButton.Heading />
    <OptionButton.Description />
  </OptionButton.Content>
  <OptionButton.Input />
  <OptionButton.Backdrop />
  <OptionButton.SelectedIcon />
</OptionButton.Root>
```

When building a custom implementation, the following components are considered optional, which means they are not necessary for the overall structure of the component. They are also the components you’re likely to disregard if you’re building a custom layout.

- `OptionButton.Heading`
- `OptionButton.Description`
- `OptionButton.SelectedIcon`

## Demos

### Building a custom implementation

This example shows how you can create a list of custom checkboxes.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Custom implementation">
    <OptionButton.Group name="iconTypes" type="checkbox" spacing={4}>
      {[
        {
          icon: ICON_TYPE.CALCULATOR,
          name: "Calculator",
        },
        {
          icon: ICON_TYPE.ENVELOPE,
          name: "Envelope",
        },
        {
          icon: ICON_TYPE.PAPERCLIP,
          name: "Paperclip",
        },
      ].map((option) => (
        <OptionButton.Root key={option.name} className="rounded p-3">
          <OptionButton.Content>
            <Flex className="items-center gap-x-2">
              <Icon icon={option.icon} />
              <Text className="font-medium">{option.name} icon</Text>
            </Flex>
          </OptionButton.Content>
          <OptionButton.Input value="calculator" disabled={option.disabled} />
          <OptionButton.Backdrop className="bg-white border border-border rounded" />
        </OptionButton.Root>
      ))}
    </OptionButton.Group>
  </Story>
</Canvas>

### Within Group

The main use case for the option button is to display multiple within a group. Make sure each option button has a unique `value` but shares the same `name`.

The `name` prop can be added to `OptionButton.Group` and it will be passed onto each input.

This example renders each `OptionButton` as a radio button (default), but they can also be made checkboxes by passing `type="checkbox"` to the group or each `OptionButton`.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Within Group">
    <OptionButton.Group name="template" type="radio" spacing={4}>
      <OptionButton
        heading="Manual"
        description="Don’t create any tickets for me, I’ll make them myself."
        value="manual"
      />
      <OptionButton
        heading="Basic Recurring"
        description="Create tickets based on a single recurring schedule, without an asset type."
        value="basic"
      />
      <OptionButton
        heading="Asset Based"
        description="Set a default, then create individual recurring or event-based schedules for any asset."
        value="asset"
      />
    </OptionButton.Group>
  </Story>
</Canvas>

### Within Modal

<Canvas withSource={SourceState.OPEN}>
  <Story name="Within Modal">
    {() => {
      const { isOpen, onOpen, onClose } = useDisclosure();
      return (
        <Box>
          <Button onClick={onOpen}>Show Modal</Button>
          <Modal
            title="Modal with OptionButtons"
            isOpen={isOpen}
            onClose={onClose}
          >
            <Modal.Body>
              <OptionButton.Group
                name="template-modal"
                type="radio"
                spacing={4}
              >
                <OptionButton
                  heading="Manual"
                  description="Don’t create any tickets for me, I’ll make them myself."
                  value="manual"
                />
                <OptionButton
                  heading="Basic Recurring"
                  description="Create tickets based on a single recurring schedule, without an asset type."
                  value="basic"
                />
                <OptionButton
                  heading="Asset Based"
                  description="Set a default, then create individual recurring or event-based schedules for any asset."
                  value="asset"
                />
              </OptionButton.Group>
            </Modal.Body>
            <Modal.Footer>
              <Stack justify={JUSTIFY.END}>
                <Button size={BUTTON_SIZE.LARGE}>Some important action</Button>
              </Stack>
            </Modal.Footer>
          </Modal>
        </Box>
      );
    }}
  </Story>
</Canvas>

### Disabling an option

If you need to disable an option, you can do so by passing `disabled` to
OptionButton. This will apply different styles to the OptionButton which can’t
be changed.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Disabled">
    <OptionButton
      heading="Manual"
      description="Don’t create any tickets for me, I’ll make them myself."
      disabled
    />
  </Story>
</Canvas>

You can also build your own custom OptionButton by composing each piece and in
doing so, you’ll be able to set your own styles for the disabled state.

<Canvas withSource={SourceState.OPEN}>
  <Story name="Disabled custom">
    {() => {
      const isDisabled = true;
      return (
        <OptionButton.Root
          className={classNames(
            isDisabled && "cursor-not-allowed",
            "rounded p-3",
          )}
        >
          <OptionButton.Content
            className={classNames(isDisabled && "opacity-50")}
          >
            <Flex className="items-center gap-x-2">
              <Icon icon={ICON_TYPE.CALCULATOR} />
              <Text className="font-medium">Calculator icon</Text>
            </Flex>
          </OptionButton.Content>
          <OptionButton.Input value="calculator" disabled={isDisabled} />
          <OptionButton.Backdrop
            className={classNames(
              isDisabled ? "bg-gray-300" : "bg-white",
              "border border-border rounded",
            )}
          />
        </OptionButton.Root>
      );
    }}
  </Story>
</Canvas>
