Calendar
Navigate a date grid, skip unavailable days, and select a civil date.
Usage
Month
Navigate and select dates in a complete month grid.
Navigate and select dates in a complete month grid.
<!-- Calendar / Month -->
<script setup lang="ts">
import { ref } from 'vue'
import {
CalendarCell, CalendarContent, CalendarGrid,
CalendarNextMonth, CalendarPreviousMonth, CalendarRoot,
type DateValue,
} from '@sectile/vue/temporal/calendar'
const selected = ref<DateValue | null>(null)
const initial = { year: 2026, month: 8, day: 24 }
</script>
<template>
<CalendarRoot v-model="selected" :default-highlighted-value="initial" default-view="month" v-slot="{ dates, view }" label="Release calendar">
<CalendarContent>
<header>
<CalendarPreviousMonth>Previous</CalendarPreviousMonth>
<strong>{{ view.year }}-{{ view.month }}</strong>
<CalendarNextMonth>Next</CalendarNextMonth>
</header>
<CalendarGrid>
<CalendarCell v-for="day in dates.flat()" :key="`${day.year}-${day.month}-${day.day}`" :value="day">
{{ day.day }}
</CalendarCell>
</CalendarGrid>
</CalendarContent>
</CalendarRoot>
</template>Week
Switch to a focused seven-day view while keeping selection and paging available.
Switch to a focused seven-day view while keeping selection and paging available.
<!-- Calendar / Week -->
<script setup lang="ts">
import { ref } from 'vue'
import {
CalendarCell, CalendarContent, CalendarGrid,
CalendarNextWeek, CalendarPreviousWeek, CalendarRoot,
type DateValue,
} from '@sectile/vue/temporal/calendar'
const selected = ref<DateValue | null>(null)
const initial = { year: 2026, month: 8, day: 24 }
</script>
<template>
<CalendarRoot v-model="selected" :default-highlighted-value="initial" default-view="week" v-slot="{ dates, view }" label="Release calendar">
<CalendarContent>
<header>
<CalendarPreviousWeek>Previous</CalendarPreviousWeek>
<strong>{{ view.year }}-{{ view.month }}</strong>
<CalendarNextWeek>Next</CalendarNextWeek>
</header>
<CalendarGrid>
<CalendarCell v-for="day in dates.flat()" :key="`${day.year}-${day.month}-${day.day}`" :value="day">
{{ day.day }}
</CalendarCell>
</CalendarGrid>
</CalendarContent>
</CalendarRoot>
</template>Disabled weekends
Keep weekend dates visible while preventing them from becoming the selected date.
Keep weekend dates visible while preventing them from becoming the selected date.
<!-- Calendar / Disabled Weekends -->
<script setup lang="ts">
import { ref } from 'vue'
import {
CalendarCell, CalendarContent, CalendarGrid,
CalendarNextMonth, CalendarPreviousMonth, CalendarRoot,
type DateValue,
} from '@sectile/vue/temporal/calendar'
const selected = ref<DateValue | null>(null)
const initial = { year: 2026, month: 8, day: 24 }
const policies = { unavailable: (value: DateValue) => {
const day = new Date(Date.UTC(value.year, value.month - 1, value.day)).getUTCDay()
return day === 0 || day === 6
} }
</script>
<template>
<CalendarRoot v-model="selected" :default-highlighted-value="initial" default-view="month" :policies="policies" v-slot="{ dates, view }" label="Release calendar">
<CalendarContent>
<header>
<CalendarPreviousMonth>Previous</CalendarPreviousMonth>
<strong>{{ view.year }}-{{ view.month }}</strong>
<CalendarNextMonth>Next</CalendarNextMonth>
</header>
<CalendarGrid>
<CalendarCell v-for="day in dates.flat()" :key="`${day.year}-${day.month}-${day.day}`" :value="day">
{{ day.day }}
</CalendarCell>
</CalendarGrid>
</CalendarContent>
</CalendarRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Calendar / Controlled -->
<script setup lang="ts">
import { ref } from 'vue'
import {
CalendarCell, CalendarContent, CalendarGrid,
CalendarNextMonth, CalendarPreviousMonth, CalendarRoot,
type DateValue,
} from '@sectile/vue/temporal/calendar'
const selected = ref<DateValue | null>(null)
const initial = { year: 2026, month: 8, day: 24 }
</script>
<template>
<CalendarRoot v-model="selected" :default-highlighted-value="initial" default-view="month" v-slot="{ dates, view }" label="Release calendar">
<CalendarContent>
<header>
<CalendarPreviousMonth>Previous</CalendarPreviousMonth>
<strong>{{ view.year }}-{{ view.month }}</strong>
<CalendarNextMonth>Next</CalendarNextMonth>
</header>
<CalendarGrid>
<CalendarCell v-for="day in dates.flat()" :key="`${day.year}-${day.month}-${day.day}`" :value="day">
{{ day.day }}
</CalendarCell>
</CalendarGrid>
</CalendarContent>
</CalendarRoot>
</template>API
Vue package: @sectile/vue/temporal/calendar
CalendarRootCalendarContentCalendarGridCalendarCellCalendarMonthCellCalendarInputCalendarPreviousWeekCalendarNextWeekCalendarPreviousMonthCalendarNextMonthCalendarPreviousYearCalendarNextYearCalendarWeekViewTriggerCalendarMonthViewTriggerCalendarYearViewTrigger
Props
CalendarRootProps
defaultHighlightedValueInitially highlighted value for uncontrolled state.
defaultValueInitial value used when the component owns its state.
defaultViewInitial calendar or picker view.
disabledWhether interaction is unavailable.
highlightedValueValue currently highlighted for keyboard interaction.
labelAccessible name announced for the control.
modelValueCurrent value when state is controlled by the parent.
policiesBehavior policies that customize validation, movement, or selection.
readonlyWhether the value can be inspected but not changed.
referenceDateDeterministic civil date used when a calendar has no selected or highlighted value.
requiredWhether the control must contain a valid value before submission.
CalendarCellProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
valueCurrent value exposed by this contract.
CalendarMonthCellProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
valueCurrent value exposed by this contract.
CalendarPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
Slots
CalendarRootSlotProps
datesDates projected by the active view.
disabledWhether interaction is unavailable.
highlightedValueValue currently highlighted for interaction.
monthsMonths projected by the active view.
readonlyWhether the value can be inspected but not changed.
valueCurrent value exposed by this contract.
viewCurrent calendar anchor.
viewModeActive calendar view mode.
CalendarCellSlotProps
disabledWhether interaction is unavailable.
highlightedWhether this item is highlighted for interaction.
inRangeWhether this value lies inside the selected range.
outsideMonthWhether this date belongs to an adjacent month.
selectedWhether this item is selected.
valueCurrent value exposed by this contract.
CalendarMonthCellSlotProps
disabledWhether interaction is unavailable.
highlightedWhether this item is highlighted for interaction.
inRangeWhether this value lies inside the selected range.
selectedWhether this item is selected.
valueCurrent value exposed by this contract.
Events
CalendarRoot
update:highlightedValueEmitted when the requested highlighted value changes.
update:modelValueEmitted when the component requests a new controlled value.
Other types
CalendarValueChangeHandler
type CalendarValueChangeHandler = NonNullable<InstanceType<typeof CalendarRoot>['$props']['onUpdate:modelValue']>CalendarHighlightedValueChangeHandler
type CalendarHighlightedValueChangeHandler = NonNullable<InstanceType<typeof CalendarRoot>['$props']['onUpdate:highlightedValue']>CalendarMonthValue
| Name | Type | Required |
|---|---|---|
year | number | Yes |
month | number | Yes |
CalendarPolicies
| Name | Type | Required |
|---|---|---|
min | DateValue | — |
max | DateValue | — |
required | boolean | — |
unavailable | (value: DateValue) => boolean | — |
weekStartsOn | 1 | 2 | 3 | 4 | 5 | 6 | 7 | — |
maxScan | number | — |
CalendarViewMode
type CalendarViewMode = 'week' | 'month' | 'year'DateValue
| Name | Type | Required |
|---|---|---|
year | number | Yes |
month | number | Yes |
day | number | Yes |
Parts
Shared scope: [data-scope="calendar"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
content | [data-part="content"] | Contains the component content shown for the active state. | — |
input | [data-part="input"] | Keeps the selected date available for native form submission. | — |
week-view-trigger | [data-part="week-view-trigger"] | Switches the calendar to the week view. | — |
month-view-trigger | [data-part="month-view-trigger"] | Switches the calendar to the month view. | — |
year-view-trigger | [data-part="year-view-trigger"] | Switches the calendar to the year view. | — |
previous-week | [data-part="previous-week"] | Moves to the previous week. | — |
next-week | [data-part="next-week"] | Moves to the next week. | — |
previous-month | [data-part="previous-month"] | Moves to the previous month. | — |
next-month | [data-part="next-month"] | Moves to the next month. | — |
previous-year | [data-part="previous-year"] | Moves to the previous year. | — |
next-year | [data-part="next-year"] | Moves to the next year. | — |
grid | [data-part="grid"] | Groups cells into a navigable two-dimensional structure. | — |
cell | [data-part="cell"] | Represents one navigable or selectable grid value. | — |
month-cell | [data-part="month-cell"] | Represents one selectable month. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Arrow Left / Arrow Right | Move by one day. |
| Arrow Up / Arrow Down | Move by one week. |
| Home / End | Move to the start or end of the week. |
| Page Up / Page Down | Move by one month; hold Shift to move by one year. |
| Enter / Space | Select the highlighted date. |
Accessibility
The inline content owns a labeled grid whose cells expose selected, highlighted, unavailable, and outside-month state.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
