diff options
Diffstat (limited to 'src/components/shared/Button.tsx')
| -rw-r--r-- | src/components/shared/Button.tsx | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/components/shared/Button.tsx b/src/components/shared/Button.tsx new file mode 100644 index 0000000..5ecf029 --- /dev/null +++ b/src/components/shared/Button.tsx @@ -0,0 +1,82 @@ +import cx from 'clsx'; +import * as React from 'react'; + +import { LoadingDot } from './Basic'; +import s0 from './Button.module.scss'; + +const { forwardRef, useCallback } = React; + +type ButtonInternalProps = { + children?: React.ReactNode; + label?: string; + text?: string; + start?: React.ReactNode | (() => React.ReactNode); +}; + +type ButtonProps = { + isLoading?: boolean; + onClick?: (e: React.MouseEvent<HTMLButtonElement>) => unknown; + disabled?: boolean; + kind?: 'primary' | 'minimal'; + className?: string; + title?: string; +} & ButtonInternalProps; + +function Button(props: ButtonProps, ref: React.Ref<HTMLButtonElement>) { + const { + onClick, + disabled = false, + isLoading, + kind = 'primary', + className, + children, + label, + text, + start, + ...restProps + } = props; + const internalProps = { children, label, text, start }; + const internalOnClick = useCallback( + (e: React.MouseEvent<HTMLButtonElement>) => { + if (isLoading) return; + onClick && onClick(e); + }, + [isLoading, onClick], + ); + const btnClassName = cx(s0.btn, { [s0.minimal]: kind === 'minimal' }, className); + return ( + <button + className={btnClassName} + ref={ref} + onClick={internalOnClick} + disabled={disabled} + {...restProps} + > + {isLoading ? ( + <> + <span style={{ display: 'inline-flex', opacity: 0 }}> + <ButtonInternal {...internalProps} /> + </span> + <span className={s0.loadingContainer}> + <LoadingDot /> + </span> + </> + ) : ( + <ButtonInternal {...internalProps} /> + )} + </button> + ); +} + +function ButtonInternal({ children, label, text, start }: ButtonInternalProps) { + return ( + <div className={s0.btnInternal}> + {start && ( + <span className={s0.btnStart}>{typeof start === 'function' ? start() : start}</span> + )} + {children || label || text} + </div> + ); +} + +export default forwardRef(Button); |
