Untitled
unknown
plain_text
a year ago
3.4 kB
12
Indexable
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>
)
}Editor is loading...
Leave a Comment