TodoTemplate : Todolist 레이아웃설정. 페이지 중앙에 그림자가 적용된 하얀색 box로 설정
TodoHead :날짜와 요일을 보여줌. 앞으로 해야할 일이 몇개 남아있는지 보여준다.
TodoList : 할일에 대한 정보가 들어있는 Todos배열을 내장함수 map을 사용해서 item들을 구현할 것이다.
TodoItem : 할일에대한 정보를 렌더링하는 컴포넌트 좌측에는 완료여부 토글, 완료 체크 될시에 텍스트의 색상이 연해지고 우측에 삭제 아이콘이 나타난다. 아이콘을 누르면 삭제된다.
TodoCreate : 새로운 할일을 등록할 수 있게 해주는 컴퍼넌트. 아래에 추가 버튼을 생성하고, 할일을 작성한뒤 enter를 누르면 할일이 추가되는 방식으로 구현한다.
styled-componenets
의 createGlobalStyle
사용하여 프로젝트 전역의 배경색을 gray색으로 변경하였음. 이때 색의 색깔은 open-color를 이용하여 코드값을 참고함.
const GlobalStyle = createGlobalStyle`
body{
background: #dee2e6;
}
`
src > components > ToodoTemplates.js 생성
Todolist의 기본 프레임을 제작한다.
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; /*위에서 아래로 */
`
function TodoTemplates({children}) {
return (
<TodoTemplateBlock>{children}</TodoTemplateBlock>
);
}
function App() {
return (
<>
<GlobalStyle/>
<TodoTemplates>안녕하세요!</TodoTemplates>
</>
);
}
현재 상황
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>2022년 3월 3일 </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>
</>
);
}
현재 상황
할일들의 목록을 표시해주는 프레임을 제작한다.
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>
</>
);
}
현재상황
할일에대한 정보를 렌더링하는 컴포넌트 좌측에는 완료여부 토글, 완료 체크 될시에 텍스트의 색상이 연해지고 우측에 삭제 아이콘이 나타난다. 아이콘을 누르면 삭제된다.
src - components - TodoItem.js
생성
해당 컴포넌트에선 react-icon을 통해서 일련의 icon을 사용할 예정이다.(MdDone, MdDelete)
4개의 styled 컴포넌트를 제작할 것이다.
-TodoItemBlock
: 할일 내용, 체크 아이콘, 삭제 아이콘을 담아두는 컴퍼넌트
-Text
: 할일의 내용 텍스트 스타일
-CheckCircle
: 체크 여부를 선택할수 있는 아이콘 스타일
-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;
}
`;
할일 왼쪽에 표시되는 체크 아이콘
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;
`}
`;
할일의 내용 텍스트. 체크가 된 상태일 경우(done = true)일 때 텍스트의 색이 밝아짐
const Text = styled.div`
flex: 1;
font-size: 21px;
color: #343a40;
${props => props.done && css`
color: ${lighten(0.1 `#343a40`)};
`}
`;
위의 모든 컴포넌트의 상위 컴퍼넌트. 해당 할일 목록중 하나에 마우스 커서를 올리면 삭제 아이콘이 보이게 된다.
const TodoItemBlock = styled.div`
display: flex;
align-items: center;
padding-top: 12px;
padding-bottom: 12px;
&:hover {
${Remove}{
opacity: 1;
}
}
`;
TodoItemBlock
내부에 CheckCircle
,Text
,Remove
컴퍼넌트를 삽입한다. 이때 MdDone
과 MdDelete
는 각각 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>
);
}
실제로 데이터를 받는 기능을 구현하지 않았으므로 임의적으로 작성한뒤 제대로 렌더링이 되는지 확인한다.
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>
);
}
현재상황
새로운 할일을 등록할 수 있게 해주는 컴포넌트. 아래에 추가 버튼을 생성하고, 할일을 작성한뒤 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도로 돌아가면서 색상이 변하는 기능을 추가한다.
onToggle
로 open
의 값을 변환하고, 만약 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
스타일 작성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가 옆으로 삐져나온 모습이 되므로 미관상 좋지않다.
요렇게됨