Calendar

Calendar (캘린더)

Calendar는 스케줄, 시간표, 가격 달력, 음력 달력처럼 데이터가 날짜 형태일 때 사용하는 컴포넌트예요. 연도/월 전환도 지원해요.

출처: 문서

본문

언제 사용하나요

데이터가 날짜 형태일 때 사용해요. 스케줄, 시간표, 가격 달력, 음력 달력 같은 경우요. 이 컴포넌트는 연도/월 전환도 지원해요.

예제 (Examples)

기본 (Basic)

연도/월 전환을 지원하는 기본 캘린더 컴포넌트예요.

import React from 'react';
import { Calendar } from 'antd';
import type { CalendarProps } from 'antd';
import type { Dayjs } from 'dayjs';

const App: React.FC = () => {
  const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
    console.log(value.format('YYYY-MM-DD'), mode);
  };

  return <Calendar onPanelChange={onPanelChange} />;
};

export default App;

공지 캘린더 (Notice Calendar)

dateCellRender와 monthCellRender를 필요한 데이터와 함께 사용해 이 컴포넌트를 렌더링할 수 있어요.

import React from 'react';
import type { BadgeProps, CalendarProps } from 'antd';
import { Badge, Calendar } from 'antd';
import { createStyles } from 'antd-style';
import type { Dayjs } from 'dayjs';

const useStyles = createStyles((props) => {
  const { prefixCls, css } = props;
  return {
    events: css`
      margin: 0;
      padding: 0;
      list-style: none;
      .${prefixCls}-badge-status {
        width: 100%;
        overflow: hidden;
        font-size: 12px;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    `,
    notesMonth: css`
      font-size: 28px;
      text-align: center;
      section {
        font-size: 28px;
      }
    `,
  };
});

const getListData = (value: Dayjs) => {
  let listData: { type: string; content: string }[] = []; // Specify the type of listData
  switch (value.date()) {
    case 8:
      listData = [
        { type: 'warning', content: 'This is warning event.' },
        { type: 'success', content: 'This is usual event.' },
      ];
      break;
    case 10:
      listData = [
        { type: 'warning', content: 'This is warning event.' },
        { type: 'success', content: 'This is usual event.' },
        { type: 'error', content: 'This is error event.' },
      ];
      break;
    case 15:
      listData = [
        { type: 'warning', content: 'This is warning event' },
        { type: 'success', content: 'This is very long usual event......' },
        { type: 'error', content: 'This is error event 1.' },
        { type: 'error', content: 'This is error event 2.' },
        { type: 'error', content: 'This is error event 3.' },
        { type: 'error', content: 'This is error event 4.' },
      ];
      break;
    default:
      break;
  }
  return listData || [];
};

const getMonthData = (value: Dayjs) => {
  if (value.month() === 8) {
    return 1394;
  }
  return undefined;
};

const App: React.FC = () => {
  const { styles } = useStyles();

  const monthCellRender = (value: Dayjs) => {
    const num = getMonthData(value);
    return num ? (
      <div className={styles.notesMonth}>
        <section>{num}</section>
        <span>Backlog number</span>
      </div>
    ) : null;
  };

  const dateCellRender = (value: Dayjs) => {
    const listData = getListData(value);
    return (
      <ul className={styles.events}>
        {listData.map((item) => (
          <li key={item.content}>
            <Badge status={item.type as BadgeProps['status']} text={item.content} />
          </li>
        ))}
      </ul>
    );
  };

  const cellRender: CalendarProps<Dayjs>['cellRender'] = (current, info) => {
    if (info.type === 'date') {
      return dateCellRender(current);
    }
    if (info.type === 'month') {
      return monthCellRender(current);
    }
    return info.originNode;
  };

  return <Calendar cellRender={cellRender} />;
};

export default App;

이벤트 범위 (Event Range)

cellRender로 여러 날에 걸친 이벤트 범위를 렌더링해요. 예제는 각 날짜가 시작, 중간, 끝 또는 단일 이벤트인지 계산해 압축된 범위 막대를 그려요.

import React from 'react';
import { Calendar, theme } from 'antd';
import type { CalendarProps } from 'antd';
import { createStyles } from 'antd-style';
import { clsx } from 'clsx';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';

