Featuring Design System
Legacy

CoreCalendar

react-datepicker 기반 날짜 및 월 선택 캘린더 컴포넌트.

개요

CoreCalendarreact-datepicker를 래핑한 캘린더 컴포넌트입니다. 단일 날짜·날짜 범위·월 선택·월 범위 선택을 모두 지원하며, 커스텀 헤더와 액션 영역을 내장합니다.

  • 단일 / 범위 선택selectsRange prop으로 모드 전환
  • 월 선택 모드showMonthYearPicker로 연/월 단위 선택
  • monthsShown — 여러 달을 나란히 표시
  • actionsChildren — 캘린더 하단에 취소/확인 버튼 등 액션 추가
  • elevation — 컨테이너에 그림자 적용
  • customInput — 커스텀 트리거 입력 요소 지정
  • excludeDates — 특정 날짜/월 비활성화

Usage

기본 사용법 (단일 날짜 선택)

import { useState } from 'react';
import { CoreCalendar } from '@featuring-corp/components';

function Example() {
  const [date, setDate] = useState<Date | null>(null);

  return (
    <CoreCalendar
      selected={date}
      onChange={(date) => setDate(date)}
      locale="ko"
    />
  );
}

월 선택 모드

import { useState } from 'react';
import { CoreCalendar } from '@featuring-corp/components';

function Example() {
  const [date, setDate] = useState<Date | null>(null);

  return (
    <CoreCalendar
      selected={date}
      onChange={(date) => setDate(date)}
      locale="ko"
      showMonthYearPicker
    />
  );
}

날짜 범위 선택

selectsRange를 사용할 때 onChange[Date | null, Date | null] 튜플을 받습니다.

import { useState } from 'react';
import { CoreCalendar } from '@featuring-corp/components';

function Example() {
  const [startDate, setStartDate] = useState<Date | null>(null);
  const [endDate, setEndDate] = useState<Date | null>(null);

  return (
    <CoreCalendar
      startDate={startDate}
      endDate={endDate}
      locale="ko"
      selectsRange
      onChange={(dates) => {
        if (Array.isArray(dates)) {
          setStartDate(dates[0]);
          setEndDate(dates[1]);
        }
      }}
    />
  );
}

여러 달 표시 + 월 범위 선택

import { useState } from 'react';
import { CoreCalendar } from '@featuring-corp/components';

function Example() {
  const [startDate, setStartDate] = useState<Date | null>(null);
  const [endDate, setEndDate] = useState<Date | null>(null);

  return (
    <CoreCalendar
      startDate={startDate}
      endDate={endDate}
      locale="ko"
      selectsRange
      showMonthYearPicker
      monthsShown={2}
      onChange={(dates) => {
        if (Array.isArray(dates)) {
          setStartDate(dates[0]);
          setEndDate(dates[1]);
        }
      }}
    />
  );
}

제외할 날짜 설정

import { useState } from 'react';
import { addDays } from 'date-fns';
import { CoreCalendar } from '@featuring-corp/components';

function Example() {
  const [date, setDate] = useState<Date | null>(null);
  const today = new Date();

  return (
    <CoreCalendar
      selected={date}
      onChange={(date) => setDate(date)}
      locale="ko"
      excludeDates={[addDays(today, -3), addDays(today, 3), addDays(today, 4)]}
    />
  );
}

커스텀 Input과 액션 버튼

customInput으로 트리거를, actionsChildren으로 하단 액션 버튼을 교체합니다.

import { useState, forwardRef } from 'react';
import { CoreCalendar, CoreTextInput, CoreButton } from '@featuring-corp/components';
import { IconCalendarFilled, IconChevronDownOutline } from '@featuring-corp/icons';

const CustomInput = forwardRef<HTMLDivElement, { value?: string; onClick?: () => void }>(
  ({ value, onClick }, ref) => (
    <div ref={ref} onClick={onClick} style={{ cursor: 'pointer' }}>
      <CoreTextInput
        leadingElement={<IconCalendarFilled />}
        trailingElement={<IconChevronDownOutline />}
        width="360px"
        defaultValue={value}
        style={{ cursor: 'pointer' }}
      />
    </div>
  ),
);

function Example() {
  const [open, setOpen] = useState(false);
  const [startDate, setStartDate] = useState<Date | null>(null);
  const [endDate, setEndDate] = useState<Date | null>(null);

  return (
    <CoreCalendar
      startDate={startDate}
      endDate={endDate}
      customInput={<CustomInput />}
      open={open}
      locale="ko"
      selectsRange
      inline={false}
      dateFormat="yyyy.MM.dd"
      monthsShown={2}
      elevation
      onClickOutside={() => {
        setOpen(false);
        setStartDate(null);
        setEndDate(null);
      }}
      onChange={(dates) => {
        if (Array.isArray(dates)) {
          setStartDate(dates[0]);
          setEndDate(dates[1]);
        }
      }}
      actionsChildren={[
        <CoreButton
          key="cancel"
          text="취소"
          buttonType="tertiary"
          onClick={() => {
            setStartDate(null);
            setEndDate(null);
            setOpen(false);
          }}
        />,
        <CoreButton
          key="apply"
          text="확인"
          buttonType="secondary"
          onClick={() => setOpen(false)}
        />,
      ]}
    />
  );
}

Props

react-datepickerDatePickerProps를 기반으로 한 컴포넌트입니다. CoreCalendar 고유 props는 아래와 같습니다.

Prop

Type

CoreDayType

Prop

Type

스타일

Calendar Container

  • padding: spacing-400 (16px)
  • border-radius: radius-100
  • background-color: white
  • elevation prop이 true이면 elevation-8 그림자 적용

헤더 및 네비게이션

  • Header: height: 32px, display: flex, justify-content: center
  • Navigation 버튼: border-radius: radius-full
    • hover: background-color: background[2], 아이콘 stroke: icon-interactive

Day Cell

상태배경텍스트
기본text[1]
오늘primary[60] (bold + underline)
선택 / Range Start / Endprimary[60]text[6]
범위 내 (In Range)primary[10]text[1]
선택/범위 hoverprimary[70]text[6]
이번 달 외text[4]
disabled / excludedtoggle-disabled-bgtext[5]
  • Range Start: border-top-left-radius, border-bottom-left-radius: spacing-100
  • Range End: border-top-right-radius, border-bottom-right-radius: spacing-100
  • 셀 크기: 32px × 32px, margin-block: spacing-50

액션 영역

  • display: flex, justify-content: flex-end
  • gap: spacing-200 (8px)
  • 구분선(<hr>): height: 1px, background-color: border-default
  • 구분선 너비: calc(100% + spacing-800) (좌우 padding 상쇄)

여러 달 레이아웃

  • display: grid, grid-auto-flow: column, gap: spacing-600