import React, { useState } from "react";
import { ReactComponent as MinusIcon } from "@Static/Icons/minus.svg";
import { ReactComponent as PlusIcon } from "@Static/Icons/plus.svg";
const MemoiedMinusIcon = React.memo(MinusIcon, (p, n) => p.width === n.width);
const MemoiedPlusIcon = React.memo(PlusIcon, (p, n) => p.width === n.width);
type InputStepperProp = {
onChange?: (value: number) => void;
defaultValue?: number;
min?: number;
max?: number;
};
const InputStepper = ({
onChange,
defaultValue = 5,
min = 1,
max = 10,
}: InputStepperProp) => {
const [step, setStep] = useState(defaultValue);
const handleMinusClick = () => {
if (step === min) return;
setStep(step - 1);
if (onChange) onChange(step - 1);
};
const handlePlusClick = () => {
if (step === max) return;
setStep(step + 1);
if (onChange) onChange(step + 1);
};
return (
<div className="flex w-[45.93vw] flex-row items-center justify-between border tablet:w-[19.14vw] desktop:w-[10.20vw]">
<button
disabled={min && step <= min ? true : false}
className="group h-m48 w-m48 border-r leading-none tablet:h-t48 tablet:w-t48 desktop:h-d48 desktop:w-d48"
onClick={() => handleMinusClick()}
>
<MemoiedMinusIcon className="w-full group-disabled:fill-gray" />
</button>
<div>
<p className="body">{step}</p>
</div>
<button
disabled={max && step >= max ? true : false}
className="group h-m48 w-m48 border-l tablet:h-t48 tablet:w-t48 desktop:h-d48 desktop:w-d48"
onClick={() => handlePlusClick()}
>
<MemoiedPlusIcon className="w-full group-disabled:fill-gray" />
</button>
</div>
);
};
export default InputStepper;
return (
<>
<div className="mx-auto mt-6 flex h-screen w-[90%] flex-col place-items-center">
<p>현재 선택된 value: {value}</p>
<InputStepper
defaultValue={value}
onChange={(value) => setValue(value)}
/>
</div>
</>
);
Step Count만 하면 되는 간단한 UI Component라 딱히 설명할 게 없긴 하다.
사실 Figma에서는 min, max에 대한 유스케이스를 다루진 않았다. 그러나 이 UI Component를 사용한다면 분명이 필요한 속성이라고 생각해서 임의로 추가했다.
엣지 케이스에 대해 생각해보자. value가 min일 때 minus를 한다면 다음과 같은 선택을 할 수 있겠다.
보통은 3번이겠다. 그러면 이 3번을 구현하려면 어떤 식으로 하는 게 좋을까?
UX적으론 2번이 맞겠다. 1번처럼 동작하게 되면, 사용자 입장에서는 개수를 줄일 수 있을 것처럼 만들어놨기 때문에 기능을 제대로 안 한다고 느낄 수도 있다. 2번처럼 버튼을 비활성화 하면 누를 수 없는 상태라고 인지하기 때문에 근본적인 오류를 처리할 수 있다.
비활성화 상태를 표시하는 것은 따로 flag state를 만들어서 관리를 하는 것이 아니라, button의 disabled 속성을 이용하는 것이 좋다. 이것이 시멘틱 웹으로도 알맞은 방향이라고 생각!
<button disabled={disabled} className="group">
<button disabled={disabled} className="group">
<Icon className="group-disabled:fill-gray" />
</button>