투두리스트 만들기 UI 준비

정영찬·2022년 3월 4일
0

리액트

목록 보기
38/79

만들 컴포넌트

  • TodoTemplate : Todolist 레이아웃설정. 페이지 중앙에 그림자가 적용된 하얀색 box로 설정

  • TodoHead :날짜와 요일을 보여줌. 앞으로 해야할 일이 몇개 남아있는지 보여준다.

  • TodoList : 할일에 대한 정보가 들어있는 Todos배열을 내장함수 map을 사용해서 item들을 구현할 것이다.

  • TodoItem : 할일에대한 정보를 렌더링하는 컴포넌트 좌측에는 완료여부 토글, 완료 체크 될시에 텍스트의 색상이 연해지고 우측에 삭제 아이콘이 나타난다. 아이콘을 누르면 삭제된다.

  • TodoCreate : 새로운 할일을 등록할 수 있게 해주는 컴퍼넌트. 아래에 추가 버튼을 생성하고, 할일을 작성한뒤 enter를 누르면 할일이 추가되는 방식으로 구현한다.

시작

배경화면 설정

styled-componenetscreateGlobalStyle 사용하여 프로젝트 전역의 배경색을 gray색으로 변경하였음. 이때 색의 색깔은 open-color를 이용하여 코드값을 참고함.

const GlobalStyle = createGlobalStyle`
  body{
    background: #dee2e6;
  }
`

TodoTemplate 제작

src > components > ToodoTemplates.js 생성

TocoTemplateBlock 생성

Todolist의 기본 프레임을 제작한다.

  • TodoTemplateBlock 스타일 생성
const TodoTemplateBlock = styled.div`
    width: 512px;
    height: 768px;

    position: relative;
    background: white;
    border-radius: 16px;
    box-shadow : 0 0 8px rgaba(0,0,0, 0.04);

    margin: 0 auto;
    margin-top: 96px;
    margin-bottom: 32px;

    display: flex;
    flex-direction: column; /*위에서 아래로 */
`
  • TodoTemplates 수정
function TodoTemplates({children}) {
    return (
        <TodoTemplateBlock>{children}</TodoTemplateBlock>
    );
}
  • App.js 수정
function App() {
 return (
   <>
    <GlobalStyle/>
    <TodoTemplates>안녕하세요!</TodoTemplates>
   </>
    
 );
}

현재 상황

TodoHead 제작

src - componenets - TodoHead.js파일 생성
날짜, 요일, 남은 일 갯수 표시

  • TodoheadBlock스타일 생성

const TodoHeadBlock = styled.div`
   padding: 48px, 32px, 24px, 32px;
   border-bottom: 1px solid #495057;

   h1{
       margin: 0;
       font-size: 36px;
       color: #343a40;
   }

   .day{
        margin-top: 4px;
        color: #868e96;
        font-size: 25px;
   }

   .tasks-left {
       color: #69db7c;
       font-size: 18px;
       margin-top: 40px;
       font-weight: bold;

   }
  • TodoHead 함수 수정
function TodoHead() {
    return (
        <TodoHeadBlock>
            <h1>202233</h1>
            <div className="day">일요일</div>
            <div className="tasks-left">3개 남음</div>
        </TodoHeadBlock>
    );
}

현재 날짜나 요일의 변경 및, 남은 할일의 갯수 조회는 기능이 추가되지 않았고, 표시되는 스타일을 보기위해 임의로 작성함.

  • App.js 수정
import TodoHead from "./components/TodoHead";
function App() {
 return (
   <>
    <GlobalStyle/>
    <TodoTemplates>
      <TodoHead></TodoHead>
    </TodoTemplates>
   </>
    
 );
}

현재 상황

TodoList 제작

할일들의 목록을 표시해주는 프레임을 제작한다.

src - components - TodoList.js 제작

  • TodoListBlock스타일 생성해서 배경을 정한뒤 얼마나 영역을 차지하는지 확인한다.
const TodoListBlock = styled.div`
    flex:1;
    padding: 20px 32px;
    padding-bottom: 48px;
    overflow-y: auto;
    background: gray;
