import { createElement } from 'react';
import { Canvas, Meta, Source, Story } from '@storybook/addon-docs/blocks';
import Button from 'components/Button';
import ButtonGroup from 'components/ButtonGroup';
import { toast as launch, ToastContainer } from 'components/Toast';
import CWBTheme, { ThemeProvider } from 'styles/CWBTheme';

<Meta title="Components API/Toast" />

# Toast & ToastContainer

Toasts give the user feedback in the form of an auto-dismissable notification.

<Canvas>
  <Story name="Toast">
    <ToastContainer />
    <ButtonGroup direction="column">
      <Button onClick={() => launch.error('Error Toast!')}>
        Launch Error Toast
      </Button>
      <Button onClick={() => launch.warning('Warning Toast!')}>
        Launch Warning Toast
      </Button>
      <Button onClick={() => launch.success('Success Toast!')}>
        Launch Success Toast
      </Button>
      <Button onClick={() => launch.info('Info Toast!')}>
        Launch Info Toast
      </Button>
      <Button
        onClick={() =>
          launch.error(
            'Here is a toast with a longer message. The text wraps to multiple lines.'
          )
        }
      >
        Launch Multiline Toast
      </Button>
    </ButtonGroup>
  </Story>
</Canvas>

<Source code="import { toast } from 'cwb-react';" />

## Usage

In order to use Toasts, you need to import and render a `<ToastContainer />` in your project. There should only be one ToastContainer at all times, so it is advised to put it at the root level (or close to the root level) of your project. This makes sure that the toasts are anchored correctly and show up at the top right corner of the screen.

<Source code="import { ToastContainer } from 'cwb-react';" />

The default settings for ToastContainer are as follows, you **do not need to pass them** again when rendering ToastContainer.

<Source
  code={
    '{\n' +
    '  position: toast.POSITION.TOP_RIGHT,\n' +
    '  autoClose: 6000,\n' +
    '  hideProgressBar: true,\n' +
    '  closeOnClick: false,\n' +
    '  draggable: false\n' +
    '}'
  }
/>

There are four Toast variants. The `toast.error` API features no auto-close, while the others auto-close after 6 seconds. The APIs take one required argument of type `string` or `ReactNode` and one optional argument of type object, which represent the `options` passed to [react-toastify](https://github.com/fkhadra/react-toastify)'s `toast` API, and returns a `toastId` of type `number`.

<Source
  code={
    '// no auto-close\n' +
    `toast.error('Error');\n` +
    '\n' +
    `// auto-closes after 6 seconds\n` +
    `toast.warning('Warning');\n` +
    `toast.success('Success');\n` +
    `toast.info('Info');`
  }
/>

Toast also provides the `toast.update` API, with which you can update an already launched toast. This can be useful when implementing an "undo action toast".

<ThemeProvider theme={CWBTheme}>
  <Canvas style={{ marginBottom: '0' }}>
    {createElement(() => {
      const launchToast = () => {
        let toastId;
        const toastInner = () => {
          return (
            <div
              style={{
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'space-between'
              }}
            >
              Action performed.
              <button
                style={{
                  color: '#0F9BF0',
                  backgroundColor: 'white',
                  border: 'none',
                  fontSize: '14px',
                  fontWeight: '600'
                }}
                onClick={() =>
                  launch.update(toastId, {
                    render: 'Undo complete.',
                    type: launch.TYPE.INFO,
                    autoClose: 1000
                  })
                }
              >
                UNDO
              </button>
            </div>
          );
        };
        toastId = launch.success(toastInner);
      };
      return <Button onClick={launchToast}>Launch Undoable Toast</Button>;
    })}
  </Canvas>
  <div style={{ marginTop: '-20px' }}>
    <Source
      code={
        'const launchToast = () => {\n' +
        '  let toastId;\n' +
        '\n' +
        '  // define the toast content as a ReactNode\n' +
        '  const toastInner = () => {\n' +
        '    return (\n' +
        '      <div\n' +
        '        style={{\n' +
        `          display: 'flex',\n` +
        `          alignItems: 'center',\n` +
        `          justifyContent: 'space-between'\n` +
        '        }}\n' +
        '      >\n' +
        '        Action performed.\n' +
        '        <button\n' +
        '          style={{\n' +
        `            color: '#0F9BF0',\n` +
        `            backgroundColor: 'white',\n` +
        `            border: 'none',\n` +
        `            fontSize: '14px',\n` +
        `            fontWeight: '600'\n` +
        '          }}\n' +
        '          onClick={() => toast.update(toastId, {\n' +
        `            render: 'Undo complete.',\n` +
        '            type: toast.TYPE.INFO,\n' +
        '            autoClose: 1000\n' +
        '          })}\n' +
        '        >\n' +
        '          UNDO\n' +
        '        </button>\n' +
        '      </div>\n' +
        '    );\n' +
        '  };\n' +
        '\n' +
        '  toastId = toast.success(toastInner);\n' +
        '};\n' +
        '\n' +
        'return (\n' +
        '  <Button onClick={launchToast}>\n' +
        '    Launch Undoable Toast\n' +
        '  </Button>\n' +
        ');'
      }
    />
  </div>
</ThemeProvider>

For more information on toast options, as well as what you can do with the `toastId`, see the [react-toastify documentation](https://fkhadra.github.io/react-toastify/introduction).

<Source
  code={
    '// Launch a warning toast with text "Foobar" in the bottom right corner\n' +
    `const options = { position: 'bottom-right' };\n` +
    `const toastId = toast.warning('Foobar', options);\n` +
    'console.log(typeof toastId); // number'
  }
/>
