๐Ÿ–ฅFrontEnd/React

ํƒญ ํ˜•์‹์˜ ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ํผ ๋งŒ๋“ค๊ธฐ

hellohailie 2023. 1. 4. 23:05

์™„์„ฑ๋ณธ

์ง€๊ธˆ๊นŒ์ง€ 2๋ฒˆ์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋กœ๊ทธ์ธ/ ํšŒ์›๊ฐ€์ž… ํŒŒํŠธ๋ฅผ ๋งก์•˜๋Š”๋ฐ ๊ทธ๋•Œ๋Š” ๋ชจ๋‘ ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…์„ ๋ณ„๋„์˜ ๊ฒฝ๋กœ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ๋งŒ๋“ค์—ˆ๋‹ค. 

๊ทธ๋Ÿฐ๋ฐ ์ด๋ฆฌ์ €๋ฆฌ ๊ตฌ๊ธ€๋ง์„ ํ•˜๋‹ค๊ฐ€ ์œ„์˜ gif์ฒ˜๋Ÿผ ํƒญ ํ˜•์‹์œผ๋กœ ๋กœ๊ทธ์ธ๊ณผ ํšŒ์›๊ฐ€์ž…์„ ๋งŒ๋“ค์–ด๋ณด๊ณ  ์‹ถ์—ˆ๋‹ค!

 

๊ทธ๋ž˜์„œ ๋„์ „!

 

์‚ฌ์šฉํ•œ ๊ธฐ์ˆ ์Šคํƒ
React, Typescript, Styled-components

 

 

๊ตฌํ˜„ํ•  ํ€˜์ŠคํŠธ

1. ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํƒญ์„ ๋ˆ„๋ฅด๋ฉด ๋ฒ„ํŠผ์ด ๊ฐ๊ฐ ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…์œผ๋กœ ๋ฐ”๋€๋‹ค.

2. ํด๋ฆญ๋˜๋Š” ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํƒญ์„ css๋กœ ํ‘œ์‹œํ•œ๋‹ค.

3. ์ด๋ฉ”์ผ์— @, . ํฌํ•จ๋˜๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 8์ž๋ฆฌ ์ด์ƒ์ผ ๋•Œ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋œ๋‹ค. 

 


1. ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํƒญ์„ ๋ˆ„๋ฅด๋ฉด ๋ฒ„ํŠผ์ด ๊ฐ๊ฐ ๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž…์œผ๋กœ ๋ฐ”๋€Œ๊ฒŒ ํ•˜๊ธฐ

ํƒญ๋ถ€๋ถ„๊ณผ ํผ๋ถ€๋ถ„์„ ๋‚˜๋ˆ ์„œ ๋งŒ๋“ค์–ด์„œ ๋ถ™์ด๋ฉด ๋œ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ๋กœ๊ทธ์ธ์ด ๋œ ์ƒํƒœ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” state๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•œ๋‹ค. 

const [isLogin, setIsLogin] = useState(true);

๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด setIsLogin์ด true๊ฐ€ ๋˜๊ณ , ํšŒ์›๊ฐ€์ž… ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด setIsLogin์ด false๊ฐ€ ๋˜๋„๋ก ํ–ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ๋ฒ„ํŠผ์—์„œ๋„ isLogin์ด true๋ฉด '๋กœ๊ทธ์ธ' ๊ธ€์ž๊ฐ€,  false๋ฉด 'ํšŒ์›๊ฐ€์ž…' ๊ธ€์ž๊ฐ€ ๋‚˜์˜ค๊ฒŒ ํ–ˆ๋‹ค. 

 

 


 

2. ํด๋ฆญ๋˜๋Š” ๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… ํƒญ์„ css๋กœ ํ‘œ์‹œํ•œ๋‹ค.

styled-component๋กœ ์ž‘์—…ํ•˜๋ฉด props๊ฐ’์„ ๋ฐ›์•„์„œ ์Šคํƒ€์ผ์„ ์œ ๋™์ ์œผ๋กœ ์กฐ์ ˆํ•  ์ˆ˜ ์žˆ๋‹ค!

์—ฌ๊ธฐ์„œ๋Š” isLogin ์ƒํƒœ์— ๋”ฐ๋ผ ์ƒ‰์ด ๋ณ€ํ•˜๋ฉด ๋˜๋‹ˆ๊นŒ isLogin์„ props๋กœ ๋ฐ›์•„์™”๋‹ค. 

 

const AuthTab = styled.div<{ isLogin: boolean }>`
  width: 300px;
  display: flex;

  button {
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
    /* border-top: 1px solid gray; */
    box-shadow: rgba(50, 50, 93, 0.25) 1px 2px 5px -1px,
      rgba(0, 0, 0, 0.3) -1px 1px 3px -1px;
    border: 0;
    border-bottom: 0;
    background-color: transparent;
    padding: 10px 30px;
    flex-basis: 50%;
    cursor: pointer;
  }

  & > button:first-child {
    background-color: ${({ isLogin }) => (isLogin ? "#5586eb" : "inherit")};
    color: ${({ isLogin }) => (isLogin ? "#ffffff" : "#000000")};
  }
  & > button:last-child {
    background-color: ${({ isLogin }) => (isLogin ? "inherit" : "#5586eb")};
    color: ${({ isLogin }) => (isLogin ? "#000000" : "#ffffff")};
  }
`;

 

 


 

