Untitled
unknown
plain_text
a month ago
3.4 kB
3
Indexable
Never
import React from "react"; import styles from "./button.module.scss"; type ButtonVariants = "standard" | "outline" | "icon-outline" | "icon-filled"; type ButtonColorSchema = "primary" | "secondary"; type ButtonSize = "sm" | "md" | "lg"; interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>{ children: React.ReactNode; variant: ButtonVariants, colorSchema?: ButtonColorSchema, size?: ButtonSize, } enum ButtonStates{ IDLE, ANIMATING } enum MouseStates { IDLE, PRESSING, } enum TransitionStates { IDLE, FORWARD, FORWARD_END, BACKWARD } type MouseButtonStates = { button: ButtonStates; mouse: MouseStates; transition: TransitionStates }; export default function Button({children, variant="standard", colorSchema="primary", size="md"}:ButtonProps): React.ReactElement{ const buttonRef: React.MutableRefObject<HTMLButtonElement | null> = React.useRef<HTMLButtonElement | null>(null); const states:React.MutableRefObject<MouseButtonStates> = React.useRef<MouseButtonStates>( { button: ButtonStates.IDLE, mouse: MouseStates.IDLE, transition: TransitionStates.IDLE } ); const press = (): void =>{ buttonRef.current!.classList.add(styles.press); states.current.button = ButtonStates.ANIMATING; states.current.transition = TransitionStates.FORWARD } const release = ():void =>{ buttonRef.current!.classList.remove(styles.press); states.current.transition = TransitionStates.BACKWARD; } const onMouseDown = (): void =>{ states.current.mouse = MouseStates.PRESSING; if(states.current.button === ButtonStates.IDLE){ press(); } }; const onMouseUp = (): void =>{ states.current.mouse = MouseStates.IDLE; if(states.current.transition === TransitionStates.FORWARD_END){ release(); } }; const onTransitionEnd = (event: React.TransitionEvent<HTMLButtonElement>): void =>{ if (event.propertyName === "scale"){ if(states.current.transition !== TransitionStates.BACKWARD){ states.current.transition = TransitionStates.FORWARD_END; if(states.current.mouse === MouseStates.IDLE){ release(); } } else{ states.current.transition = TransitionStates.IDLE; states.current.button = ButtonStates.IDLE; if(states.current.mouse === MouseStates.PRESSING){ press() } } } }; const onMouseLeave = ()=>{ states.current.mouse = MouseStates.IDLE; if(states.current.button === ButtonStates.ANIMATING && states.current.transition === TransitionStates.FORWARD_END){ release(); } } return ( <button ref={buttonRef} onMouseDown={onMouseDown} onMouseUp={onMouseUp} onTransitionEnd={onTransitionEnd} onMouseLeave={onMouseLeave} className={[styles['button'], styles[variant], styles[colorSchema], styles[size]].join(" ")} > {children} </button> ) }
Leave a Comment