ComponentsP3 본문

DatePicker

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

마지막 업데이트 2026-06-11

한눈에#

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를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

import { DatePicker } from '@wds/ui-web';

<DatePicker />

변형#

mode가 변형 축입니다 — 'single'(기본)은 클릭 한 번으로 확정되고, 'range'는 시작 → 끝 두 번 클릭으로 확정됩니다. 끝을 시작보다 앞에 찍으면 자동으로 스왑되고, 확정 뒤 세 번째 클릭은 새 범위를 시작합니다. 범위 표시는 'YYYY-MM-DD ~ YYYY-MM-DD'입니다.

데스크톱 변형 (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"가 유지됩니다.

모바일#

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

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

Props#

Prop타입기본값설명
mode'single' | 'range''single'선택 단위 — 단일 날짜 또는 시작·끝 범위
defaultValueDate | DateRange초기 선택값 (비제어) — range면 { start, end }
onChange(value: Date | DateRange) => void선택 완료 콜백 — 단일은 클릭, 범위는 끝 선택 시점
placeholderstring'날짜 선택'값이 없을 때 트리거 텍스트 + 팝업 dialog의 aria-label
variant'docked' | 'modal' | 'modalInput''docked'데스크톱 표시 — docked: 앵커 팝업(즉시) · modal: 중앙 모달(확인) · modalInput: 모달+직접 입력(단일). compact는 BottomSheet 우선
mobilebooleanfalsetrue면 BottomSheet에서 임시 선택 → 확인으로 확정합니다 (DK 모바일 표준)
mobileTitlestring시트 제목 — 기본 placeholder
confirmLabelstring'확인'mobile 확정 버튼 라벨
cancelLabelstring'취소'mobile 취소 버튼 라벨

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

접근성#

계약구현
트리거aria-haspopup="dialog" + aria-expanded
팝업role="dialog"placeholder가 접근 가능한 이름
달력role="grid" APG 패턴 — roving tabindex(포커스 셀만 0)
키보드 이동화살표(일) · Home/End(주 시작·끝) · 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 (선택·범위 면은 안 덮음)
모션duration.fast · 팝업 등장 ease.emphasized-decelerate / ease.standard

관련#