`;

TodoList함수 수정

function TodoList() {
    return (
       <TodoListBlock></TodoListBlock>
    );
}

App.js에 렌더링

import TodoList from "./components/TodoList";
function App() {
 return (
   <>
    <GlobalStyle/>
    <TodoTemplates>
      <TodoHead></TodoHead>
      <TodoList></TodoList>
    </TodoTemplates>
   </>
    
 );
}

현재상황

TodoItem 제작

할일에대한 정보를 렌더링하는 컴포넌트 좌측에는 완료여부 토글, 완료 체크 될시에 텍스트의 색상이 연해지고 우측에 삭제 아이콘이 나타난다. 아이콘을 누르면 삭제된다.

src - components - TodoItem.js 생성
해당 컴포넌트에선 react-icon을 통해서 일련의 icon을 사용할 예정이다.(MdDone, MdDelete)

4개의 styled 컴포넌트를 제작할 것이다.
-TodoItemBlock : 할일 내용, 체크 아이콘, 삭제 아이콘을 담아두는 컴퍼넌트
-Text : 할일의 내용 텍스트 스타일
-CheckCircle : 체크 여부를 선택할수 있는 아이콘 스타일
-Remove : 삭제 아이콘 스타일

Remove

처음엔 보이지 않다가 TodoItemBlcok에 커서를 올리면 보이게 된다.

const Remove = styled.div`
    opacity: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #adb5bd;
    font-size: 24px;
    cursor: pointer;
    &:hover{
        color:#e03131;
    }
`;

CheckCircle

할일 왼쪽에 표시되는 체크 아이콘

const CheckCircle = styled.div`
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 1px solid #343a40;
    font-size: 24px; 
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: 20px;
    cursor: pointer;
    ${props => props.done && css`
        border: 1px solid #12b886;
        color: #12b886;
    `}