const useStyle = createStyles(({ cssVar, css }) => {
  const barRadius = 999;

  const {
    controlHeight,
    marginXXS,
    controlHeightSM,
    colorTextLightSolid,
    fontSizeSM,
    paddingXS,
    marginXS,
    paddingXXS,
  } = cssVar;

  return {
    itemContent: css`
      overflow: visible;
    `,
    cell: css`
      min-height: ${controlHeight};
    `,
    list: css`
      display: flex;
      flex-direction: column;
      gap: ${marginXXS};
      margin-top: ${marginXXS};
    `,
    bar: css`
      display: block;
      height: calc(${controlHeightSM} - ${marginXXS});
      overflow: hidden;
      color: ${colorTextLightSolid};
      font-size: ${fontSizeSM};
      white-space: nowrap;
      text-overflow: ellipsis;
    `,
    barStart: css`
      margin-inline-end: calc(-1 * (${paddingXS} + ${marginXS} / 2));
      padding-inline-start: calc(${paddingXXS} + ${paddingXXS});
      border-start-start-radius: ${barRadius}px;
      border-end-start-radius: ${barRadius}px;
    `,
    barMiddle: css`
      margin-inline: calc(-1 * (${paddingXS} + ${marginXS} / 2));
    `,
    barEnd: css`
      margin-inline-start: calc(-1 * (${paddingXS} + ${marginXS} / 2));
      border-start-end-radius: ${barRadius}px;
      border-end-end-radius: ${barRadius}px;
    `,
    barSingle: css`
      padding-inline-start: calc(${paddingXXS} + ${paddingXXS});
      border-radius: ${barRadius}px;
    `,
  };
});

export interface CalendarEvent {
  key: string;
  title: string;
  start: Dayjs;
  end: Dayjs;
  color: string;
}

const getEvents = (token: ReturnType<typeof theme.useToken>['token']): CalendarEvent[] => [
  {
    key: 'release',
    title: 'Release window',
    start: dayjs('2026-01-08'),
    end: dayjs('2026-01-10'),
    color: token.colorPrimary,
  },
  {
    key: 'design-review',
    title: 'Design review',
    start: dayjs('2026-01-14'),
    end: dayjs('2026-01-14'),
    color: token.colorSuccess,
  },
  {
    key: 'maintenance',
    title: 'Maintenance',
    start: dayjs('2026-01-21'),
    end: dayjs('2026-01-24'),
    color: token.colorWarning,
  },
  {
    key: 'bug-fix',
    title: 'Bug fix',
    start: dayjs('2026-01-30'),
    end: dayjs('2026-01-31'),
    color: token.colorError,
  },
];

const isInRange = (current: Dayjs, event: CalendarEvent) => {
  return !current.isBefore(event.start, 'day') && !current.isAfter(event.end, 'day');
};

const getRangePosition = (current: Dayjs, event: CalendarEvent) => {
  const starts = current.isSame(event.start, 'day');
  const ends = current.isSame(event.end, 'day');

  if (starts && ends) {
    return 'single';
  }

  if (starts) {
    return 'start';
  }

  if (ends) {
    return 'end';
  }

  return 'middle';
};

const App: React.FC = () => {
  const { token } = theme.useToken();
  const { styles } = useStyle();
  const events = React.useMemo(() => getEvents(token), [token]);

  const cellRender = React.useCallback<NonNullable<CalendarProps<Dayjs>['cellRender']>>(
    (current, info) => {
      if (info.type !== 'date') {
        return null;
      }

      const currentEvents = events.filter((event) => isInRange(current, event));

      return (
        <div className={styles.cell}>
          <div className={styles.list}>
            {currentEvents.map((event) => {
              const position = getRangePosition(current, event);
              const rangeClassName = {
                start: styles.barStart,
                middle: styles.barMiddle,
                end: styles.barEnd,
                single: styles.barSingle,
              }[position];
              return (
                <span
                  key={event.key}
                  className={clsx(styles.bar, rangeClassName)}
                  style={{ backgroundColor: event.color }}
                >
                  {position === 'start' || position === 'single' ? event.title : null}
                </span>
              );
            })}
          </div>
        </div>
      );
    },
    [events, styles],
  );

  return (
    <Calendar
      classNames={{ itemContent: styles.itemContent }}
      defaultValue={dayjs('2026-01-01')}
      cellRender={cellRender}
    />
  );
};

