TIL 39일차

안광의·2021년 8월 10일
1

Today I Learned

목록 보기
39/64
post-thumbnail

시작하며

오늘은 styled components를 활용하여 웹페이지 상에서 자주 사용되는 UI를 구현하는 스프린트를 진행하였다. React와 CSS의 문법과 기능을 복습하면서 새로운 작성 방식을 익힐 수 있었다.

React

import { useState } from 'react';
import styled from 'styled-components';
export const ModalContainer = styled.div`
  text-align: center;
  margin: 125px auto;
  width: 100%;
  height: 100%;
`;
export const ModalBackdrop = styled.div`
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.8);
`;
export const ModalBtn = styled.button`
  background-color: #4000c7;
  text-decoration: none;
  border: none;
  padding: 20px;
  color: white;
  border-radius: 30px;
  cursor: grab;
`;
export const ModalView = styled.div.attrs(props => ({
  role: 'dialog'
}))`
  width: 320px;
  padding: 1.5rem;
  background: white;
  border-radius: 2px;
  margin: 0;
`;
export const Modal = () => {
  const [isOpen, setIsOpen] = useState(false);
  const openModalHandler = () => {
    setIsOpen(!isOpen)
  };
  return (
    <>
      <ModalContainer onClick={openModalHandler}>
        <ModalBtn onClick={openModalHandler}>
          {isOpen ? "Opened!" : "Open Modal"}
        </ModalBtn>
        {isOpen ? <ModalBackdrop onClick={openModalHandler}>
        <ModalView> 
          <div onClick={openModalHandler}>
            &times;
          </div>
            Hello CodeStates!
          </ModalView>
        </ModalBackdrop>: ""}
      </ModalContainer>
    </>
  );
};



Tab

import { useState } from 'react';
import styled from 'styled-components';
const TabMenu = styled.ul`
  background-color: #dcdcdc;
  color: rgba(73, 73, 73, 0.5);
  font-weight: bold;
  display: flex;
  flex-direction: row;
  justify-items: center;
  align-items: center;
  list-style: none;
  margin-bottom: 7rem;
  border-radius: 10px;
  .submenu {
    ${'' /* 기본 Tabmenu 에 대한 CSS를 구현합니다. */}
    padding-top: 0.8rem;
    padding-bottom: 0.8rem;
    padding-left: 0.9rem;
    text-align: center;
    padding-right: 0.9rem;
    cursor: pointer;
    border-radius: 10px;
  }
  .focused {
    ${'' /* 선택된 Tabmenu 에만 적용되는 CSS를 구현합니다.  */}
    color: #ffffff;
    background-color: #4900CE;
  }
  & div.desc {
    text-align: center;
  }
`;
const Desc = styled.div`
  text-align: center;
`;
export const Tab = () => {
  // TIP: Tab Menu 중 현재 어떤 Tab이 선택되어 있는지 확인하기 위한
  // currentTab 상태와 currentTab을 갱신하는 함수가 존재해야 하고, 초기값은 0 입니다.
  const [currentTab, setCurrentTab] = useState(0);
  const menuArr = [
    { name: 'Tab1', content: 'Tab menu ONE' },
    { name: 'Tab2', content: 'Tab menu TWO' },
    { name: 'Tab3', content: 'Tab menu THREE' },
  ];
  const selectMenuHandler = (index) => {
    setCurrentTab(index);
  };
  return (
    <>
      <div>
        <TabMenu>
          {menuArr.map((menu, idx) => {
            return (
              <li 
              key={idx}
              className={idx === currentTab ? 'submenu focused' : 'submenu' } 
              onClick={() => selectMenuHandler(idx)}>
              {menu.name}
              </li>
            );
          })}
        </TabMenu>
        <Desc>
          <p>{menuArr[currentTab].content}</p>
        </Desc>
      </div>
    </>
  );
};



Tag

