69 lines
1.6 KiB
TypeScript
69 lines
1.6 KiB
TypeScript
import React, { HTMLAttributes, useMemo } from 'react';
|
|
|
|
import { keyframes } from '@/theme';
|
|
|
|
import {
|
|
ButtonSpinnerProps,
|
|
StyledButtonSpinnerBox,
|
|
StyledButtonSpinnerDot,
|
|
StyledButtonSpinnerDotsBox,
|
|
} from './button-spinner.styles';
|
|
|
|
export const ButtonSpinner: React.FC<ButtonSpinnerProps> = (props) => {
|
|
const {
|
|
label,
|
|
placement,
|
|
spacing = '$2',
|
|
children,
|
|
className,
|
|
...rest
|
|
} = props;
|
|
|
|
const marginProp = placement === 'start' ? 'marginRight' : 'marginLeft';
|
|
|
|
const spinnerStyles = useMemo(
|
|
() => ({
|
|
position: label ? 'relative' : 'absolute',
|
|
[marginProp]: label ? spacing : 0,
|
|
}),
|
|
[label, marginProp, spacing]
|
|
);
|
|
|
|
return (
|
|
<StyledButtonSpinnerBox className={className} css={spinnerStyles} {...rest}>
|
|
{children || <ButtonSpinnerDots />}
|
|
</StyledButtonSpinnerBox>
|
|
);
|
|
};
|
|
|
|
const blink = keyframes({
|
|
'0%': { opacity: 0.2 },
|
|
'50%': { opacity: 1 },
|
|
'100%': { opacity: 0.2 },
|
|
});
|
|
|
|
const ButtonSpinnerDots: React.FC<HTMLAttributes<HTMLDivElement>> = (props) => {
|
|
return (
|
|
<StyledButtonSpinnerDotsBox {...props}>
|
|
<StyledButtonSpinnerDot
|
|
css={{
|
|
animation: `${blink} infinite linear 2s`,
|
|
animationDelay: '0ms',
|
|
}}
|
|
/>
|
|
<StyledButtonSpinnerDot
|
|
css={{
|
|
animation: `${blink} infinite linear 2s`,
|
|
animationDelay: '250ms',
|
|
}}
|
|
/>
|
|
<StyledButtonSpinnerDot
|
|
css={{
|
|
animation: `${blink} infinite linear 2s`,
|
|
animationDelay: '500ms',
|
|
}}
|
|
/>
|
|
</StyledButtonSpinnerDotsBox>
|
|
);
|
|
};
|