export default App;

카드 (Card)

제한된 공간에서 렌더링을 위해 컨테이너 요소 안에 중첩돼요.

import React from 'react';
import { Calendar, theme } from 'antd';
import type { CalendarProps } from 'antd';
import type { Dayjs } from 'dayjs';

const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
  console.log(value.format('YYYY-MM-DD'), mode);
};

const App: React.FC = () => {
  const { token } = theme.useToken();

  const wrapperStyle: React.CSSProperties = {
    width: 300,
    border: `${token.lineWidth}px ${token.lineType} ${token.colorBorderSecondary}`,
    borderRadius: token.borderRadiusLG,
  };

  return (
    <div style={wrapperStyle}>
      <Calendar fullscreen={false} onPanelChange={onPanelChange} />
    </div>
  );
};

export default App;

선택 가능한 캘린더 (Selectable Calendar)

연도/월 전환을 지원하는 기본 캘린더 컴포넌트예요.

import React, { useState } from 'react';
import { Alert, Calendar } from 'antd';
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';

const App: React.FC = () => {
  const [value, setValue] = useState(() => dayjs('2017-01-25'));
  const [selectedValue, setSelectedValue] = useState(() => dayjs('2017-01-25'));

  const onSelect = (newValue: Dayjs) => {
    setValue(newValue);
    setSelectedValue(newValue);
  };

  const onPanelChange = (newValue: Dayjs) => {
    setValue(newValue);
  };

  return (
    <>
      <Alert title={`You selected date: ${selectedValue?.format('YYYY-MM-DD')}`} />
      <Calendar value={value} onSelect={onSelect} onPanelChange={onPanelChange} />
    </>
  );
};

export default App;

음력 달력 (Lunar Calendar)

음력 달력, 절기 같은 정보를 표시해요.

import React from 'react';
import { Calendar, Col, Radio, Row, Select } from 'antd';
import type { CalendarProps } from 'antd';
import { createStyles } from 'antd-style';
import type { DefaultOptionType } from 'antd/es/select';
import { clsx } from 'clsx';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
import { HolidayUtil, Lunar } from 'lunar-typescript';

const useStyle = createStyles(({ cssVar, token, css, cx }) => {
  const lunar = css`
    color: ${token.colorTextTertiary};
    font-size: ${token.fontSizeSM}px;
  `;
  const weekend = css`
    color: ${token.colorError};
    &.gray {
      opacity: 0.4;
    }
  `;
  return {
    wrapper: css`
      width: 450px;
      border: ${token.lineWidth}px ${token.lineType} ${token.colorBorderSecondary};
      border-radius: ${token.borderRadiusOuter};
      padding: 5px;
    `,
    dateCell: css`
      position: relative;
      &:before {
        content: '';
        position: absolute;
        inset-inline-start: 0;
        inset-inline-end: 0;
        top: 0;
        bottom: 0;
        margin: auto;
        max-width: 40px;
        max-height: 40px;
        background: transparent;
        transition: background-color ${cssVar.motionDurationSlow};
        border-radius: ${token.borderRadiusOuter}px;
        border: ${token.lineWidth}px ${token.lineType} transparent;
        box-sizing: border-box;
      }
      &:hover:before {
        background: ${token.controlItemBgHover};
      }
    `,
    today: css`
      &:before {
        border: ${token.lineWidth}px ${token.lineType} ${token.colorPrimary};
      }
    `,
    text: css`
      position: relative;
      z-index: 1;
    `,
    lunar,
    current: css`
      color: ${token.colorTextLightSolid};
      &:before {
        background: ${token.colorPrimary};
      }
      &:hover:before {
        background: ${token.colorPrimary};
        opacity: 0.8;
      }
      .${cx(lunar)} {
        color: ${token.colorTextLightSolid};
        opacity: 0.9;
      }
      .${cx(weekend)} {
        color: ${token.colorTextLightSolid};
      }
    `,
    monthCell: css`
      width: 120px;
      color: ${token.colorTextBase};
      border-radius: ${token.borderRadiusOuter}px;
      padding: 5px 0;
      &:hover {
        background: ${token.controlItemBgHover};
      }
    `,
    monthCellCurrent: css`
      color: ${token.colorTextLightSolid};
      background: ${token.colorPrimary};
      &:hover {
        background: ${token.colorPrimary};
        opacity: 0.8;
      }
    `,
    weekend,
  };
});

