Date Time Range Picker
시작·종료 날짜와 각각의 현지 시각을 선택합니다.
용법
유지 보수 기간
여러 날에 걸친 유지 보수 기간의 시작·종료 시각을 각각 선택합니다.
여러 날에 걸친 유지 보수 기간의 시작·종료 시각을 각각 선택합니다.
<!-- Date Time Range Picker / Maintenance -->
<script setup lang="ts">
import { DateTimeRangePickerRoot, DateTimeRangePickerAnchor, DateTimeRangePickerStartDateTimeInput, DateTimeRangePickerEndDateTimeInput, DateTimeRangePickerTrigger, DateTimeRangePickerContent, DateTimeRangePickerPreviousWeek, DateTimeRangePickerPreviousMonth, DateTimeRangePickerPreviousYear, DateTimeRangePickerNextWeek, DateTimeRangePickerNextMonth, DateTimeRangePickerNextYear, DateTimeRangePickerWeekViewTrigger, DateTimeRangePickerMonthViewTrigger, DateTimeRangePickerYearViewTrigger, DateTimeRangePickerGrid, DateTimeRangePickerCell, DateTimeRangePickerMonthCell } from '@sectile/vue/date-time-range-picker'
import { CalendarDays } from '@lucide/vue'
const initialRange = {
start: {
date: { year: 2026, month: 8, day: 22 },
time: { hour: 9, minute: 30, second: 0, millisecond: 0 },
},
end: {
date: { year: 2026, month: 8, day: 25 },
time: { hour: 17, minute: 30, second: 0, millisecond: 0 },
},
}
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
</script>
<template>
<DateTimeRangePickerRoot :default-value="initialRange" v-slot="{ dates, months, view, viewMode }" class="catalog-stack catalog-temporal-picker">
<DateTimeRangePickerAnchor class="catalog-range-fields">
<label class="catalog-endpoint">
<span>Start</span>
<DateTimeRangePickerStartDateTimeInput class="catalog-input" aria-label="Start date and time" />
</label>
<label class="catalog-endpoint">
<span>End</span>
<DateTimeRangePickerEndDateTimeInput class="catalog-input" aria-label="End date and time" />
</label>
<DateTimeRangePickerTrigger class="catalog-picker-trigger" aria-label="Open date and time range picker">
<CalendarDays :size="18" aria-hidden="true" />
</DateTimeRangePickerTrigger>
</DateTimeRangePickerAnchor>
<DateTimeRangePickerContent class="catalog-popup catalog-picker-popup catalog-picker-popup--floating">
<div class="catalog-picker-toolbar">
<div class="catalog-inline">
<DateTimeRangePickerPreviousWeek v-if="viewMode === 'week'">‹</DateTimeRangePickerPreviousWeek>
<DateTimeRangePickerPreviousMonth v-else-if="viewMode === 'month'">‹</DateTimeRangePickerPreviousMonth>
<DateTimeRangePickerPreviousYear v-else>‹</DateTimeRangePickerPreviousYear>
<strong>{{ viewMode === 'year' ? view.year : monthNames[view.month - 1] + ' ' + view.year }}</strong>
<DateTimeRangePickerNextWeek v-if="viewMode === 'week'">›</DateTimeRangePickerNextWeek>
<DateTimeRangePickerNextMonth v-else-if="viewMode === 'month'">›</DateTimeRangePickerNextMonth>
<DateTimeRangePickerNextYear v-else>›</DateTimeRangePickerNextYear>
</div>
<div class="catalog-view-switch">
<DateTimeRangePickerWeekViewTrigger>Week</DateTimeRangePickerWeekViewTrigger>
<DateTimeRangePickerMonthViewTrigger>Month</DateTimeRangePickerMonthViewTrigger>
<DateTimeRangePickerYearViewTrigger>Year</DateTimeRangePickerYearViewTrigger>
</div>
</div>
<DateTimeRangePickerGrid v-if="viewMode !== 'year'" class="catalog-calendar" :data-view="viewMode">
<DateTimeRangePickerCell
v-for="day in dates.flat()"
:key="[day.year, day.month, day.day].join('-')"
:value="day"
>
{{ day.day }}
</DateTimeRangePickerCell>
</DateTimeRangePickerGrid>
<DateTimeRangePickerGrid v-else class="catalog-month-grid">
<DateTimeRangePickerMonthCell
v-for="month in months.flat()"
:key="[month.year, month.month].join('-')"
:value="month"
>
{{ monthNames[month.month - 1] }}
</DateTimeRangePickerMonthCell>
</DateTimeRangePickerGrid>
</DateTimeRangePickerContent>
</DateTimeRangePickerRoot>
</template>업무 시간
일반 업무 시간 안에서 시작 시각과 종료 시각을 선택합니다.
일반 업무 시간 안에서 시작 시각과 종료 시각을 선택합니다.
<!-- Date Time Range Picker / Office Hours -->
<script setup lang="ts">
import { DateTimeRangePickerRoot, DateTimeRangePickerAnchor, DateTimeRangePickerStartDateTimeInput, DateTimeRangePickerEndDateTimeInput, DateTimeRangePickerTrigger, DateTimeRangePickerContent, DateTimeRangePickerPreviousWeek, DateTimeRangePickerPreviousMonth, DateTimeRangePickerPreviousYear, DateTimeRangePickerNextWeek, DateTimeRangePickerNextMonth, DateTimeRangePickerNextYear, DateTimeRangePickerWeekViewTrigger, DateTimeRangePickerMonthViewTrigger, DateTimeRangePickerYearViewTrigger, DateTimeRangePickerGrid, DateTimeRangePickerCell, DateTimeRangePickerMonthCell } from '@sectile/vue/date-time-range-picker'
import { CalendarDays } from '@lucide/vue'
const initialRange = {
start: {
date: { year: 2026, month: 8, day: 22 },
time: { hour: 9, minute: 30, second: 0, millisecond: 0 },
},
end: {
date: { year: 2026, month: 8, day: 25 },
time: { hour: 17, minute: 30, second: 0, millisecond: 0 },
},
}
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
</script>
<template>
<DateTimeRangePickerRoot :default-value="initialRange" v-slot="{ dates, months, view, viewMode }" class="catalog-stack catalog-temporal-picker">
<DateTimeRangePickerAnchor class="catalog-range-fields">
<label class="catalog-endpoint">
<span>Start</span>
<DateTimeRangePickerStartDateTimeInput class="catalog-input" aria-label="Start date and time" />
</label>
<label class="catalog-endpoint">
<span>End</span>
<DateTimeRangePickerEndDateTimeInput class="catalog-input" aria-label="End date and time" />
</label>
<DateTimeRangePickerTrigger class="catalog-picker-trigger" aria-label="Open date and time range picker">
<CalendarDays :size="18" aria-hidden="true" />
</DateTimeRangePickerTrigger>
</DateTimeRangePickerAnchor>
<DateTimeRangePickerContent class="catalog-popup catalog-picker-popup catalog-picker-popup--floating">
<div class="catalog-picker-toolbar">
<div class="catalog-inline">
<DateTimeRangePickerPreviousWeek v-if="viewMode === 'week'">‹</DateTimeRangePickerPreviousWeek>
<DateTimeRangePickerPreviousMonth v-else-if="viewMode === 'month'">‹</DateTimeRangePickerPreviousMonth>
<DateTimeRangePickerPreviousYear v-else>‹</DateTimeRangePickerPreviousYear>
<strong>{{ viewMode === 'year' ? view.year : monthNames[view.month - 1] + ' ' + view.year }}</strong>
<DateTimeRangePickerNextWeek v-if="viewMode === 'week'">›</DateTimeRangePickerNextWeek>
<DateTimeRangePickerNextMonth v-else-if="viewMode === 'month'">›</DateTimeRangePickerNextMonth>
<DateTimeRangePickerNextYear v-else>›</DateTimeRangePickerNextYear>
</div>
<div class="catalog-view-switch">
<DateTimeRangePickerWeekViewTrigger>Week</DateTimeRangePickerWeekViewTrigger>
<DateTimeRangePickerMonthViewTrigger>Month</DateTimeRangePickerMonthViewTrigger>
<DateTimeRangePickerYearViewTrigger>Year</DateTimeRangePickerYearViewTrigger>
</div>
</div>
<DateTimeRangePickerGrid v-if="viewMode !== 'year'" class="catalog-calendar" :data-view="viewMode">
<DateTimeRangePickerCell
v-for="day in dates.flat()"
:key="[day.year, day.month, day.day].join('-')"
:value="day"
>
{{ day.day }}
</DateTimeRangePickerCell>
</DateTimeRangePickerGrid>
<DateTimeRangePickerGrid v-else class="catalog-month-grid">
<DateTimeRangePickerMonthCell
v-for="month in months.flat()"
:key="[month.year, month.month].join('-')"
:value="month"
>
{{ monthNames[month.month - 1] }}
</DateTimeRangePickerMonthCell>
</DateTimeRangePickerGrid>
</DateTimeRangePickerContent>
</DateTimeRangePickerRoot>
</template>외부 상태 관리
현재 값은 부모가 관리하고, 허용된 변경을 컴포넌트에 다시 전달합니다.
현재 값은 부모가 관리하고, 허용된 변경을 컴포넌트에 다시 전달합니다.
<!-- Date Time Range Picker / Controlled -->
<script setup lang="ts">
import { ref } from 'vue'
import { DateTimeRangePickerRoot, DateTimeRangePickerAnchor, DateTimeRangePickerStartDateInput, DateTimeRangePickerStartTimeInput, DateTimeRangePickerEndDateInput, DateTimeRangePickerEndTimeInput, DateTimeRangePickerTrigger, DateTimeRangePickerContent, DateTimeRangePickerPreviousWeek, DateTimeRangePickerPreviousMonth, DateTimeRangePickerPreviousYear, DateTimeRangePickerNextWeek, DateTimeRangePickerNextMonth, DateTimeRangePickerNextYear, DateTimeRangePickerWeekViewTrigger, DateTimeRangePickerMonthViewTrigger, DateTimeRangePickerYearViewTrigger, DateTimeRangePickerGrid, DateTimeRangePickerCell, DateTimeRangePickerMonthCell } from '@sectile/vue/date-time-range-picker'
import { CalendarDays } from '@lucide/vue'
const initialRange = {
start: {
date: { year: 2026, month: 8, day: 22 },
time: { hour: 9, minute: 30, second: 0, millisecond: 0 },
},
end: {
date: { year: 2026, month: 8, day: 25 },
time: { hour: 17, minute: 30, second: 0, millisecond: 0 },
},
}
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
const value = ref(initialRange)
</script>
<template>
<DateTimeRangePickerRoot v-model="value" v-slot="{ dates, months, view, viewMode }" class="catalog-stack catalog-temporal-picker">
<DateTimeRangePickerAnchor class="catalog-range-fields">
<label class="catalog-endpoint">
<span>Start</span>
<span><DateTimeRangePickerStartDateInput class="catalog-input" aria-label="Start date" /><DateTimeRangePickerStartTimeInput class="catalog-input" aria-label="Start time" /></span>
</label>
<label class="catalog-endpoint">
<span>End</span>
<span><DateTimeRangePickerEndDateInput class="catalog-input" aria-label="End date" /><DateTimeRangePickerEndTimeInput class="catalog-input" aria-label="End time" /></span>
</label>
<DateTimeRangePickerTrigger class="catalog-picker-trigger" aria-label="Open date and time range picker">
<CalendarDays :size="18" aria-hidden="true" />
</DateTimeRangePickerTrigger>
</DateTimeRangePickerAnchor>
<DateTimeRangePickerContent class="catalog-popup catalog-picker-popup catalog-picker-popup--floating">
<div class="catalog-picker-toolbar">
<div class="catalog-inline">
<DateTimeRangePickerPreviousWeek v-if="viewMode === 'week'">‹</DateTimeRangePickerPreviousWeek>
<DateTimeRangePickerPreviousMonth v-else-if="viewMode === 'month'">‹</DateTimeRangePickerPreviousMonth>
<DateTimeRangePickerPreviousYear v-else>‹</DateTimeRangePickerPreviousYear>
<strong>{{ viewMode === 'year' ? view.year : monthNames[view.month - 1] + ' ' + view.year }}</strong>
<DateTimeRangePickerNextWeek v-if="viewMode === 'week'">›</DateTimeRangePickerNextWeek>
<DateTimeRangePickerNextMonth v-else-if="viewMode === 'month'">›</DateTimeRangePickerNextMonth>
<DateTimeRangePickerNextYear v-else>›</DateTimeRangePickerNextYear>
</div>
<div class="catalog-view-switch">
<DateTimeRangePickerWeekViewTrigger>Week</DateTimeRangePickerWeekViewTrigger>
<DateTimeRangePickerMonthViewTrigger>Month</DateTimeRangePickerMonthViewTrigger>
<DateTimeRangePickerYearViewTrigger>Year</DateTimeRangePickerYearViewTrigger>
</div>
</div>
<DateTimeRangePickerGrid v-if="viewMode !== 'year'" class="catalog-calendar" :data-view="viewMode">
<DateTimeRangePickerCell
v-for="day in dates.flat()"
:key="[day.year, day.month, day.day].join('-')"
:value="day"
>
{{ day.day }}
</DateTimeRangePickerCell>
</DateTimeRangePickerGrid>
<DateTimeRangePickerGrid v-else class="catalog-month-grid">
<DateTimeRangePickerMonthCell
v-for="month in months.flat()"
:key="[month.year, month.month].join('-')"
:value="month"
>
{{ monthNames[month.month - 1] }}
</DateTimeRangePickerMonthCell>
</DateTimeRangePickerGrid>
</DateTimeRangePickerContent>
</DateTimeRangePickerRoot>
</template>Floating 위치
이 컴포넌트는 공통 위치 엔진을 사용합니다. 실시간 위치 예시에서 side, align, 간격, 충돌 경계, strategy, tracking을 바꾸며 계산 결과를 확인할 수 있습니다.
API
Vue 패키지: @sectile/vue/temporal/date-time-range-picker
DateTimeRangePickerRootDateTimeRangePickerTriggerDateTimeRangePickerAnchorDateTimeRangePickerPortalDateTimeRangePickerContentDateTimeRangePickerGridDateTimeRangePickerCellDateTimeRangePickerMonthCellDateTimeRangePickerStartDateTimeInputDateTimeRangePickerEndDateTimeInputDateTimeRangePickerStartDateInputDateTimeRangePickerEndDateInputDateTimeRangePickerStartTimeInputDateTimeRangePickerEndTimeInputDateTimeRangePickerPreviousWeekDateTimeRangePickerNextWeekDateTimeRangePickerPreviousMonthDateTimeRangePickerNextMonthDateTimeRangePickerPreviousYearDateTimeRangePickerNextYearDateTimeRangePickerWeekViewTriggerDateTimeRangePickerMonthViewTriggerDateTimeRangePickerYearViewTrigger
Props
DateTimeRangePickerRootProps
align기준 요소를 중심으로 팝업 내용을 정렬할 위치입니다.
as이 파트가 렌더링할 요소 또는 컴포넌트입니다.
asChild하나뿐인 자식 요소에 파트 속성을 직접 합칠지 여부입니다.
avoidCollisions팝업이 화면 안에 남도록 위치를 뒤집거나 이동할지 여부입니다.
collisionBoundary팝업을 화면 안에 유지할 때 사용할 경계입니다.
collisionPadding팝업과 충돌 경계 사이에 둘 간격입니다.
defaultHighlightedValue컴포넌트가 관리하는 처음 강조 값입니다.
defaultOpen컴포넌트가 관리하는 초기 열림 상태입니다.
defaultValue컴포넌트가 값을 관리할 때 사용할 초깃값입니다.
defaultView달력 또는 선택기의 초기 보기입니다.
disabled사용자 조작을 막을지 여부입니다.
hideWhenDetached기준 요소가 레이아웃에서 벗어나면 팝업을 숨길지 여부입니다.
highlightedValue키보드 조작 대상으로 강조된 현재 값입니다.
label보조 기술이 읽는 컨트롤 이름입니다.
modelValue부모가 상태를 관리할 때 사용할 현재 값입니다.
open연결된 팝업이나 펼침 영역이 열려 있는지 여부입니다.
policies검증, 이동, 선택 동작을 조정하는 정책입니다.
position실행 요소를 기준으로 팝업 위치를 계산할지 여부입니다.
readonly값 확인만 허용하는 읽기 전용 상태 여부입니다.
referenceDate달력의 선택값과 강조값을 초기화할 때 사용하는 민간 기준 날짜입니다.
required제출 전에 올바른 값이 반드시 있어야 하는지 여부입니다.
side기준 요소를 중심으로 팝업을 우선 배치할 방향입니다.
sideOffset팝업과 기준 요소 사이 거리입니다.
strategy기준 요소에 연결된 콘텐츠의 CSS 위치 전략입니다.
tracking기준 요소에 연결된 콘텐츠가 열린 동안 위치를 갱신할 방식입니다.
DateTimeRangePickerPartProps
as이 파트가 렌더링할 요소 또는 컴포넌트입니다.
asChild하나뿐인 자식 요소에 파트 속성을 직접 합칠지 여부입니다.
DateTimeRangePickerPortalProps
deferTeleport 대상을 현재 mount 또는 update tick이 끝날 때 찾을지 여부입니다.
disabled사용자 조작을 막을지 여부입니다.
to포털 콘텐츠를 옮길 대상입니다.
슬롯
DateTimeRangePickerRootSlotProps
dates현재 보기에 표시할 날짜입니다.
disabled사용자 조작을 막을지 여부입니다.
highlightedValue조작 대상으로 강조된 현재 값입니다.
months현재 보기에 표시할 달입니다.
open연결된 팝업이나 펼침 영역이 열려 있는지 여부입니다.
readonly값 확인만 허용하는 읽기 전용 상태 여부입니다.
value이 계약이 노출하는 현재 값입니다.
view현재 달력 기준점입니다.
viewMode현재 달력 보기 방식입니다.
years현재 보기에 표시할 연도입니다.
DateTimeRangePickerCellSlotProps
disabled사용자 조작을 막을지 여부입니다.
highlighted조작 대상으로 강조된 항목인지 여부입니다.
inRange선택한 범위 안에 있는 값인지 여부입니다.
outsideMonth인접한 달의 날짜인지 여부입니다.
selected현재 선택된 항목인지 여부입니다.
value이 계약이 노출하는 현재 값입니다.
DateTimeRangePickerMonthCellSlotProps
disabled사용자 조작을 막을지 여부입니다.
highlighted조작 대상으로 강조된 항목인지 여부입니다.
inRange선택한 범위 안에 있는 값인지 여부입니다.
selected현재 선택된 항목인지 여부입니다.
value이 계약이 노출하는 현재 값입니다.
기타 타입
DateTimeRangePickerValueChangeHandler
type DateTimeRangePickerValueChangeHandler = NonNullable<InstanceType<typeof DateTimeRangePickerRoot>['$props']['onUpdate:modelValue']>DateTimeRangePickerOpenChangeHandler
type DateTimeRangePickerOpenChangeHandler = NonNullable<InstanceType<typeof DateTimeRangePickerRoot>['$props']['onUpdate:open']>DateTimeRangePickerHighlightedValueChangeHandler
type DateTimeRangePickerHighlightedValueChangeHandler = NonNullable<InstanceType<typeof DateTimeRangePickerRoot>['$props']['onUpdate:highlightedValue']>DateTimeRange
| 이름 | 타입 | 필수 |
|---|---|---|
start | DateTimeValue | 필수 |
end | DateTimeValue | 필수 |
DateValue
| 이름 | 타입 | 필수 |
|---|---|---|
year | number | 필수 |
month | number | 필수 |
day | number | 필수 |
파트
공통 범위: [data-scope="date-time-range-picker"]. 컴포넌트 내부로 스타일을 제한할 때 파트 선택자와 함께 사용합니다.
| 파트 | 선택자 | 역할 | 추가 속성 |
|---|---|---|---|
start-date-time-input | [data-part="start-date-time-input"] | Start Date Time Input 스타일 영역을 노출합니다. | — |
end-date-time-input | [data-part="end-date-time-input"] | End Date Time Input 스타일 영역을 노출합니다. | — |
start-date-input | [data-part="start-date-input"] | Start Date Input 스타일 영역을 노출합니다. | — |
end-date-input | [data-part="end-date-input"] | End Date Input 스타일 영역을 노출합니다. | — |
start-time-input | [data-part="start-time-input"] | Start Time Input 스타일 영역을 노출합니다. | — |
end-time-input | [data-part="end-time-input"] | End Time Input 스타일 영역을 노출합니다. | — |
anchor | [data-part="anchor"] | 떠 있는 콘텐츠의 배치 기준을 제공합니다. | — |
trigger | [data-part="trigger"] | 연결된 콘텐츠를 열고 닫거나 활성화합니다. | — |
content | [data-part="content"] | 현재 상태에 맞는 컴포넌트 콘텐츠를 담습니다. | — |
week-view-trigger | [data-part="week-view-trigger"] | 달력을 주 보기로 전환합니다. | — |
month-view-trigger | [data-part="month-view-trigger"] | 달력을 월 보기로 전환합니다. | — |
year-view-trigger | [data-part="year-view-trigger"] | 달력을 년 보기로 전환합니다. | — |
previous-week | [data-part="previous-week"] | 이전 주(으)로 이동합니다. | — |
next-week | [data-part="next-week"] | 다음 주(으)로 이동합니다. | — |
previous-month | [data-part="previous-month"] | 이전 월(으)로 이동합니다. | — |
next-month | [data-part="next-month"] | 다음 월(으)로 이동합니다. | — |
previous-year | [data-part="previous-year"] | 이전 년(으)로 이동합니다. | — |
next-year | [data-part="next-year"] | 다음 년(으)로 이동합니다. | — |
grid | [data-part="grid"] | 셀을 탐색 가능한 2차원 구조로 묶습니다. | — |
cell | [data-part="cell"] | 탐색하거나 선택할 수 있는 그리드 값 하나입니다. | — |
month-cell | [data-part="month-cell"] | 선택할 수 있는 월 하나입니다. | — |
키보드 동작
| 키 | 동작 |
|---|---|
| Arrow keys | 강조된 날짜를 하루 또는 일주일 단위로 이동합니다. |
| Home / End | 한 주의 시작 또는 끝으로 이동합니다. |
| Page Up / Page Down | 한 달 단위로 이동하고, Shift와 함께 누르면 일 년 단위로 이동합니다. |
| Enter / Space | 강조된 날짜를 선택합니다. |
| Escape | 현재 날짜를 유지한 채 달력을 닫습니다. |
접근성
두 개의 날짜·시간 필드와 달력 격자가 시작·종료 지점을 명확히 구분합니다.
