기본으로 생성되었던 calendar 컴포넌트를 디자인 시안에 맞게 각 요소가 뭘 뜻하는지 정리하면서 하나씩 적용을 했다.
"use client";
import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { DayPicker } from "react-day-picker";
import { cn } from "@/lib/utils";
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
function Calendar({
className,
classNames,
showOutsideDays = true,
...props
}: CalendarProps) {
return (
<DayPicker
showOutsideDays={showOutsideDays} // 현재 월에 속하지 않는 날짜 표시 여부
className={cn("w-full", className)} // 기본 클래스와 사용자 정의 클래스 병합
classNames={{
// 캘린더의 전체적인 구조
months: "flex flex-col w-full", // 월 컨테이너
month: // 개별 월 컨테이너
"flex flex-col space-y-[18px] inset-0 absolute justify-center items-center",
// 상단 네비게이션
caption: // 년월 표시 및 네비게이션 영역
"flex w-full mt-[22px] relative justify-center items-center text-white",
caption_label: "body-16-r", // 년월 텍스트 스타일
nav: "space-x-1 flex items-center", // 이전/다음 월 네비게이션 컨테이너
nav_button: "h-2 w-2 bg-transparent opacity-50 hover:opacity-50", // 네비게이션 버튼 스타일
nav_button_previous: "absolute left-[85px] top-[3px]", // 이전 월 버튼 위치
nav_button_next: "absolute right-[85px] top-[3px]", // 다음 월 버튼 위치
// 달력 테이블 구조
table: "w-full border-collapse", // 전체 달력 테이블
head_row: // 요일 헤더 행
"flex items-center justify-center border-b border-[#797272] border-b pb-[14px] mb-3",
head_cell: // 요일 헤더 셀
"text-muted-foreground w-[43px] mt-1 font-medium text-xs leading-[12px] tracking-[-0.24px] text-secondary-200",
// 날짜 행
row: "flex w-full justify-center",
// 날짜 셀
cell: "h-10 w-[43px] text-center flex justify-center items-center relative",
// 날짜 스타일
// 기본 날짜
day: "text-white font-medium text-[12px] caption w-7 h-7 hover:bg-white/10 rounded-full",
day_range_end: "day-range-end", // 범위 선택 시 끝 날짜
day_selected: // 선택된 날짜
"bg-primary text-primary-foreground w-7 h-7 hover:bg-white/10 hover:text-primary-foreground focus:bg-white/10 focus:text-primary-foreground",
day_today: // 오늘 날짜
"bg-primary-50 w-7 h-7 rounded-full font-bold hover:bg-white/10 hover:text-white",
day_outside: // 현재 월에 속하지 않는 날짜
"day-outside text-muted-foreground text-white/30 text-[12px] aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
day_disabled: "text-muted-foreground opacity-50", // 비활성화된 날짜
day_range_middle: // 범위 선택 시 중간 날짜
"aria-selected:bg-accent aria-selected:text-accent-foreground",
day_hidden: "invisible", // 숨겨진 날짜
...classNames,
}}
// 네비게이션 아이콘 컴포넌트
components={
{
IconLeft: () => <ChevronLeft className="w-2 h-2" />, // 이전 월 화살표 아이콘
IconRight: () => <ChevronRight className="w-2 h-2" />, // 다음 월 화살표 아이콘
}
}
{...props}
/>
);
}
Calendar.displayName = "Calendar";
export { Calendar };
🚨 발생했던 문제
shadcn/ui 캘린더에 디자인 시안 css 를 적용 중 달력의 월을 변경하는 아이콘 크기를 줄여야했는데, 여러 방법으로 시도해봤지만 변화가 없었다.
nav_button 이나 IconLeft / IconRight 요소에 크기를 계속 바꿔봐도 아무 반응을 하지 않았고,
IconLeft/Right 를 아예 주석처리해도 사라지지도 않았다. 그럼 저 컴포넌츠는 아예 적용이 안되고 있는 것인가. .
nav_button: "h-2 w-2 bg-transparent opacity-50 hover:opacity-50",
components={
{
IconLeft: () => <ChevronLeft className="w-2 h-2" />,
IconRight: () => <ChevronRight className="w-2 h-2" />,
}
}
개발자 도구로 요소를 찍어보니 calendar 컴포넌트 내에서는 보이지 않는 요소들이 보였고 이 도구 안에서 크기를 변경하면 반영이 잘 되었다.ㅠ
❓ 원인
이전에 시도했던 방식들이 작동하지 않았던 이유로는 라이브러리의 기본 스타일이 커스텀 스타일을 덮어씌웠기 때문이었다.
✅ 해결방법
calendar 컴포넌트 내에서 여러가지 방법들을 시도해봤는데 결국에는 svg 태그안의 rdp-nav_icon class 명을 globals.css 에 넣어서 width와 height 값을 !important 로 주어서 값을 바꾸는데 성공했다.
.rdp-nav_icon {
width: 10px !important;
height: 10px !important;
}
!important
다른 스타일보다 우선순위를 높게 만들어 반드시 내가 지정한 이 크기가 적용되도록 해준다.
🧐 느낀점
라이브러리를 사용해서 기능은 쉽게 구현가능했지만, css 적용에서 속성들도 하나하나 찾아봐야하고 마음대로 되지 않아서 직접 구현하는 컴포넌트를 css 하는 것보다 많이 까다로웠고 시간이 오래걸렸다.
이번 경험으로 라이브러리를 선택할 때스타일 커스터마이징이 용이한지도 중요하게 생각해야할 부분임을 느꼈고, 또 복잡한 기능은 라이브러리를 활용하되, 스타일링이 중요한 경우 직접 구현도 고려해보면 좋을 것 같다. 그리고 개발자 도구로 라이브러리의 DOM 구조와 클래스명을 파악하는 것도 되게 꿀팁이었어서 앞으로 좀 더 활용해봐야겠다고 생각했다.
결국 라이브러리를 얼마나 잘 이해하고 활용하느냐가 중요한 것 같다.
'TIL' 카테고리의 다른 글
css 우선순위 문제 (0) | 2024.11.11 |
---|---|
자체 UT 후 계획 및 버그수정 (1) | 2024.11.08 |
[Refactoring] 바텀시트 재사용 컴포넌트로 분리하기 (0) | 2024.11.05 |
댓글&답글 삭제 유효성 적용하기 (1) | 2024.11.04 |
캘린더 일정관리 - 일정 시간 중복 체크 유효성 ② (0) | 2024.11.03 |