const App: React.FC = () => {
  const { styles } = useStyle({ test: true });

  const [selectDate, setSelectDate] = React.useState<Dayjs>(() => dayjs());
  const [panelDate, setPanelDate] = React.useState<Dayjs>(() => dayjs());

  const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
    console.log(value.format('YYYY-MM-DD'), mode);
    setPanelDate(value);
  };

  const onDateChange: CalendarProps<Dayjs>['onSelect'] = (value) => {
    setSelectDate(value);
  };

  const cellRender: CalendarProps<Dayjs>['fullCellRender'] = (date, info) => {
    const d = Lunar.fromDate(date.toDate());
    const lunar = d.getDayInChinese();
    const solarTerm = d.getJieQi();
    const isWeekend = date.day() === 6 || date.day() === 0;
    const h = HolidayUtil.getHoliday(date.get('year'), date.get('month') + 1, date.get('date'));
    const displayHoliday = h?.getTarget() === h?.getDay() ? h?.getName() : undefined;
    if (info.type === 'date') {
      return React.cloneElement(info.originNode, {
        ...(info.originNode as React.ReactElement<any>).props,
        className: clsx(styles.dateCell, {
          [styles.current]: selectDate.isSame(date, 'date'),
          [styles.today]: date.isSame(dayjs(), 'date'),
        }),
        children: (
          <div className={styles.text}>
            <span
              className={clsx({
                [styles.weekend]: isWeekend,
                gray: !panelDate.isSame(date, 'month'),
              })}
            >
              {date.get('date')}
            </span>
            {info.type === 'date' && (
              <div className={styles.lunar}>{displayHoliday || solarTerm || lunar}</div>
            )}
          </div>
        ),
      });
    }

    if (info.type === 'month') {
      // Due to the fact that a solar month is part of the lunar month X and part of the lunar month X+1,
      // when rendering a month, always take X as the lunar month of the month
      const d2 = Lunar.fromDate(new Date(date.get('year'), date.get('month')));
      const month = d2.getMonthInChinese();
      return (
        <div
          className={clsx(styles.monthCell, {
            [styles.monthCellCurrent]: selectDate.isSame(date, 'month'),
          })}
        >
          {date.get('month') + 1}月({month}月)
        </div>
      );
    }
  };

  const getYearLabel = (year: number) => {
    const d = Lunar.fromDate(new Date(year + 1, 0));
    return `${d.getYearInChinese()}年(${d.getYearInGanZhi()}${d.getYearShengXiao()}年)`;
  };

  const getMonthLabel = (month: number, value: Dayjs) => {
    const d = Lunar.fromDate(new Date(value.year(), month));
    const lunar = d.getMonthInChinese();
    return `${month + 1}月(${lunar}月)`;
  };

  return (
    <div className={styles.wrapper}>
      <Calendar
        fullCellRender={cellRender}
        fullscreen={false}
        onPanelChange={onPanelChange}
        onSelect={onDateChange}
        headerRender={({ value, type, onChange, onTypeChange }) => {
          const start = 0;
          const end = 12;
          const monthOptions: DefaultOptionType[] = [];

          let current = value.clone();
          const localeData = value.localeData();
          const months: dayjs.MonthNames[] = [];
          for (let i = 0; i < 12; i++) {
            current = current.month(i);
            months.push(localeData.monthsShort(current));
          }

          for (let i = start; i < end; i++) {
            monthOptions.push({
              label: getMonthLabel(i, value),
              value: i,
            });
          }

          const year = value.year();
          const month = value.month();
          const options: DefaultOptionType[] = [];
          for (let i = year - 10; i < year + 10; i += 1) {
            options.push({
              label: getYearLabel(i),
              value: i,
            });
          }
          return (
            <Row justify="end" gutter={8} style={{ padding: 8 }}>
              <Col>
                <Select
                  size="small"
                  popupMatchSelectWidth={false}
                  className="my-year-select"
                  value={year}
                  options={options}
                  onChange={(newYear) => {
                    const now = value.clone().year(newYear);
                    onChange(now);
                  }}
                />
              </Col>
              <Col>
                <Select
                  size="small"
                  popupMatchSelectWidth={false}
                  value={month}
                  options={monthOptions}
                  onChange={(newMonth) => {
                    const now = value.clone().month(newMonth);
                    onChange(now);
                  }}
                />
              </Col>
              <Col>
                <Radio.Group
                  size="small"
                  onChange={(e) => onTypeChange(e.target.value)}
                  value={type}
                >
                  <Radio.Button value="month">月</Radio.Button>
                  <Radio.Button value="year">年</Radio.Button>
                </Radio.Group>
              </Col>
            </Row>
          );
        }}
      />
    </div>
  );
};

