ComponentsP3 본문

DatePicker

Input형 트리거 + Calendar 팝업 — 단일/범위 날짜를 비제어로 선택하고, docked popup은 closing exit 뒤 정리하며 트리거에 YYYY-MM-DD로 표시합니다.

마지막 업데이트 2026-07-01

한눈에#

Input형 트리거 + Calendar 팝업으로 하나의 날짜(또는 범위)를 고릅니다 — 선택을 완료하면 팝업이 닫히고 트리거에 YYYY-MM-DD로 표시됩니다.

단일 선택 — mode: single (기본)

아직 선택 없음

범위 선택 — mode: range (시작 → 끝, 역순은 자동 정렬)

아직 선택 없음

  • Input형 트리거 + Calendar 팝업
  • single·range 모드
  • docked·modal·modalInput
  • 비제어 + BottomSheet 모바일

트리거 높이는 input.height로 Input과 같은 폼 줄맞춤 — 팝업은 APG grid 달력

사용 시점#

폼에서 하나의 날짜(또는 가끔 범위)를 고르면 DatePicker — 업무 조회 기간이나 시각만 고르면 다른 컴포넌트입니다.

권장 — 이렇게 쓰세요

지양 — 이러지 마세요

쓴다마감일·생일·예약일처럼 하나의 날짜(mode=range로 시작~끝도 가능)를 폼 필드로

대신 DateRangePicker연·월·분기 프리셋 + 듀얼 먼스로 업무 조회 기간을 고를 때

대신 TimePicker날짜 없이 시각만 고를 때

플레이그라운드#

컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

DatePicker를 직접 조작해 보세요

속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.

빌더 열기

플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.

변형#

mode가 변형 축입니다 — 'single'(기본)은 클릭 한 번으로 확정되고, 'range'는 시작 → 끝 두 번 클릭으로 확정됩니다. 끝을 시작보다 앞에 찍으면 자동으로 스왑되고, 확정 뒤 세 번째 클릭은 새 범위를 시작합니다. 범위 표시는 'YYYY-MM-DD ~ YYYY-MM-DD'입니다. 달력의 주 시작은 weekStartsOn으로 조정하며 기본값은 월요일 시작입니다. weekStartsOn="sunday"를 주면 일요일 시작 달력으로 표시되고 Home/End 키보드 이동도 일~토 기준을 따릅니다.

데스크톱 변형 (ADR-012 B-P2)#

variant데스크톱(비 compact) 표시 방식을 가릅니다(M3 date picker 3변형) —

  • docked (기본): 트리거 하단에 앵커되는 팝업. 날짜를 클릭하면 즉시 확정되고 닫힙니다(기존 동작).
  • modal: 화면 중앙의 Modal에 달력을 띄우고 취소/확인으로 마무리합니다. 모바일 시트와 동일한 임시 선택(확인 시에만 onChange) 흐름입니다.
  • modalInput: modal에 더해 직접 입력 필드(YYYY-MM-DD)를 둡니다(단일 모드). 타이핑과 달력 선택을 모두 허용하며 — 달력 선택은 입력 필드에 동기화되고, 유효한 날짜를 입력하면 임시 선택이 갱신됩니다. 범위 모드에서는 입력 필드 없이 modal처럼 동작합니다.