3. ์ด๋ฉ”์ผ์— @, . ํฌํ•จ๋˜๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 8์ž๋ฆฌ ์ด์ƒ์ผ ๋•Œ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋œ๋‹ค. 

์ด ๋ถ€๋ถ„์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” input์— onKeyUp ์ด๋ฒคํŠธ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋œ๋‹ค. 

input์˜ value ๊ฐ’์„ ์ž˜ ๋“ค์—ฌ๋‹ค ๋ณด๊ณ  ์žˆ๋‹ค๊ฐ€, ์ด๋ฉ”์ผ์— @, . ํฌํ•จ๋˜๊ณ , ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ 8์ž๋ฆฌ ์ด์ƒ์ผ ๋•Œ ๋ฒ„ํŠผ์ด ํ™œ์„ฑํ™”๋˜๋„๋ก css ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค€๋‹ค. 

 

์ด๋ฅผ ์œ„ํ•ด์„œ isActive๋ผ๊ณ  ๋จผ์ € ์ƒํƒœ๋ฅผ ์„ ์–ธํ•ด์ค€๋‹ค. 

const [isActive, setIsActive] = useState<boolean>(false);

๊ทธ๋ฆฌ๊ณ  input์—๋Š” onKeyUp ์ด๋ฒคํŠธ๋ฅผ ์ด์šฉํ•ด์„œ changeButton์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค. 

const changeButton = () => {
    email.includes("@") && password.length >= 8
      ? setIsActive(true)
      : setIsActive(false);
  };

 

๊ทธ๋ฆฌ๊ณ  ๋ฒ„ํŠผ์— css ํšจ๊ณผ๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด์„œ isActive ๊ฐ€ true์ธ์ง€, false์ธ์ง€์— ๋”ฐ๋ผ css๋ฅผ ๋‹ฌ๋ฆฌํ•œ๋‹ค. 

 <button className={isActive ? "Active" : "Disabled"}>
          {isLogin ? "๋กœ๊ทธ์ธ" : "ํšŒ์›๊ฐ€์ž…"}
</button>

ํ•ด๋ณด๊ณ  ์‹ถ์—ˆ๋Š”๋ฐ ํ•ด๋‚ด์„œ ๊ธฐ์˜๋‹ค!!


์ „์ฒด ์ฝ”๋“œ

import React, { useState } from "react";
import styled from "styled-components";

const Auth = () => {
  const [isLogin, setIsLogin] = useState(true);
  const [email, setEmail] = useState<string>("");
  const [password, setPassword] = useState<string>("");
  const [isActive, setIsActive] = useState<boolean>(false);

  const changeButton = () => {
    email.includes("@") && password.length >= 8
      ? setIsActive(true)
      : setIsActive(false);
  };

  return (
    <Container>
      <AuthTab isLogin={isLogin}>
        <button type='button' onClick={() => setIsLogin(true)}>
          ๋กœ๊ทธ์ธ
        </button>
        <button type='button' onClick={() => setIsLogin(false)}>
          ํšŒ์›๊ฐ€์ž…
        </button>
      </AuthTab>

      <AuthForm>
        <InputInfo>
          <Input
            type='email'
            id='id'
            placeholder='
            EMAIL'
            required
            value={email}
            onKeyUp={changeButton}
            onChange={(e) => {
              setEmail(e.target.value);
            }}
          ></Input>

          <Input
            type='password'
            id='password'
            placeholder='PASSWORD'
            required
            value={password}
            onKeyUp={changeButton}
            onChange={(e) => {
              setPassword(e.target.value);
            }}
          ></Input>
        </InputInfo>

        <button className={isActive ? "Active" : "Disabled"}>
          {isLogin ? "๋กœ๊ทธ์ธ" : "ํšŒ์›๊ฐ€์ž…"}
        </button>
      </AuthForm>
    </Container>
  );
};

export default Auth;

const Container = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
`;
const AuthTab = styled.div<{ isLogin: boolean }>`
  width: 300px;
  display: flex;

  button {
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
    /* border-top: 1px solid gray; */
    box-shadow: rgba(50, 50, 93, 0.25) 1px 2px 5px -1px,
      rgba(0, 0, 0, 0.3) -1px 1px 3px -1px;
    border: 0;
    border-bottom: 0;
    background-color: transparent;
    padding: 10px 30px;
    flex-basis: 50%;
    cursor: pointer;
  }

  & > button:first-child {
    background-color: ${({ isLogin }) => (isLogin ? "#5586eb" : "inherit")};
    color: ${({ isLogin }) => (isLogin ? "#ffffff" : "#000000")};
  }
  & > button:last-child {
    background-color: ${({ isLogin }) => (isLogin ? "inherit" : "#5586eb")};
    color: ${({ isLogin }) => (isLogin ? "#000000" : "#ffffff")};
  }
`;

const AuthForm = styled.form`
  /* border: 1px solid gray; */
  box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
    rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
  width: 300px;
  display: flex;
  flex-direction: column;
  align-items: center;

  button {
    margin: 10px 0px;
    background-color: transparent;
    border: 1px solid #81a4ea;
    padding: 10px;
    width: 88%;
    border-radius: 10px;
  }

  .Disabled {
    background-color: inherit;
  }
  .Active {
    background-color: #5586eb;
    color: white;
  }
`;

const InputInfo = styled.div`
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
`;
const Input = styled.input`
  padding: 10px;
  margin: 10px 0px;
  width: 80%;
  border: 1px solid lightblue;
  border-radius: 10px;
`;