export default App;

주 번호 표시 (Show Week)

showWeek prop을 true로 설정해 전체 화면 캘린더에 주 번호를 표시해요.

import React from 'react';
import { Calendar } from 'antd';

const App: React.FC = () => (
  <>
    <Calendar fullscreen showWeek />
    <br />
    <Calendar fullscreen={false} showWeek />
  </>
);

export default App;

헤더 커스터마이즈 (Customize Header)

Calendar 헤더 콘텐츠를 커스터마이즈해요.

import React from 'react';
import dayjs from 'dayjs';

import 'dayjs/locale/zh-cn';

import { Calendar, Flex, Radio, Select, theme, Typography } from 'antd';
import type { CalendarProps } from 'antd';
import type { Dayjs } from 'dayjs';
import dayLocaleData from 'dayjs/plugin/localeData';

dayjs.extend(dayLocaleData);

const App: React.FC = () => {
  const { token } = theme.useToken();

  const onPanelChange = (value: Dayjs, mode: CalendarProps<Dayjs>['mode']) => {
    console.log(value.format('YYYY-MM-DD'), mode);
  };

  const wrapperStyle: React.CSSProperties = {
    width: 300,
    border: `${token.lineWidth}px ${token.lineType} ${token.colorBorderSecondary}`,
    borderRadius: token.borderRadiusLG,
  };

  return (
    <div style={wrapperStyle}>
      <Calendar
        fullscreen={false}
        headerRender={({ value, type, onChange, onTypeChange }) => {
          const year = value.year();
          const month = value.month();

          const yearOptions = Array.from({ length: 20 }, (_, i) => {
            const label = year - 10 + i;
            return { label, value: label };
          });

          const monthOptions = value
            .localeData()
            .monthsShort()
            .map((label, index) => ({
              label,
              value: index,
            }));

          return (
            <div style={{ padding: 8 }}>
              <Typography.Title level={4}>Custom header</Typography.Title>
              <Flex gap={8}>
                <Radio.Group
                  size="small"
                  onChange={(e) => onTypeChange(e.target.value)}
                  value={type}
                >
                  <Radio.Button value="month">Month</Radio.Button>
                  <Radio.Button value="year">Year</Radio.Button>
                </Radio.Group>
                <Select
                  size="small"
                  popupMatchSelectWidth={false}
                  value={year}
                  options={yearOptions}
                  onChange={(newYear) => {
                    const now = value.clone().year(newYear);
                    onChange(now);
                  }}
                />
                <Select
                  size="small"
                  popupMatchSelectWidth={false}
                  value={month}
                  options={monthOptions}
                  onChange={(newMonth) => {
                    const now = value.clone().month(newMonth);
                    onChange(now);
                  }}
                />
              </Flex>
            </div>
          );
        }}
        onPanelChange={onPanelChange}
      />
    </div>
  );
};

export default App;

커스텀 시맨틱 DOM 스타일링

classNames와 styles에 객체/함수를 전달해 Calendar의 시맨틱 DOM 스타일을 커스터마이즈할 수 있어요.

import React from 'react';
import { Calendar, Flex } from 'antd';
import type { CalendarProps, GetProp } from 'antd';
import { createStyles } from 'antd-style';
import type { Dayjs } from 'dayjs';

const useStyles = createStyles(({ token }) => ({
  root: {
    padding: 10,
    backgroundColor: token.colorPrimaryBg,
  },
}));

const stylesObject: CalendarProps<Dayjs>['styles'] = {
  root: {
    borderRadius: 8,
    width: 600,
  },
};