responsive='auto'인 compact 뷰포트에서는 변형과 무관하게 BottomSheet가 우선합니다 (DK 모바일 표준 — ## 모바일 참조).

크기#

단일 크기입니다 — 트리거 높이는 input.height(= control-height-md)로 Input과 같은 어휘를 공유합니다. 3단 size는 component 토큰 신설 기준(§4) 미충족으로 P5 패리티 요구 시 재평가합니다.

상태#

비제어 컴포넌트입니다 — defaultValue로 시작하고 선택 완료 시 onChange로 알립니다. 열림/닫힘도 내부 소유: 트리거 클릭으로 열고, 선택 완료·Escape·외부 클릭으로 닫힙니다(Escape·선택 완료는 트리거로 포커스 복원). 트리거의 Hover/Focus/Disabled는 CSS 의사클래스로 표현되며, 열림 동안 aria-expanded="true"가 유지됩니다. docked 팝업은 닫힘 요청 시 즉시 제거하지 않고 closing 상태로 anchor-origin fade/scale-out을 완료한 뒤 unmount합니다.

모바일#

DK 모바일 재활용 표준입니다 — mobile을 켜면 팝업 대신 BottomSheet 안에 Calendar가 렌더되고, footer의 취소/확인 버튼으로 마무리합니다. 날짜를 골라도 즉시 확정되지 않는 임시 선택이며, 확인을 눌러야 onChange가 발화하고 시트가 닫힙니다. 취소·Escape·배경 닫기는 임시 선택을 폐기합니다(범위 모드도 동일 — 시작·끝을 고른 뒤 확인으로 확정). 시트 제목은 mobileTitle(기본 placeholder), 버튼 라벨은 confirmLabel/cancelLabel로 바꿉니다. 모바일 시트 안 Calendar는 별도 테두리 카드로 가두지 않고, 시트 본문 폭을 쓰는 borderless content로 렌더합니다. 라이브 데모는 데스크톱 뷰포트라 코드로 안내합니다.

<DatePicker
  mobile
  mobileTitle="기간 선택"
  mode="range"
  confirmLabel="적용"
  onChange={(range) => applyPeriod(range)}
/>

Props#

Prop타입기본값설명
mode'single' | 'range''single' as M선택 단위 — 단일 날짜 또는 시작·끝 범위
defaultValueDateRange | Date초기 선택값 (비제어) — range면 { start, end }
onChange(value: CalendarValue<M>) => void선택 완료 콜백 — 단일은 클릭, 범위는 끝 선택 시점
placeholderstring날짜 선택값이 없을 때 트리거에 표시되는 텍스트 — 팝업 dialog의 접근 가능한 이름으로도 사용
variant'docked' | 'modal' | 'modalInput'docked데스크톱(비 compact) 표시 변형 (ADR-012 B-P2) — docked(기본): 트리거 하단 앵커 팝업(즉시 선택) · modal: 중앙 Modal + 취소/확인(임시 선택) · modalInput: Modal에 직접 입력 필드 추가(단일 모드). compact+auto는 변형과 무관하게 BottomSheet 유지.
weekStartsOn'monday' | 'sunday'monday주 시작 요일 — 기본 monday. sunday면 달력과 키보드 Home/End가 일~토 기준
responsive'auto' | 'mobile' | 'desktop'적응형 표시 (ADR-012) — auto(기본): compact 뷰포트에서 borderless/full-width Calendar BottomSheet(임시 선택→확인) 전환. mobile/desktop은 강제 override
mobilebooleanfalse@deprecated responsive='mobile' 사용. true면 BottomSheet 강제 — 하위호환 alias
mobileTitlestring시트 제목 — 기본: placeholder
confirmLabelstring확인mobile 확정 버튼 라벨
cancelLabelstring취소mobile 취소 버튼 라벨
refRef<HTMLButtonElement>트리거 <button>으로 (병합) 전달되는 ref (React 19 ref-as-prop)

트리거는 네이티브 button 속성을 확장합니다 — disabled, className 등이 그대로 전달됩니다 (onChange/value/defaultValue는 컴포넌트 시그니처로 대체).

접근성#

계약구현
트리거aria-haspopup="dialog" + aria-expanded
팝업role="dialog"placeholder가 접근 가능한 이름
달력role="grid" APG 패턴 — roving tabindex(포커스 셀만 0)
키보드 이동화살표(일) · Home/End(weekStartsOn 기준 주 시작·끝) · PageUp/Down(월)
선택Enter·Space — 비활성(min/max/disabled) 날짜는 선택·포커스 불가
오늘aria-current="date"
닫기Escape(트리거 포커스 복원) · 외부 클릭 · 선택 완료
월 라벨Intl ko-KR “2026년 6월” — 월/연도 선택 버튼 + aria-live="polite" 갱신 안내
모션팝업 등장은 opacity/transform만 + prefers-reduced-motion 존중

토큰#

component 토큰 없이 semantic(+input 어휘)을 직접 소비합니다(신설 기준 §4 미충족).

속성토큰
트리거input.height · input.bg · input.border · input.radius · input.fg · input.placeholder
트리거 포커스/열림color.focus-ring(링) · input.border-focus
팝업color.surface-raised · radius.md · shadow.lg · z.dropdown
달력 선택/범위color.primary · color.on-primary · color.primary-subtle · color.primary-text
달력 hover/눌림color.surface-hover / color.surface-pressed (선택·범위 면은 안 덮음)
모션등장 spring.effect.fast + ease.emphasized-decelerate, 닫힘 spring.effect.fast + ease.emphasized-accelerate, 상태 전환 ease.standard

관련#