/* eslint-disable react/button-has-type */ import { useStyledTheme } from '@pfb/hooks/useTheme'; import { Theme } from '@pfb/models/theme.model'; import { ButtonHTMLAttributes, PropsWithChildren, useCallback, MouseEvent, forwardRef, ReactNode, } from 'react'; import { keyframes } from '@emotion/core'; export interface ButtonProps { primary?: boolean; error?: boolean; link?: boolean; transparent?: boolean; after?: ReactNode; } const getColorPair = (theme: Theme, props: ButtonProps) => { if (props.primary) { return theme.colors.primary; } if (props.error) { return theme.colors.error; } if (props.link) { return { backgroundColor: 'transparent', color: theme.elements.link.color, borderColor: 'transparent', }; } if (props.transparent) { return { backgroundColor: 'transparent', color: theme.elements.link.color, borderColor: 'transparent', }; } return theme.colors.default; }; const rippleTransition = keyframes` to { transform: scale(4); opacity: 0; }`; const styles = (props: { primary: boolean; error: boolean; link: boolean; transparent: boolean; }) => (theme: Theme) => { const colorPairByProps = getColorPair(theme, props); return { button: { width: '100%', color: colorPairByProps.color, borderRadius: '4px', fontWeight: 'bold' as const, padding: `${theme.spacing(1)} ${theme.spacing(4)}`, border: '1px solid', borderColor: colorPairByProps.borderColor, backgroundColor: colorPairByProps.backgroundColor, position: 'relative' as const, overflow: 'hidden', transition: 'background 400ms', outline: '0', boxShadow: !props.link && !props.transparent && '0 0 0.5rem rgba(0, 0, 0, 0.3)', cursor: 'pointer', gridGap: theme.spacing(1), display: 'grid', gridAutoFlow: 'column', 'span.ripple': { position: 'absolute' as const, borderRadius: '50%', transform: 'scale(0)', animation: `${rippleTransition} 600ms linear`, backgroundColor: 'rgba(255, 255, 255, 0.7)', }, ':disabled': { backgroundColor: theme.palette.neutral, borderColor: theme.palette.darkerNeutral, color: theme.palette.darkerNeutral, cursor: 'not-allowed', }, }, }; }; export const Button = forwardRef< HTMLButtonElement, PropsWithChildren> >((props, ref) => { const { children, primary = false, error = false, link = false, transparent = false, after, onClick, ...otherProps } = props; const styled = useStyledTheme(styles({ primary, error, link, transparent })); console.log(styled.button.backgroundColor, 'transparent', transparent); const createRipple = useCallback( (event: MouseEvent) => { if (!!onClick) { onClick(event); } const button = event.currentTarget; const circle = document.createElement('span'); const diameter = Math.max(button.clientWidth, button.clientHeight); const radius = diameter / 2; circle.style.width = `${diameter}px`; circle.style.height = `${diameter}px`; circle.style.left = `${event.clientX - button.offsetLeft - radius}px`; circle.style.top = `${event.clientY - button.offsetTop - radius}px`; circle.classList.add('ripple'); circle.addEventListener('animationend', () => button.removeChild(circle)); button.appendChild(circle); }, [onClick], ); return ( ); });