summaryrefslogtreecommitdiff
path: root/src/components/Button.js
blob: d5b88cf7737252305c76a37943946d0f5156dba5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React from 'react';
import cx from 'classnames';

import type { Node, Element, SyntheticEvent } from 'react';

import { LoadingDot } from './shared/Basic';

import s0 from './Button.module.css';

const { memo, forwardRef, useCallback } = React;

type ButtonProps = {
  children?: Node,
  label?: string,
  text?: string,
  isLoading?: boolean,
  start?: Element | (() => Element),
  onClick?: (SyntheticEvent<HTMLButtonElement>) => mixed,
  kind?: 'primary' | 'minimal'
};
function Button(props: ButtonProps, ref) {
  const { onClick, isLoading, kind = 'primary', ...restProps } = props;
  const internalOnClick = useCallback(
    e => {
      if (isLoading) return;
      onClick && onClick(e);
    },
    [isLoading, onClick]
  );
  const btnClassName = cx(s0.btn, {
    [s0.minimal]: kind === 'minimal'
  });
  return (
    <button className={btnClassName} ref={ref} onClick={internalOnClick}>
      {isLoading ? (
        <>
          <span
            style={{
              display: 'inline-flex',
              opacity: 0
            }}
          >
            <ButtonInternal {...restProps} />
          </span>
          <span className={s0.loadingContainer}>
            <LoadingDot />
          </span>
        </>
      ) : (
        <ButtonInternal {...restProps} />
      )}
    </button>
  );
}

function ButtonInternal({ children, label, text, start }) {
  return (
    <>
      {start ? (
        <span className={s0.btnStart}>
          {typeof start === 'function' ? start() : start}
        </span>
      ) : null}
      {children || label || text}
    </>
  );
}

export default memo(forwardRef(Button));