일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- react
- formik submitting not working
- git commit merge
- 리팩토링2판4장
- 시스템설계면접팁
- cypressBDD
- 테스트코드책
- 헤드퍼스트전략패턴
- formik react-query submitting not working
- react-ga
- 디자인패턴
- 가상면접2장
- 시스템설계면접예시
- cypress React
- FirebaseAnalytics
- 가상면접3장
- s3이미지다운로드됨
- 시스템설계면접
- Git commit 합치기
- 시스템설계
- 전략패턴
- 가상면접으로대규모시스템
- file not found Error
- 시스템설계방법
- git commit 협업
- 리액트구글애널리틱스
- 리팩터링2판테스트
- git squash
- gitsquash
- awss3
- Today
- Total
mingg IT
[Calendar] react-big-calendar custom(커스텀) 하기 본문
목적
- 아래와 같은 calendar 형식으로 커스텀이 필요한 상황 이였다.
- 클릭 시 일자, 가격, 배경 색 변경
- 헤더영역, 일자 영역 border 제거 필요
- 달력 내 일자 영역을 둥근 border 필요
react-big-calendar 사용한 이유
- 이벤트 추가 및 사용하기에 간단함
- 커스텀 하기에 좋음
- 다양한 형태의 캘린더 제공(우리 프로젝트에선 오버스펙이긴함)
- npm 링크: https://www.npmjs.com/package/react-big-calendar
사용 기술 스택
- Nextjs v13
- Tailwind css
- react v18
- react-big-calendar v1.10.1
커스텀 전의 캘린더 모습
(참고: 토, 일 색 변형 등은 내가 수정해주었음)
import "moment-timezone/builds/moment-timezone-with-data";
import "moment/locale/ko";
import { useEffect, useState } from "react";
import { Calendar, momentLocalizer } from "react-big-calendar";
import "react-big-calendar/lib/css/react-big-calendar.css";
const events = [
{
title: Number(972000).toLocaleString(),
start: new Date(2024, 2, 17),
end: new Date(2024, 2, 17),
},
{
title: Number(973000).toLocaleString(),
start: new Date(2024, 2, 18),
end: new Date(2024, 2, 18),
},
..생략
];
return (
<div style={{ height: 360 }}>
<Calendar
backgroundColor={"#fff"}
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
eventPropGetter={dayOfWeekStyleGetter}
views={["month"]}
formats={formats}
/>
</div>
</div>
)
1. css 파일 작성
우선 커스텀을 하기 위해선 css 파일을 만들어 주어야함.
customer.css 를 만들고 import 해서 불러오자.
배경색
확인해보면 배경부분을 가르키는 클래스명은 rbbc-day-bg 이다.
25~ 29, 01 ~ 06 와 같이 이번달에 포함되지 않는 영역은 또 클래스명이 다르기 때문에 아래에서 논의 하겠음.
custom-calendar.css
.rbc-day-bg {
border: 1px solid white !important;
border-radius: 5px !important;
background-color: green !important;
opacity: 0.1;
}
배경색 클래스명: rbc-day-bg 수정
이렇게 수정하게 되면 배경색이 바뀌어 있다.
이번달에 포함되지 않는 배경색
custom-calendar.css
.rbc-off-range-bg {
background-color: #e6e6e6 !important;
border-radius: 5px !important;
}
배경색 클래스명: rbc-off-range-bg 수정
확인해보면 이번달에 포함되지 않는 영역의 배경색이 변경 되어있다.
이제부터 클릭 할 때마다 색이 변경되는 영역을 커스텀 해보도록 하겠다.
이건 class를 확인해보면 알 겠지만 css파일만 수정해서는 할 수가 없다.
2. Customer 컴포넌트 작성
클릭시 배경색 변경
아래와 같이 일자 하나에 대한 커스텀이 필요할 경우에는
dateCellWrapper: CustomDateCellWrapper 를 이용해준다.
<Calendar
backgroundColor={"#fff"}
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
eventPropGetter={dayOfWeekStyleGetter}
views={["month"]}
formats={formats}
selectable={true}
onSelectSlot={(slot) => {
setSelectedDate(slot.start);
}}
components={{
month: {
dateCellWrapper: CustomDateCellWrapper, // 커스텀 컴포넌트 추가
},
}}
/>
// 여기가 핵심
const CustomDateCellWrapper = (props) => {
const isSelected = isSameDate(props.value, selectedDate);
return (
<div
className={
isSelected
? `${props.children.props.className}-selected`
: props.children.props.className
}
>
{props.children}
</div>
);
};
const isSameDate = (date, selectedDate) => {
const calendarDay = new Date(date).getDay();
const calendarDate = new Date(date).getDate();
const selectedDay = selectedDate && new Date(selectedDate).getDay();
const selectDate = selectedDate && new Date(selectedDate).getDate();
const isSame =
`${calendarDay}_${calendarDate}` === `${selectedDay}_${selectDate}`;
return isSame;
};
CustomerDateCellWrapper내 props를 콘솔로 찍어보면 어떤 데이터가 나오는지 확인이 가능하다.
우리가 살펴볼 부분은 바로 className과 내려오는 날짜 값인 value 이다.
className: 'rbc-day-bg' 를 기억하겠지만 바로 위에서 커스텀 했던 클래스 부분이다.
value: 내가 클릭한 날짜와 해당 날짜가 일치하는지 찾는데 이용된다.
그렇다면 내가 클릭했다면 rbc-day-bg-selected 클래스를 만들어주고, default는 rbc-day-bg 클래스를 이용하면 된다.
// 여기가 핵심
const CustomDateCellWrapper = (props) => {
const isSelected = isSameDate(props.value, selectedDate);
return (
<div
className={
isSelected
? `${props.children.props.className}-selected`
: props.children.props.className
}
>
{props.children}
</div>
);
};
custom-calendar.css
.rbc-day-bg-selected {
flex: 1 0 0% !important;
border: 1px solid white !important;
border-radius: 5px !important;
background-color: green !important;
color: white !important;
}
클릭시 일자색 변경
클릭시 black -> white 색 변경
모든게 한번에 되면 좋겠지만.. 이 캘린더는 일자 영역을 잘게 쪼게어 놓았다.
클릭시 1, 2, 3 과 같은 일자색(day) 색을 변경하기 위해선 추가 작업이 필요하다.
dateHeader: CustomDateHeader 를 이용해준다.
<Calendar
backgroundColor={"#fff"}
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
eventPropGetter={dayOfWeekStyleGetter}
views={["month"]}
formats={formats}
selectable={true}
onSelectSlot={(slot) => {
setSelectedDate(slot.start);
}}
components={{
toolbar: CustomToolbar,
month: {
dateCellWrapper: CustomDateCellWrapper,
dateHeader: CustomDateHeader, // 추가
},
}}
/>
const CustomDateHeader = (props) => {
const isSelected = isSameDate(props.date, selectedDate);
return (
<div
style={{
color: isSelected ? "white" : "black",
}}
>
{props.label}
</div>
);
};
CustomerDateCellWrapper 와 차이점은 props내 label로 01, 02 와 같은 day 정보가 내려오는 것이다.
마찬가지로 console.log(props)로 찍어보면 쉽게 확인 가능하다.
클릭시 가격 정보 색 변경
마찬가지로 클릭시 black -> white로 가격색이 변경 되면 좋겠다.
해당 영역은 이벤트가 발생하는 영역이라고 해서
event: CustomEventContent 를 추가해주었다.
<Calendar
backgroundColor={"#fff"}
localizer={localizer}
events={events}
startAccessor="start"
endAccessor="end"
eventPropGetter={dayOfWeekStyleGetter}
views={["month"]}
formats={formats}
selectable={true}
onSelectSlot={(slot) => {
setSelectedDate(slot.start);
}}
components={{
month: {
dateCellWrapper: CustomDateCellWrapper,
dateHeader: CustomDateHeader,
event: CustomEventContent, // 추가
},
}}
/>
//핵심 로직
const CustomEventContent = (props) => {
const isSelected = isSameDate(props.event.start, selectedDate);
return (
<div
style={{
color: isSelected ? "white" : "black",
}}
>
{props.event.title}
</div>
);
};
(이제 똑같은 것을 3번 정도 반복 했으니 지겨울 수도 있겠지만 ..)
event의 날짜 정보는 props.event.start로 들어와서 클릭한 날짜와 동일 날짜인지 비교하는데 사용해준다.
핵심 로직은 이정도이고 외에 border 제거 등 내가 이용한 css는 아래에 첨부해두도록 하겠다.
혹시나 필요한 사람 있으면 참고하기를 바란다.
툴바도 커스텀한 부분이 있는데 그건 다음장에 작성하도록 하겠음.
결과물
custom-calendar.css
.rbc-day-bg {
border: 1px solid white !important;
border-radius: 5px !important;
background-color: green !important;
opacity: 0.1;
}
.rbc-off-range-bg {
background-color: #e6e6e6 !important;
border-radius: 5px !important;
}
.rbc-day-bg-selected {
flex: 1 0 0% !important;
border: 1px solid white !important;
border-radius: 5px !important;
background-color: green !important;
color: white !important;
}
.rbc-date-cell {
text-align: left !important;
padding-left: 5px !important;
}
.rbc-month-row + .rbc-month-row {
border: none !important;
}
.rbc-month-view {
border: none !important;
}
.rbc-header {
border-bottom: 1px solid white !important;
}
.rbc-header + .rbc-header {
border-left: 1px solid white !important;
}
.rbc-day-bg rbc-off-range-bg {
background-color: #e6e6e6 !important;
}
요약
- 사실 저번주엔 커스텀에 실패했었다. 그 이유는 css 파일로만 수정하려고 했기 때문임
- Calendar 같은 경우엔 라이브러리를 그대로 사용할 경우는 많이 없을 것 같다. (커스텀 필수) 이번 기회에 내맛대로 커스텀하면서 재밌었음
- react-big-calendar말고 react-calendar도 있던데 다음에 사용해 봐야겠다.
이벤트 커스텀 했던 포스팅 추가로 작성했다.
https://mingg123.tistory.com/287
'FrontEnd' 카테고리의 다른 글
[CSS] position:fixed 사용시 width가 변하는 현상 (0) | 2024.04.13 |
---|---|
[Calendar] react-big-calendar event custom(커스텀) 하기 2 (0) | 2024.04.13 |
[Next.js] Image 컴포넌트 html2canvas 시 이미지가 깨지는 현상 (0) | 2024.02.04 |
[React+MUI5] 테이블 렌더링 최적화 (1) | 2023.10.24 |
[함수형 프로그래밍] 9장 계층형 설계 2 (0) | 2023.10.22 |