`;

Text

할일의 내용 텍스트. 체크가 된 상태일 경우(done = true)일 때 텍스트의 색이 밝아짐

const Text = styled.div`
    flex: 1;
    font-size: 21px;
    color: #343a40;
    ${props => props.done && css`
        color: ${lighten(0.1 `#343a40`)};
    `}
`;

TodoItemBlock

위의 모든 컴포넌트의 상위 컴퍼넌트. 해당 할일 목록중 하나에 마우스 커서를 올리면 삭제 아이콘이 보이게 된다.

const TodoItemBlock = styled.div`
    display: flex;
    align-items: center;
    padding-top: 12px;
    padding-bottom: 12px;

    
    &:hover {
        ${Remove}{
            opacity: 1;
        }
    }
`;

TodoItem 함수 수정

TodoItemBlock내부에 CheckCircle,Text,Remove 컴퍼넌트를 삽입한다. 이때 MdDoneMdDelete는 각각 CheckCircle,Remove 에 넣는다. 또한 props 값으로 id,done,text를 받아올것이다. 각각 할일 고유번호, 완료 여부, 할일의 내용을 뜻한다.

function TodoItem({id, done, text}) {
    return (
        <TodoItemBlock>
            <CheckCircle done={done}>
                {done && <MdDone/>}
            </CheckCircle>
            <Text done={done}>{text}</Text>
            <Remove>
                <MdDelete/>
            </Remove>

        </TodoItemBlock>
    );
}

TodoList에서 TodoItem을 렌더링

실제로 데이터를 받는 기능을 구현하지 않았으므로 임의적으로 작성한뒤 제대로 렌더링이 되는지 확인한다.

function TodoList() {
    return (
       <TodoListBlock>
           <TodoItem text="프로젝트 생성하기" done={true}></TodoItem>
           <TodoItem text="컴포넌트 스타일링하기" done={true}></TodoItem>
           <TodoItem text="context만들기" done={false}></TodoItem>
           <TodoItem text="기능 구현하기" done={false}></TodoItem>
       </TodoListBlock>
    );
}

현재상황

TodoCreate 제작

새로운 할일을 등록할 수 있게 해주는 컴포넌트. 아래에 추가 버튼을 생성하고, 할일을 작성한뒤 enter를 누르면 할일이 추가되는 방식으로 구현한다.
src - components - TodoCreate.js생성

  • CircleButton style 컴포넌트 생성
    TodoTemplate기준으로 하단 가운데에 위치하며 버튼에 커서를 올리면 색이 밝아지고, 클릭하면 색이 어두워진다.
const CircleButton = styled.button`
    background: #1c7ed6;
    &:hover{
        background: ${lighten(0.1 , '#1c7ed6')};
    }
    &:active {
        background: ${darken(0.1, '#1c7ed6')};
    }

    z-index: 5;
    cursor: pointer;
    width: 80px;
    height: 80px;
    display: flex;
    align-items: center;
    justify-content: center;

    position: absolute;
    left: 50%;
    bottom: 0px;
    transform: translate(-50%, -50%);

    font-size: 60px;
    color: white;
    border-radius: 50%;
    border: none;
    outline: none;
`
  • App.js에 렌더링
function App() {
 return (
   <>
    <GlobalStyle/>
    <TodoTemplates>
      <TodoHead></TodoHead>
      <TodoList></TodoList>
      <TodoCreate/>
    </TodoTemplates>
   </>
    
 );
}

현재상황

  • CircleButton을 클릭했을 때, 45도로 돌아가면서 색상이 변하는 기능을 추가한다.
    onToggleopen의 값을 변환하고, 만약 true 값이 된다면 스타일을 변경한다.

    • useState추가 import React, {useState} from "react";

    • TodoCreate함수에 useState를 이용하여 open값의 상태를 조절한다.

            const [open, setOpen] =  useState(false);
    • 버튼을 클릭했을 때 동작하는 기능(onToggle) 제작

        const onToggle = () => setOpen(!open);
    • open이 true 가 되었을때의 스타일 선언

       transition: 0.125s all ease-in;
      
       ${props => props.open && css`
           background: #e03131;
           &:hover{
               background:#ff6b6b;
           }
           &:focus{
               background:#c92a2a;
           }
      
           transform: translate(-50%, 50%) rotate(45deg);
       `}

현재 상황

  • CircleButton을 클릭했을때 할일 추가를 작성하기위한 form이 나타나게 한다.
    • InsertFormPositioner를 통해 생성되는 form의 위치를 지정한다. CircleButton바로 위에서 나타날 것이다.
      const InsertFormPositioner = styled.div`
       width: 100%;
       bottom: 0;
       left: 0;
       position: absolute;

`;

- `InsertFormPositioner` 내부에 들어가는 `InsertForm`을 생성한다.
```js
const InsertForm = styled.div`
 background: #ced4da;
 padding: 32px;
 padding-bottom: 72px;
 border-bottom-left-radius: 16px;
 border-bottom-right-radius: 16px;
 border-top: 1px solid #495057;
`

현재 상황

버튼을 클릭하면 할일을 적어서 추가하기 위한 입력창의 화면만 나타난다.

  • 할일을 입력하는 input 창을 생성한다.
    Input스타일 작성
const Input = styled.input`
  padding: 12px;
  border-radius: 4px;
  border: 1px solid #e9ecef;
  width: 100%;
  outline: none;
  font-size: 18px;
  box-sizing: border-box;
`;

-TodoCreate함수 수정

 return (
    <>
      {open && (
        <InsertFormPositioner>
          <InsertForm>
            <Input
              placeholder="할일을 입력후, Enter를 누르세요"
              autoFocus
            ></Input>
          </InsertForm>
        </InsertFormPositioner>
      )}
      <CircleButton open={open} onClick={onToggle}>
        <MdAdd />
      </CircleButton>
    </>

현재상황

Input 스타일에서 border-box를 설정하지 않으면 패딩이 적용된뒤에 box가 옆으로 삐져나온 모습이 되므로 미관상 좋지않다.

요렇게됨

profile
개발자 꿈나무

0개의 댓글