import { useState } from 'react';
import styled from 'styled-components';
export const TagsInput = styled.div`
  margin: 8rem auto;
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  min-height: 48px;
  width: 480px;
  padding: 0 8px;
  border: 1px solid rgb(214, 216, 218);
  border-radius: 6px;
ul {
    display: flex;
    flex-wrap: wrap;
    padding: 0;
    margin: 8px 0 0 0;
.tag {
      width: auto;
      height: 32px;
      display: flex;
      align-items: center;
      justify-content: center;
      color: #fff;
      padding: 0 8px;
      font-size: 14px;
      list-style: none;
      border-radius: 6px;
      margin: 0 8px 8px 0;
      background: #4000c7;
.tag-close-icon {
        display: block;
        width: 16px;
        height: 16px;
        line-height: 16px;
        text-align: center;
        font-size: 14px;
        margin-left: 8px;
        color: #4000c7;
        border-radius: 50%;
        background: #fff;
        cursor: pointer;
      }
    }
  }
input {    
    flex: 1;
    border: none;
    height: 46px;
    font-size: 14px;
    padding: 4px 0 0 0;
    :focus {
    outline: transparent;
  }
  }
  &:focus-within {
    border: 1px solid #4000c7;
  }
`;
export const Tag = () => {
  const initialTags = ['CodeStates', 'kimcoding'];
  const [tags, setTags] = useState(initialTags);
  const removeTags = (indexToRemove) => {
    // TODO : 태그를 삭제하는 메소드를 완성하세요.
    setTags(tags.filter(tag => indexToRemove !== tags.indexOf(tag)));
  };
  const addTags = (event) => {
    if (!tags.includes(event.target.value) && event.target.value !== '') {
      setTags([...tags, event.target.value])
      event.target.value = ''; 
    }
    }
  return (
    <>
      <TagsInput>
        <ul id='tags'>
          {tags.map((tag, index) => (
            <li key={index} className='tag'>
              <span className='tag-title'>{tag}</span>
              <span className='tag-close-icon' onClick={() => removeTags(index)}>&times;
              </span>
            </li>
          ))}
        </ul>
        <input
          className='tag-input'
          type='text'
          onKeyUp={ (event) => event.key === 'Enter' ? addTags(event) : '' }
          placeholder='Press enter to add tags'
        />
      </TagsInput>
    </>
  );
};



Toggle

import { useState } from 'react';
import { isCompositeComponent } from 'react-dom/test-utils';
import styled from 'styled-components';
const ToggleContainer = styled.div`
  position: relative;
  margin-top: 8rem;
  left: 47%;
  cursor: pointer;
.toggle-container {
    width: 50px;
    height: 24px;
    border-radius: 30px;
    background-color: #8b8b8b;
    &.toggle--checked {
      background-color: #4900CE;
    }
  }
.toggle-circle {
    position: absolute;
    top: 1px;
    left: 1px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background-color: #ffffff;
    &.toggle--checked {
      left: 27px
    }
  }
`;
const Desc = styled.div`
  text-align: center;
`;
export const Toggle = () => {
  const [isOn, setisOn] = useState(false);
  const toggleHandler = () => {
    setisOn(!isOn)
  };
  return (
    <>
      <ToggleContainer onClick={toggleHandler}>
        <div className={`toggle-container ${isOn ? "toggle--checked" : ""}`}/>
        <div className={`toggle-circle ${isOn ? "toggle--checked" : ""}`}/>
      </ToggleContainer>
      <Desc>{isOn ? "Toggle Switch ON":"Toggle Switch OFF"}</Desc>
      </>
  );
};

마치며

styled components는 React와 CSS의 기본적인 문법을 기반으로 해서 기능 구현을 위해 코드를 작성하는 것은 어렵지 않았으나 스프린트를 진행하면서 CSS에 대한 공부가 부족하다는 것을 느낄 수 있었다. 만약 프론트엔드 포지션으로 일하게 된다면 CSS는 필수적이고 백엔드 포지션이라도 기본적인 내용은 알아야 하기 때문에 따로 공부해야겠다고 느꼈다.

profile
개발자로 성장하기

0개의 댓글