const stylesFunction: CalendarProps<Dayjs>['styles'] = (
  info,
): GetProp<CalendarProps<Dayjs>, 'styles', 'Return'> => {
  if (info.props.fullscreen) {
    return {
      root: {
        border: '2px solid #BDE3C3',
        borderRadius: 10,
        backgroundColor: 'rgba(189,227,195, 0.3)',
      },
    };
  }
};

const App: React.FC = () => {
  const { styles: classNames } = useStyles();
  return (
    <Flex vertical gap="medium">
      <Calendar fullscreen={false} classNames={classNames} styles={stylesObject} />
      <Calendar classNames={classNames} styles={stylesFunction} />
    </Flex>
  );
};

export default App;

API

공통 props 참고: Common props

참고: Calendar의 locale 일부는 value에서 읽어요. 그래서 dayjs의 locale을 올바르게 설정해 주세요.

// The default locale is en-US, if you want to use other locale, just set locale in entry file globally.
// import dayjs from 'dayjs';
// import 'dayjs/locale/zh-cn';
// dayjs.locale('zh-cn');

<Calendar cellRender={cellRender} onPanelChange={onPanelChange} onSelect={onSelect} />
속성 설명 타입 기본값 버전 전역 설정
cellRender 셀 콘텐츠 커스터마이즈 function(current: dayjs, info: { prefixCls: string, originNode: React.ReactElement, today: dayjs, range?: 'start' | 'end', type: PanelMode, locale?: Locale, subType?: 'hour' | 'minute' | 'second' | 'meridiem' }) => React.ReactNode - 5.4.0 ×
classNames 컴포넌트 내부 각 시맨틱 구조의 클래스 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> - 6.0.0
dateFullCellRender 날짜 셀의 표시 커스터마이즈, 반환된 콘텐츠가 셀을 덮어씀. 5.4.0 이상에서는 fullCellRender를 사용하세요 function(date: Dayjs): ReactNode - < 5.4.0 ×
fullCellRender 셀 콘텐츠 커스터마이즈 function(current: dayjs, info: { prefixCls: string, originNode: React.ReactElement, today: dayjs, range?: 'start' | 'end', type: PanelMode, locale?: Locale, subType?: 'hour' | 'minute' | 'second' | 'meridiem' }) => React.ReactNode - 5.4.0 ×
defaultValue 기본 선택 날짜 dayjs - ×
disabledDate 선택할 수 없는 날짜를 지정하는 함수. currentDate는 value prop과 같은 dayjs 객체이므로 변경하지 마세요 (https://github.com/ant-design/ant-design/issues/30987) (currentDate: Dayjs) => boolean - ×
fullscreen 전체 화면으로 표시할지 여부 boolean true ×
showWeek 주 번호 표시 여부 boolean false 5.23.0 ×
styles 컴포넌트 내부 각 시맨틱 구조의 인라인 스타일 커스터마이즈. 객체 또는 함수 지원 Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> - 6.0.0
headerRender 패널에 커스텀 헤더 렌더링 function(object:{value: Dayjs, type: 'year' | 'month', onChange: f(), onTypeChange: f()}) - ×
locale 캘린더의 locale object (기본) ×
mode 캘린더의 표시 모드 month | year month ×
validRange 유효 범위 설정 [dayjs, dayjs] - ×
value 현재 선택 날짜 dayjs - ×
onChange 날짜가 바뀔 때 콜백 function(date: Dayjs) - ×
onPanelChange 패널이 바뀔 때 콜백 function(date: Dayjs, mode: string) - ×
onSelect 날짜가 선택될 때 콜백, source 정보 포함 function(date: Dayjs, info: { source: 'year' | 'month' | 'date' | 'customize' }) - info: 5.6.0 ×

시맨틱 DOM (Semantic DOM)

https://ant.design/components/calendar/semantic.md

디자인 토큰 (Design Token)

컴포넌트 토큰 (Calendar)

토큰 이름 설명 타입 기본값
fullBg 전체 캘린더의 배경색 string #ffffff
fullPanelBg 전체 캘린더 패널의 배경색 string #ffffff
itemActiveBg 선택된 날짜 항목의 배경색 string #e6f4ff
miniContentHeight mini 캘린더 콘텐츠의 높이 string | number 256
monthControlWidth 월 선택 너비 string | number 70
yearControlWidth 연도 선택 너비 string | number 80

전역 토큰 (Global Token)

토큰 이름 설명 타입 기본값
borderRadiusLG LG 크기 테두리 반지름, Card, Modal 등 큰 반지름 컴포넌트에 사용 number
borderRadiusSM SM 크기 테두리 반지름, Button, Input, Select 등 작은 입력 컴포넌트에 사용 number
colorBgContainer 컨테이너 배경색. 예: 기본 버튼, 입력박스 등. colorBgElevated와 혼동하지 말 것. string
colorFillSecondary 두 번째 채움 색 레벨. Rate, Skeleton 등 요소의 형태를 더 명확히 외곽. 세 번째 채움 색의 Hover 상태로도 사용(Table 등) string
colorIcon 약한 액션. 예: allowClear 또는 Alert 닫기 버튼 string
colorIconHover 약한 액션 호버 색. 예: allowClear 또는 Alert 닫기 버튼 string
colorPrimary 브랜드 색. 제품의 특성과 커뮤니케이션을 반영하는 가장 직접적인 시각 요소. 선택하면 완전한 색 팔레트가 자동 생성 string
colorSplit 구분선 색. colorBorderSecondary와 같지만 투명도가 있음. string
colorText W3C 표준을 준수하는 기본 텍스트 색. 가장 어두운 중성색이기도 함. string
colorTextDisabled 비활성 상태 텍스트의 색 제어. string
colorTextHeading 제목의 폰트 색 제어. string
colorTextLightSolid 배경색이 있는 텍스트의 하이라이트 색 제어. 예: Primary Button의 텍스트 string
colorTextTertiary 세 번째 텍스트 색 레벨. 폼 보충 설명 텍스트, 목록 설명 텍스트 같은 설명 텍스트에 주로 사용 string
controlHeightLG LG 컴포넌트 높이 number
controlHeightSM SM 컴포넌트 높이 number
controlItemBgActive 컨트롤 컴포넌트 항목의 활성 배경색 제어. string
controlItemBgHover 컨트롤 컴포넌트 항목의 호버 배경색 제어. string
fontFamily 시스템 기본 인터페이스 폰트와 화면 표시에 적합한 대체 폰트 라이브러리 세트 제공 string
fontSize 디자인 시스템에서 가장 널리 사용되는 폰트 크기. number
fontWeightStrong 제목 컴포넌트(h1, h2, h3 등)나 선택 항목의 폰트 두께 제어. number
lineHeight 텍스트의 줄 높이. number
lineType 기본 컴포넌트의 테두리 스타일 string
lineWidth 기본 컴포넌트의 테두리 너비 number
lineWidthBold Button, Input, Select 등 아웃라인 계열 컴포넌트의 기본 선 너비 number
marginXS 요소의 여백 제어, 작은 크기. number
marginXXS 요소의 여백 제어, 가장 작은 크기. number
motionDurationMid 모션 속도, 중간 속도. 중간 요소 애니메이션 상호작용에 사용. string
motionDurationSlow 모션 속도, 느린 속도. 대형 요소 애니메이션 상호작용에 사용. string
padding 요소의 패딩 제어. number
paddingSM 요소의 작은 패딩 제어. number
paddingXS 요소의 매우 작은 패딩 제어. number
paddingXXS 요소의 매우 작은 여분의 패딩 제어. number
screenXS 초소형 화면의 화면 너비 제어. number

FAQ

Calendar를 커스텀 날짜 라이브러리와 함께 사용하려면? {#faq-customize-date-library}

커스텀 날짜 라이브러리 사용 참고

날짜 관련 컴포넌트의 locale은 어떻게 설정하나요? {#faq-set-locale-date-components}

날짜 관련 컴포넌트의 locale 설정 참고

날짜 관련 컴포넌트 locale이 동작하지 않아요? {#faq-locale-not-working}

FAQ 날짜 관련 컴포넌트 locale이 동작하지 않아요? 참고

패널 클릭에서 날짜를 얻으려면? {#faq-get-date-panel-click}

onSelect가 제공하는 info.source가 도움이 돼요.

<Calendar
  onSelect={(date, { source }) => {
    if (source === 'date') {
      console.log('Panel Select:', source);
    }
  }}
/>

더 알아보기 (Learn more)