JS' 공부흔적
[JavaScript] 마우스로 버튼을 클릭할 때와 키보드로 버튼을 클릭할 때를 구분하는 방법 본문
728x90
같은 버튼을 클릭해도 마우스로 클릭할 때와 키보드로 클릭할 때 다르게 동작하도록 구현할 필요가 생겼다. 원래는 키보드를 눌렀을 때 useState()를 통해 boolean state로 관리하려고 했지만, 의도한 대로 동작하지 않았다.
이를 event 객체의 detail을 사용하여 해결했다.
event.detail이란?
event.detail은 특정 이벤트 내에서 마우스로 버튼을 누른 횟수를 나타낸다. 버튼이 한 번 눌렸다면 1, 더블 클릭을 했다면 2, 그 이상 다중 클릭을 했다면 해당 숫자만큼 표시된다. 아래 각 경우에 해당하는 예시를 보자.
위에서 언급했듯이 특정 이벤트 내에서 마우스로 버튼을 누른 횟수를 나타내기 때문에, 만약 키보드 동작으로 버튼을 클릭한다면 event.detail 값은 0이 나온다.
event.detail을 사용하여 아래와 같이 구현했다.
- 마우스로 버튼을 클릭할 때는 처음 버튼부터 누른 버튼까지 모두 색칠되도록 구현
- 키보드에 의해(나의 경우 엔터키) 버튼을 클릭할 때는 버튼이 차례대로 색칠되도록 구현
코드는 아래와 같다.
// App.tsx
import { useRef, useState } from "react";
import { Button, Wrap } from "./App.style";
const App = () => {
const buttons = [1, 2, 3];
const divRef = useRef<HTMLDivElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [count, setCount] = useState(0);
const onKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "Enter" && buttonRef.current) {
buttonRef.current.click();
}
};
const onClick = (event: React.MouseEvent<HTMLButtonElement>, btn: number) => {
if (event.detail) {
setCount(btn);
} else {
setCount((prev) => (prev + 1) % 4);
}
if (divRef.current) divRef.current.focus();
};
return (
<Wrap ref={divRef} tabIndex={0} onKeyDown={onKeyDown}>
{buttons.map((btn) => (
<Button
ref={buttonRef}
key={btn}
isFilled={btn <= count}
onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
onClick(event, btn)
}
/>
))}
</Wrap>
);
};
export default App;
// App.style.ts
import styled from "styled-components";
export const Wrap = styled.div`
background-color: wheat;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
gap: 16px;
`;
export const Button = styled.button<{ isFilled: boolean }>`
width: 100px;
height: 100px;
border-radius: 50%;
border: 1px solid black;
background-color: ${({ isFilled }) => (isFilled ? "black" : "white")};
`;
728x90
반응형