DatePickerField
A form field to pick dates, either as an input that opens a calendar popup or as an inline calendar, with label, help text and validation.
Component
Help text example
Props
| Props | Required | Default | Type |
|---|---|---|---|
id | true | — | string |
label | — | — | string |
ariaLabel | — | — | string |
helpText | — | — | string |
helpTextPosition | — | Position.BOTTOM | Position |
type | — | DatePickerType.DATE | DatePickerType |
variant | — | PickerVariant.INPUT | PickerVariant |
modelValue | — | null | string | string[] | CalendarRange | null |
mode | — | CalendarMode.SINGLE | CalendarMode |
placeholder | — | — | string |
icon | — | — | string |
size | — | InputSize.MD | InputSize |
displayFormat | — | — | Intl.DateTimeFormatOptions |
closeOnSelect | — | true | boolean |
clearable | — | true | boolean |
calendarPosition | — | Position.BOTTOM | Position |
autoFlip | — | true | boolean |
min | — | — | string |
max | — | — | string |
isDateDisabled | — | () => false | (date: string) => boolean |
locale | — | 'en-US' | string |
firstDayOfWeek | — | 0 | number |
color | — | ColorAccent.PRIMARY_BRAND | ColorAccent |
hasYearControls | — | false | boolean |
hasOutsideDays | — | true | boolean |
hasWeekNumbers | — | false | boolean |
isRounded | — | false | boolean |
isNavigationLocked | — | false | boolean |
isBoxed | — | true | boolean |
markers | — | {} | Record<string, CalendarMarker[]> |
maxMarkers | — | 3 | number |
dayPopoverTrigger | — | Trigger.MANUAL | Trigger |
hasDayPopover | — | — | (date: string) => boolean |
dayPopoverPosition | — | Position.BOTTOM | Position |
dayPopoverAlign | — | — | Align |
dayPopoverAutoFlip | — | true | boolean |
hourFormat | — | — | HourFormat |
hasSeconds | — | false | boolean |
minuteStep | — | 1 | number |
secondStep | — | 1 | number |
validator | — | () => null | (value: unknown) => string | null |
error | — | '' | string |
disabled | — | false | boolean |
readonly | — | false | boolean |
required | — | false | boolean |
showOptionalLabel | — | true | boolean |
optionalLabel | — | — | string |
transparent | — | false | boolean |
clearAriaLabel | — | — | string |
openAriaLabel | — | — | string |
doneText | — | — | string |
clearText | — | — | string |
glowColorMode | — | GlowColorMode.NONE | GlowColorMode |
glowTrigger | — | GlowTrigger.FOCUS | GlowTrigger |
glowType | — | GlowType.INNER | GlowType |
glowOpacity | — | 40 | number |
glowSize | — | — | number |
Slots
| Name | Description |
|---|---|
day-popover | Content of the panel of a day in the calendar, shown according to `dayPopoverTrigger`. Receives `date` (the ISO date), `markers` (the markers of the day) and `close` (a function that closes the panel). |
Usage
id
Sets the id of the input (and the for of the label). Required.
<template>
<DatePickerField id="birth-date" />
</template>
label
Sets the label shown above the field. In the INLINE variant it also names the calendar.
<template>
<DatePickerField id="date" label="Birth date" />
</template>
ariaLabel
Sets the accessible name when there is no visible label.
<template>
<DatePickerField id="date" ariaLabel="Birth date" />
</template>
helpText
Sets the help text. When there is an error, the error is shown instead.
<template>
<DatePickerField id="date" helpText="Pick your birth date" />
</template>
helpTextPosition
Sets where the help text is shown, via the Position enum.
<template>
<DatePickerField id="date" :helpTextPosition="Position.TOP" helpText="Hint" />
</template>
Options
| Value | Description |
|---|---|
TOP | top |
BOTTOM | bottom |
type
Sets what the field picks, via the DatePickerType enum. The values are the ones of the native input types they replace, so a v-model keeps the same format.
<template>
<DatePickerField id="week" :type="DatePickerType.WEEK" label="Week" />
</template>
Options
| Value | Description |
|---|---|
DATE | date: an ISO date, such as `2026-10-15` |
MONTH | month: a month, such as `2026-10` |
WEEK | week: an ISO week, such as `2026-W41` |
DATETIME_LOCAL | datetime-local: a date and a time, such as `2026-10-15T19:30` |
variant
Sets how the calendar is shown via the PickerVariant enum. INPUT shows a field that opens the calendar in a popup, and INLINE shows the calendar itself in place of the field. The label, help text and error are shown in both.
<template>
<DatePickerField id="date" :variant="PickerVariant.INLINE" label="Date" />
</template>
Options
| Value | Description |
|---|---|
INPUT | input |
INLINE | inline |
modelValue
Sets the selected value. In SINGLE mode it is a string, in MULTIPLE mode an array of strings and in RANGE mode a CalendarRange. The format of each string depends on the type: a date (2026-10-15), a month (2026-10), an ISO week (2026-W41) or a date and time (2026-10-15T19:30). Bind it with v-model.
<template>
<DatePickerField v-model="date" id="date" />
</template>
TypeScript Interface
export interface CalendarRange {
start: string | null
end: string | null
}
mode
Sets how many selections can be made, via the CalendarMode enum. See the Calendar for how each mode behaves. It combines with the type: a range of months, several weeks... The DATETIME_LOCAL type always takes one.
<template>
<DatePickerField v-model="range" id="range" :mode="CalendarMode.RANGE" />
</template>
Options
| Value | Description |
|---|---|
SINGLE | single |
MULTIPLE | multiple |
RANGE | range |
placeholder
Sets the placeholder of the input. Falls back to a text for the type in useDSConfig().calendar. Only applies to the INPUT variant.
<template>
<DatePickerField id="date" placeholder="Choose a day" />
</template>
icon
Sets an icon shown at the start of the input. Only applies to the INPUT variant.
<template>
<DatePickerField id="date" icon="mdi:cake-variant-outline" />
</template>
size
Sets the height of the input via the InputSize enum. Only applies to the INPUT variant.
<template>
<DatePickerField id="date" :size="InputSize.LG" />
</template>
Options
| Value | Description |
|---|---|
MD | md |
LG | lg |
displayFormat
Sets how dates are written in the input, using Intl.DateTimeFormat options. Defaults to a numeric day/month/year order that follows the locale, and to the month name and year for the MONTH type. It does not apply to the WEEK type or to the time of DATETIME_LOCAL.
<template>
<DatePickerField id="date" :displayFormat="{ dateStyle: 'long' }" />
</template>
closeOnSelect
Closes the popup once the selection is complete: after one date, month or week, and after the end date of a range. MULTIPLE mode and the DATETIME_LOCAL type never close on their own, since they take more than one pick: close them with Escape or by clicking outside.
<template>
<DatePickerField id="date" :closeOnSelect="false" />
</template>
clearable
Shows a button to clear the value while there is one.
<template>
<DatePickerField id="date" :clearable="false" />
</template>
calendarPosition
Sets whether the popup opens below or above the input, via the Position enum.
<template>
<DatePickerField id="date" :calendarPosition="Position.TOP" />
</template>
Options
| Value | Description |
|---|---|
TOP | top |
BOTTOM | bottom |
autoFlip
Moves the calendar to the other side when it does not fit in the window. If it would be cut off at the bottom or the top edge of the screen and there is more room on the other side, it opens there instead. The position is checked when it opens, and calendarPosition is only the starting point. Set it to false to always keep the position as given.
<template>
<DatePickerField v-model="date" id="date" :autoFlip="false" />
</template>
min
Sets the earliest selectable value, in the format of the type: a date, a month (2026-10), a week (2026-W41) or a date and time (2026-10-15T09:00). In date and time, the time limit only applies on the day of the date limit.
<template>
<DatePickerField id="date" min="2026-10-10" />
</template>
max
Sets the latest selectable value, in the same formats as min.
<template>
<DatePickerField id="date" max="2026-10-20" />
</template>
isDateDisabled
Receives each day as an ISO string and returns true to disable it.
<template>
<DatePickerField id="date" :isDateDisabled="isWeekend" />
</template>
locale
Sets the BCP 47 locale used for the text in the input and the calendar.
<template>
<DatePickerField id="date" locale="es-ES" :firstDayOfWeek="1" />
</template>
firstDayOfWeek
Sets the first column of the calendar, from 0 (Sunday) to 6 (Saturday). The WEEK type always starts on Monday.
<template>
<DatePickerField id="date" :firstDayOfWeek="1" />
</template>
color
Sets the accent color of the calendar. Supports PRIMARY_BRAND and SECONDARY_BRAND.
<template>
<DatePickerField id="date" :color="ColorAccent.SECONDARY_BRAND" />
</template>
Options
| Value | Description |
|---|---|
PRIMARY_BRAND | primary-brand |
SECONDARY_BRAND | secondary-brand |
hasYearControls
Shows buttons to jump a year in the calendar header.
<template>
<DatePickerField id="date" :hasYearControls="true" />
</template>
hasOutsideDays
Shows the days of the adjacent months in the calendar.
<template>
<DatePickerField id="date" :hasOutsideDays="false" />
</template>
hasWeekNumbers
Shows the ISO week number of each row in the calendar. The WEEK type always shows them.
<template>
<DatePickerField id="date" :hasWeekNumbers="true" :firstDayOfWeek="1" />
</template>
isRounded
Makes the calendar cells fully round.
<template>
<DatePickerField id="date" :isRounded="true" />
</template>
isNavigationLocked
Locks the calendar to the visible month. See the Calendar.
<template>
<DatePickerField id="date" :isNavigationLocked="true" />
</template>
isBoxed
Adds the border and background to the calendar. Only applies to the INLINE variant, since the popup is always boxed.
<template>
<DatePickerField id="date" :variant="PickerVariant.INLINE" :isBoxed="false" />
</template>
markers
Shows dots under the days of the calendar, such as events or tasks. It is passed to the Calendar. It maps ISO dates to a list of markers. A marker can have a color, from the ColorAccent enum (PRIMARY_BRAND by default), and a label, which is added to the aria-label of the day so screen readers get it too. The dots follow the design system colors, and on a selected day they use the color of the text on filled backgrounds so they stay visible.
<template>
<DatePickerField v-model="date" id="date" :markers="events" />
</template>
<script setup lang="ts">
const events = {
'2026-10-15': [{ color: ColorAccent.DANGER, label: 'Deploy' }],
'2026-10-20': [{ label: 'Review' }, { color: ColorAccent.SUCCESS, label: 'Release' }],
}
</script>
TypeScript Interface
export interface CalendarMarker {
color?: ColorAccent
label?: string
}
maxMarkers
Sets how many dots are drawn under a day. The labels of all its markers are still part of the aria-label.
<template>
<DatePickerField v-model="date" id="date" :markers="events" :maxMarkers="2" />
</template>
dayPopoverTrigger
Sets when the panel of a day opens, via the Trigger enum. See the Calendar for the details. The CLICK trigger selects the day too, which closes the popup unless closeOnSelect is off or the selection takes more picks, so HOVER is usually the better fit for a date field. The content of the panel is the day-popover slot, which receives the date, its markers and a close function. By default the panel opens only for days with markers, and hasDayPopover changes that. It also closes with Escape, with a click outside, and when the visible month changes. Without the slot, or with MANUAL, no panel is shown.
<template>
<DatePickerField v-model="date" id="date" :markers="events" :dayPopoverTrigger="Trigger.HOVER">
<template #day-popover="{ date, markers, close }">
<p v-for="marker in markers" :key="marker.label">{{ marker.label }}</p>
</template>
</DatePickerField id="date">
</template>
Options
| Value | Description |
|---|---|
CLICK | click: a click opens the panel (and a second click closes it). The click still selects the day. |
HOVER | hover: the panel opens while the pointer or the keyboard focus is on the day, and stays open while the pointer is over it. |
MANUAL | manual: the panel never opens. This is the default. |
The panel opens below the day, towards the inside of the calendar for the first and last columns. It is not repositioned near the edge of the screen and can be clipped by a parent with overflow: hidden.
hasDayPopover
Receives each day as an ISO string and returns true when it has a panel. It replaces the default rule of opening only for days with markers, so you can show a panel on any day, such as an empty state with an add button.
<template>
<DatePickerField v-model="date" id="date" :dayPopoverTrigger="Trigger.CLICK" :hasDayPopover="isWorkday">
<template #day-popover="{ date }">
<ActionButton text="Add task" @click="addTask(date)" />
</template>
</DatePickerField id="date">
</template>
dayPopoverPosition
Sets whether the panel of a day opens below or above it, via the Position enum. See the Calendar for the details. It is not the position of the calendar popup, which is calendarPosition. With dayPopoverAutoFlip, it goes to the other side when it does not fit.
<template>
<DatePickerField v-model="date" id="date" :markers="events" :dayPopoverTrigger="Trigger.HOVER" :dayPopoverPosition="Position.TOP">
<template #day-popover="{ date }">{{ date }}</template>
</DatePickerField v-model="date" id="date">
</template>
Options
| Value | Description |
|---|---|
BOTTOM | bottom |
TOP | top |
dayPopoverAlign
Sets how the panel is aligned with its day, via the Align enum. Without it, the panel is centered under the day, and the first two and last two columns align it inwards (LEFT and RIGHT) so it stays inside the calendar.
<template>
<DatePickerField v-model="date" id="date" :markers="events" :dayPopoverTrigger="Trigger.HOVER" :dayPopoverAlign="Align.LEFT">
<template #day-popover="{ date }">{{ date }}</template>
</DatePickerField v-model="date" id="date">
</template>
Options
| Value | Description |
|---|---|
LEFT | left: the left edge of the panel is aligned with the left edge of the day |
CENTER | center: the panel is centered on the day |
RIGHT | right: the right edge of the panel is aligned with the right edge of the day |
dayPopoverAutoFlip
Moves the panel when it does not fit in the window. It goes to the other side, above or below, when it would be cut off and there is more room there, and it aligns to the right or the left when it would overflow horizontally. The position is checked when the panel opens, and a position or align that you set is only the starting point. Set it to false to always keep the placement as given.
<template>
<DatePickerField v-model="date" id="date" :markers="events" :dayPopoverTrigger="Trigger.HOVER" :dayPopoverAutoFlip="false">
<template #day-popover="{ date }">{{ date }}</template>
</DatePickerField v-model="date" id="date">
</template>
hourFormat
Sets the 12 or 24 hour clock of the time picker via the HourFormat enum. Defaults to the one of the locale. Only applies to the DATETIME_LOCAL type.
<template>
<DatePickerField id="date" :type="DatePickerType.DATETIME_LOCAL" :hourFormat="HourFormat.HOURS_12" />
</template>
Options
| Value | Description |
|---|---|
HOURS_12 | 12 |
HOURS_24 | 24 |
hasSeconds
Adds a seconds column to the time picker and to the value (YYYY-MM-DDTHH:mm:ss). Only applies to the DATETIME_LOCAL type.
<template>
<DatePickerField id="date" :type="DatePickerType.DATETIME_LOCAL" :hasSeconds="true" />
</template>
minuteStep
Sets the interval between the minutes of the time picker. Only applies to the DATETIME_LOCAL type.
<template>
<DatePickerField id="date" :type="DatePickerType.DATETIME_LOCAL" :minuteStep="15" />
</template>
secondStep
Sets the interval between the seconds of the time picker. Only applies to the DATETIME_LOCAL type.
<template>
<DatePickerField id="date" :type="DatePickerType.DATETIME_LOCAL" :hasSeconds="true" :secondStep="15" />
</template>
validator
Validates the value and returns an error message, or null. It runs only when the field is required, whenever the value changes and when the popup closes.
<template>
<DatePickerField id="date" required :validator="validateField" />
</template>
error
Sets the error message. The field and the help text switch to the error style.
<template>
<DatePickerField id="date" error="Required field" />
</template>
disabled
Disables the field and the calendar.
<template>
<DatePickerField id="date" :disabled="true" />
</template>
readonly
Shows the value without letting the user change it. The popup does not open, and an inline calendar can be browsed but not selected.
<template>
<DatePickerField id="date" :readonly="true" />
</template>
required
Marks the field as required: hides the optional label and enables the validator.
<template>
<DatePickerField id="date" label="Date" :required="true" />
</template>
showOptionalLabel
Shows the optional text next to the label when the field is not required.
<template>
<DatePickerField id="date" label="Date" :showOptionalLabel="false" />
</template>
optionalLabel
Sets the optional text. Falls back to useDSConfig().forms.optionalLabelText().
<template>
<DatePickerField id="date" label="Fecha" optionalLabel="(opcional)" />
</template>
transparent
Removes the background of the input.
<template>
<DatePickerField id="date" :transparent="true" />
</template>
clearAriaLabel
Sets the aria-label of the clear button. Falls back to useDSConfig().forms.clearSelectionText().
<template>
<DatePickerField id="date" clearAriaLabel="Borrar fecha" />
</template>
openAriaLabel
Sets the aria-label of the calendar button. Falls back to useDSConfig().calendar.openText().
<template>
<DatePickerField id="date" openAriaLabel="Abrir calendario" />
</template>
doneText
Sets the text of the button that closes the calendar in CalendarMode.MULTIPLE and in the date and time type, where no pick completes the selection. Falls back to useDSConfig().calendar.doneText().
<template>
<DatePickerField id="date" :mode="CalendarMode.MULTIPLE" doneText="Listo" />
</template>
clearText
Sets the text of the button that clears the selected value in CalendarMode.MULTIPLE and in the date and time type. It sits next to the done button and keeps the calendar open. Falls back to useDSConfig().calendar.clearText().
<template>
<DatePickerField id="date" :mode="CalendarMode.MULTIPLE" clearText="Limpiar" />
</template>
glowColorMode
Draws a glow around the date input box only. The label and the help text do not glow. It is shown in light mode, dark mode, both or none, and it uses the GlowColorMode enum. It is GlowColorMode.NONE by default, so the field has no glow until you turn it on.
The glow uses the brand color and turns to the error color when the field has an error.
<template>
<DatePickerField :glowColorMode="GlowColorMode.DARK" />
</template>
Options
| Value | Description |
|---|---|
NONE | No glow. |
BOTH | Glow in light and dark mode. |
LIGHT | Glow in light mode only. |
DARK | Glow in dark mode only. |
glowTrigger
Sets when the glow appears. It uses the GlowTrigger enum and works together with glowColorMode, which decides in which theme the glow shows. It is GlowTrigger.FOCUS by default.
FOCUS shows the glow while the field has focus. On touch screens there is no hover, so with HOVER the glow never shows.
<template>
<DatePickerField :glowColorMode="GlowColorMode.BOTH" :glowTrigger="GlowTrigger.FOCUS" />
</template>
Options
| Value | Description |
|---|---|
ALWAYS | The glow is always visible. |
HOVER | The glow shows while the pointer is over the field. |
FOCUS | The glow shows while the field has focus. |
HOVER_FOCUS | The glow shows on hover and on focus. |
glowType
Sets where the glow is drawn. It uses the GlowType enum and works together with glowColorMode. It is GlowType.INNER by default.
<template>
<DatePickerField :glowColorMode="GlowColorMode.BOTH" :glowType="GlowType.INNER" />
</template>
Options
| Value | Description |
|---|---|
OUTER | The glow spreads around the outside of the element. |
INNER | The glow is drawn inside the element, along its edges. |
glowOpacity
Sets how strong the glow is, from 0 (invisible) to 100 (full color). The default is 40. Values move in steps of 5, so 42 is rounded to 40. It has no effect while glowColorMode is GlowColorMode.NONE.
<template>
<DatePickerField :glowColorMode="GlowColorMode.BOTH" :glowOpacity="30" />
</template>
glowSize
Sets how far the glow spreads, in pixels. It is null by default, so each component keeps its own size (for example, buttons follow their size). Values move in steps of 2 from 0 to 64, so 13 is rounded to 14. It has no effect while glowColorMode is GlowColorMode.NONE.
<template>
<DatePickerField :glowColorMode="GlowColorMode.BOTH" :glowSize="32" />
</template>
Accessibility
For every type, in the INPUT variant the field is a read-only text input with aria-haspopup="dialog" and aria-expanded. Focus moves into the calendar when it opens and returns to the input when it closes.
| Value | Description |
|---|---|
Enter / Space / ArrowDown | Opens the calendar from the input. |
Escape | Closes the calendar and returns the focus to the input. |
Inside the calendar, the arrow keys, Home, End and PageUp / PageDown move between days. See the Calendar accessibility notes for the full list.
Emits
| Value | Description |
|---|---|
@update:modelValue | Emitted with the new value when it changes: a string, an array of strings or a `CalendarRange`, depending on the mode. Clearing emits `null`, `[]` or `{ start: null, end: null }`. |
@day-click | Emitted with `{ date, key, isDisabled }` when a day of the calendar is clicked, also for disabled days and when the calendar is readonly. `key` is what the click would select: the date, its ISO week or its month, depending on the `unit`. |
@day-hover | Emitted with `{ date, key, isDisabled }` when the pointer enters a day. |
@day-hover-end | Emitted when the pointer leaves the grid of days. |
@month-change | Emitted with `{ year, month, from, to }` when the visible month changes, by the buttons, the month and year pickers or the keyboard. `month` goes from 1 to 12, and `from` and `to` are the first and last day of the month as ISO dates, so you can load its events. |
@update:error | Emitted with the validation message, or an empty string, when the validator runs. |
Example
<template>
<DatePickerField :modelValue="date" id="date" @update:modelValue="handleChange" />
</template>
<script setup lang="ts">
const date = ref<string | null>(null)
const handleChange = (value: string | null) => {
date.value = value
}
</script>
Methods
| Value | Description |
|---|---|
open() | Opens the popup. Does nothing when the field is disabled, readonly or inline. |
close() | Closes the popup and returns the focus to the input. |