import { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs';
import { CheckboxInput } from './CheckboxInput';
import { Box } from '../Box/Box';
import { FormLabel } from '../FormLabel/FormLabel';

<Meta title="Components/CheckboxInput/Overview" component={CheckboxInput} />

# CheckboxInput

Use a CheckboxInput to allow users to make a range of selections (zero, one or many).

<Canvas isExpanded>
  <CheckboxInput
    id="example"
    label="Checkbox with a label"
    isChecked
    onChange={() => {}}
  />
</Canvas>

## Props

<ArgsTable of={CheckboxInput} />

## Default

All that is required to render a basic version of the CheckboxInput is a unique `id`, a `label`, `isChecked`, and an onchange event handler passed to the `onChange` prop.

<Canvas>
  <Story
    name="Default"
    parameters={{
      design: {
        type: 'figma',
        url: 'https://www.figma.com/file/k1kOsplTGXvSSMQQCzhCND/Palmetto-Design-System?node-id=787%3A8277',
      },
    }}
  >
    {() => {
      const [value, setValue] = useState(null);
      return (
        <CheckboxInput
          id="defaultStateIsUnchecked"
          label="Label"
          onChange={event => setValue(event.target.checked)}
          isChecked={value}
        />
      );
    }}
  </Story>
</Canvas>

## States

The state of a checkbox can be `checked`, `unchecked` or `indeterminate`. For More
details on indeterminate checkboxes [See Here](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#indeterminate).

An important consideration is that a checkbox being `indeterminate` has no effect on the value of it's `checked` value. Accordingly
we have kept this prop separate and affect the checkbox visually as well as the value of the indeterminate HTML attribute on the checkbox
element. I.E: A checkbox can be indeterminate while being either checked or unchecked. The logic for such UI implementations is left
up to the user.

<Canvas>
  <Story name="States">
    {() => {
      return (
        <Box gap="md">
          <CheckboxInput
            id="statesUnchecked"
            label="Unchecked"
            onChange={() => {}}
            isChecked={false}
          />
          <CheckboxInput
            id="statesCHecked"
            label="Checked"
            onChange={() => {}}
            isChecked={true}
          />
          <CheckboxInput
            id="statesUnchecked"
            label="Indeterminate"
            onChange={() => {}}
            isChecked={true}
            isIndeterminate={true}
          />
        </Box>
      );
    }}
  </Story>
</Canvas>

## Indeterminate Checkboxes

Use cases for intermediate checkboxes can sometimes be unclear. Below is an example of when to use this UI pattern.

<Canvas>
  <Story name="Indeterminate Checkboxes">
    {() => {
      const [exampleOneChildOne, setExampleOneChildOne] = useState(false);
      const [exampleOneChildTwo, setExampleOneChildTwo] = useState(true);
      const handleParentChange = event => {
        setExampleOneChildOne(event.target.checked);
        setExampleOneChildTwo(event.target.checked);
      };
      return (
        <Box gap="md">
          <Box display="block" fontWeight="bold">
            Nested Checkboxes (select all)
          </Box>
          <Box gap="sm">
            <CheckboxInput
              id="statesUnchecked"
              label="Parent"
              onChange={handleParentChange}
              isChecked={exampleOneChildOne || exampleOneChildTwo}
              isIndeterminate={exampleOneChildOne !== exampleOneChildTwo}
            />
            <Box padding="0 0 0 sm" gap="sm">
              <CheckboxInput
                id="statesUnchecked"
                label="Child One"
                onChange={event => setExampleOneChildOne(event.target.checked)}
                isChecked={exampleOneChildOne}
              />
              <CheckboxInput
                id="statesUnchecked"
                label="Child Two"
                onChange={event => setExampleOneChildTwo(event.target.checked)}
                isChecked={exampleOneChildTwo}
              />
            </Box>
          </Box>
        </Box>
      );
    }}
  </Story>
</Canvas>

## Required

Use the `isRequired` prop to set the `required` and `aria-required` on the underlying input element.

<Canvas>
  <Story name="Required">
    {() => {
      const [value, setValue] = useState(null);
      return (
        <CheckboxInput
          id="requiredCheckboxIsUnchecked"
          label="Required Checkbox"
          isChecked={value}
          onChange={event => setValue(event.target.checked)}
          isRequired
        />
      );
    }}
  </Story>
</Canvas>

You can remove or customize the required indicator using the `requiredIndicator` prop.

<Canvas>
  <Story name="Custom Required Indicator">
    {() => {
      const [value, setValue] = useState(false);
      const [value2, setValue2] = useState(false);
      return (
        <Box gap="md">
          <CheckboxInput
            id="requiredCheckboxNull"
            label="Required Without Indicator"
            isChecked={value}
            onChange={event => setValue(event.target.checked)}
            isRequired
            requiredIndicator={null}
          />
          <CheckboxInput
            id="requiredCheckboxCustom"
            label="Required Custom Indicator"
            isChecked={value2}
            onChange={event => setValue2(event.target.checked)}
            isRequired
            requiredIndicator=" (required)"
          />
        </Box>
      );
    }}
  </Story>
</Canvas>

## Sizes

Set the size of the checkbox and label with the `size` prop.

<Canvas>
  <Story name="Sizes">
    {() => {
      const [sm, setSm] = useState(null);
      const [md, setMd] = useState(null);
      const [lg, setLg] = useState(null);
      const [responsive, setResponsive] = useState(null);
      return (
        <Box gap="md">
          <CheckboxInput
            id="smCheckboxInput"
            label="Small checkbox"
            helpText="More helpful text about this checkbox"
            isChecked={sm}
            onChange={event => setSm(event.target.checked)}
            size="sm"
          />
          <CheckboxInput
            id="mdCheckboxInput"
            label="Medium checkbox"
            helpText="More helpful text about this checkbox"
            isChecked={md}
            onChange={event => setMd(event.target.checked)}
            size="md"
          />
          <CheckboxInput
            id="lgCheckboxInput"
            label="Large checkbox"
            helpText="More helpful text about this checkbox"
            isChecked={lg}
            onChange={event => setLg(event.target.checked)}
            size="lg"
          />
          <CheckboxInput
            id="responsiveCheckboxInput"
            label="Responsive checkbox"
            helpText="Will change sizes depending on viewport width"
            isChecked={responsive}
            onChange={event => setResponsive(event.target.checked)}
            size={{ base: 'sm', tablet: 'md', desktop: 'lg', hd: 'sm' }}
          />
        </Box>
      );
    }}
  </Story>
</Canvas>

## Help Text

Use `helpText` to add additional context to the checkbox.
This can help keep checkbox label concise.

<Canvas>
  <Story name="Help Text">
    {() => {
      const [value, setValue] = useState(null);
      return (
        <CheckboxInput
          id="helpTextCheckbox"
          label="Checkbox with help text"
          helpText="More helpful text about this checkbox"
          isChecked={value}
          onChange={event => setValue(event.target.checked)}
        />
      );
    }}
  </Story>
</Canvas>

## Checked Initial State

Use the `isChecked` prop to mark the input as checked upon initial render.

<Canvas>
  <Story name="Checked Initial State">
    {() => {
      const [value, setValue] = useState(true);
      return (
        <CheckboxInput
          id="initialStateChecked"
          label="Label"
          onChange={value => setValue(event.target.checked)}
          isChecked={value}
        />
      );
    }}
  </Story>
</Canvas>

## Hidden Label

The `label` is a required prop, but if you need to hide it for stylistic reasons, you can do
so with the `hideLabel` prop. The checkbox will still utilize the label string value to
populate the `aria-label` property on the input for accessibility reasons.

<Canvas>
  <Story name="Hidden Label">
    {() => {
      const [value, setValue] = useState(null);
      return (
        <CheckboxInput
          id="hiddenLabel"
          hideLabel
          onChange={value => setValue(event.target.checked)}
          isChecked={value}
        />
      );
    }}
  </Story>
</Canvas>

## Disabled and Unchecked

Use the `isDisabled` prop to disable an input.

<Canvas>
  <Story name="Disabled">
    {() => (
      <Box gap="md">
        <CheckboxInput
          id="disabledAndUnchecked"
          label="Disabled and Unchecked"
          isChecked={false}
          onChange={() => {}}
          isDisabled
        />
        <CheckboxInput
          id="disabledAndChecked"
          label="Disabled and Checked"
          isChecked={true}
          onChange={() => {}}
          isDisabled
        />
      </Box>
    )}
  </Story>
</Canvas>

## Error

Use the `error` prop to mark the input as invalid. `error` accepts a `boolean`, `string`, or `node`. If either a `string` or `node` is passed, a validation message is displayed below it.

<Canvas>
  <Story name="Error">
    {() => {
      const [value, setValue] = useState(null);
      return (
        <CheckboxInput
          id="invalidCheckbox"
          label="Label"
          isChecked={value}
          onChange={value => setValue(event.target.checked)}
          isRequired
          error="You must accept the Terms and Conditions"
        />
      );
    }}
  </Story>
</Canvas>
