1. 사각형을 만들 코드의 길이를 정하고 Display Flex를 사용하여 중앙에 보안 코드를 배치합니다.
import styled from "styled-components";
const CODE_LENGTH = 5;
const App = () => {
return (
<Container>
<Box>
{Array(CODE_LENGTH)
.fill(0)
.map((v, i) => {
return <Display key={i}>{codes(i)}</Display>;
})}
</Box>
</Container>
);
};
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 200px 0;
`;
const Box = styled.div`
display: flex;
justify-content: center;
gap: 6px;
margin: 30px 0 10px;
`;
const Display = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 76px;
border: 1px solid #e0e0e0;
border-radius: 10px;
font-weight: 700;
font-size: 32px;
color: #2e2e2e;
`;
export default App;
2. 입력을 만들고 position:absolute로 디스플레이와 동일한 위치로 설정합니다.
<Box>
{Array(CODE_LENGTH).fill(0).map((v, i) => {
return <Display key={i}>{codes(i)}</Display>;
})}
<Input maxLength={CODE_LENGTH} />
</Box>
const Input = styled.input`
position: absolute;
max-width: 320px;
padding: 0 20px 3px;
height: 76px;
font-size: 28px;
`;
3. 입력한 텍스트, 배경색, 외곽선, 프레임을 모두 지웁니다.
문자를 숨기면 캐럿도 숨겨지며, 캐럿-색상 속성을 통해서만 속성을 할당할 수 있습니다.
const Input = styled.input`
position: absolute;
max-width: 320px;
padding: 0 20px 3px;
height: 76px;
background: none;
font-size: 28px;
color: rgba(0, 0, 0, 0);
caret-color: black;
border: none;
outline: none;
`;
4. 입력의 문자 간격 속성을 사용하여 문자 간격을 디스플레이 패널과 맞춥니다.
letter-spacing: 50px;
5. useState를 통해 입력 값을 받고 입력 값에 따라 유효성 검사 값을 표시합니다.
여기에서는 입력한 코드가 5자인지 여부만 확인합니다.
const (codes, setCodes) = useState("");
<Box>
{Array(CODE_LENGTH).fill(0).map((v, i) => {
return <Display key={i}>{codes(i)}</Display>;
})}
<Input
value={codes}
onChange={(e) => setCodes(e.target.value)}
maxLength={CODE_LENGTH}
/>
</Box>
{codes.length >= CODE_LENGTH ? (
<Validation>Code correct</Validation>
) : (
<Validation color="#ff5a60">Code uncorrect</Validation>
)}
const Validation = styled.p<{ color?: string }>`
font-weight: 500;
color: ${({ color }) => (color ? color : "#1eba66")};
`;
전체 코드는 다음과 같습니다.
import { useState } from "react";
import styled from "styled-components";
const CODE_LENGTH = 5;
const App = () => {
const (codes, setCodes) = useState("");
return (
<Container>
<h1>Verification Code</h1>
<Box>
{Array(CODE_LENGTH)
.fill(0)
.map((v, i) => {
return <Display key={i}>{codes(i)}</Display>;
})}
<Input
value={codes}
onChange={(e) => setCodes(e.target.value)}
maxLength={CODE_LENGTH}
/>
</Box>
{codes.length >= CODE_LENGTH ? (
<Validation>Code correct</Validation>
) : (
<Validation color="#ff5a60">Code uncorrect</Validation>
)}
</Container>
);
};
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin: 200px 0;
`;
const Box = styled.div`
display: flex;
justify-content: center;
gap: 6px;
margin: 30px 0 10px;
`;
const Display = styled.div`
display: flex;
align-items: center;
justify-content: center;
width: 60px;
height: 76px;
border: 1px solid #e0e0e0;
border-radius: 10px;
font-weight: 700;
font-size: 32px;
color: #2e2e2e;
`;
const Input = styled.input`
position: absolute;
max-width: 320px;
padding: 0 20px 3px;
height: 76px;
background: none;
letter-spacing: 50px;
font-size: 28px;
color: rgba(0, 0, 0, 0);
caret-color: black;
border: none;
outline: none;
`;
const Validation = styled.p<{ color?: string }>`
font-weight: 500;
color: ${({ color }) => (color ? color : "#1eba66")};
`;
export default App;