MazDatePicker
A powerful and flexible date picker component with support for single dates, date ranges, time selection, and extensive customization options
Before use it, you should install the MazUi plugin in your project, follow instructions in Getting Started
TIP
This component can be translated globally using the MazUi plugin.
Table of Contents
- Basic Usage
- Date Formats
- Date Selection
- Custom Trigger
- Time Selection
- Range Selection
- Internationalization
- Validation & Constraints
- Types
- Props
- Events
- Slots
Basic Usage
The simplest way to use MazDatePicker:
<template>
<MazDatePicker
v-model="date"
label="Select a date"
placeholder="Choose your date"
format="YYYY-MM-DD"
/>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
</script>Date Formats
Understanding date formats is crucial for using MazDatePicker effectively. The component uses two different format concepts:
1. Data Format (format prop)
This controls how dates are stored and transmitted in your v-model. Default is 'YYYY-MM-DD'.
2. Display Format (input-date-format prop)
This controls how dates appear in the input field using Intl.DateTimeFormatOptions.
<template>
<!-- ISO Format (recommended) -->
<MazDatePicker
v-model="date1"
label="ISO Format (YYYY-MM-DD)"
format="YYYY-MM-DD"
:input-date-format="{ dateStyle: 'medium' }"
/>
<!-- US Format -->
<MazDatePicker
v-model="date2"
label="US Format (MM/DD/YYYY)"
format="MM/DD/YYYY"
:input-date-format="{ dateStyle: 'short' }"
/>
<!-- European Format -->
<MazDatePicker
v-model="date3"
label="European Format (DD-MM-YYYY)"
format="DD-MM-YYYY"
:input-date-format="{ dateStyle: 'medium' }"
/>
</template>
<script setup>
import { ref } from 'vue'
const date1 = ref('2024-03-15') // ISO format
const date2 = ref('03/15/2024') // US format
const date3 = ref('15-03-2024') // European format
</script>Custom Display Transformation
Use inputDateTransformer to completely customize how dates appear in the input:
<template>
<MazDatePicker
v-model="date"
label="Custom Display Format"
:input-date-transformer="transformDate"
/>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
const date = ref()
const transformDate = ({ value }) => {
return value ? `📅 ${dayjs(value).format('dddd, MMMM Do YYYY')}` : ''
}
</script>Date Selection
Standard Date Picker
<template>
<MazDatePicker
v-model="date"
label="Select Date"
color="primary"
auto-close
/>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
</script>Inline Date Picker
Perfect for dashboards or when you want the calendar always visible:
<template>
<MazDatePicker
v-model="date"
inline
color="secondary"
/>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
</script>Double Calendar
Show two months at once for better date selection:
<template>
<MazDatePicker
v-model="date"
label="Double Calendar"
double
color="success"
/>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
</script>Custom Trigger
By default MazDatePicker renders a readonly MazInput as the field that opens the calendar. Use the #trigger slot to replace it with your own element - a button, a custom input, an icon... Clicking the slotted element opens the calendar automatically (no @click needed), and the slot exposes the current open state plus functions for programmatic control.
Slot bindings
| Binding | Type | Description |
|---|---|---|
is-open | boolean | Whether the calendar is currently open |
open | () => void | Open the calendar programmatically |
close | () => void | Close the calendar programmatically |
toggle | () => void | Toggle the calendar programmatically |
<template>
<MazDatePicker v-model="date" auto-close>
<!-- Clicking the button opens the picker automatically. -->
<template #trigger="{ isOpen }">
<MazBtn color="secondary" :class="{ 'ring-2 ring-secondary': isOpen }">
{{ date || 'Pick a date' }}
</MazBtn>
</template>
</MazDatePicker>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
</script>TIP
The model value is not passed through the slot - use your own v-model ref (here date) to display the selected value in your custom trigger. The exposed open / close / toggle functions are only needed when you want to drive the picker from your own logic.
In
inlinemode the calendar is always visible, so thetriggerslot is not rendered. To open the picker from an element rendered outside the component, use thecustom-element-selectorprop instead.
Time Selection
Date + Time (24h format)
<template>
<MazDatePicker
v-model="dateTime"
label="Date & Time (24h)"
format="YYYY-MM-DD HH:mm"
time
color="info"
/>
</template>
<script setup>
import { ref } from 'vue'
const dateTime = ref()
</script>Date + Time (12h format)
<template>
<MazDatePicker
v-model="dateTime"
label="Date & Time (12h)"
format="YYYY-MM-DD hh:mm a"
time
color="warning"
/>
</template>
<script setup>
import { ref } from 'vue'
const dateTime = ref()
</script>Time Only Selection
<template>
<!-- 24h format -->
<MazDatePicker
v-model="time24"
label="Time Only (24h)"
format="HH:mm"
only-time
color="accent"
/>
<!-- 12h format -->
<MazDatePicker
v-model="time12"
label="Time Only (12h)"
format="hh:mm a"
only-time
color="destructive"
/>
</template>
<script setup>
import { ref } from 'vue'
const time24 = ref('14:30')
const time12 = ref('02:30 pm')
</script>Custom Minute Intervals
<template>
<MazDatePicker
v-model="time1"
label="5min intervals"
format="HH:mm"
:minute-interval="5"
only-time
/>
<MazDatePicker
v-model="time2"
label="15min intervals"
format="HH:mm"
:minute-interval="15"
only-time
/>
<MazDatePicker
v-model="time3"
label="30min intervals"
format="HH:mm"
:minute-interval="30"
only-time
/>
</template>
<script setup>
import { ref } from 'vue'
const time1 = ref()
const time2 = ref()
const time3 = ref()
</script>Range Selection
For selecting date ranges, pass an object with start and end properties:
<template>
<MazDatePicker
v-model="range"
label="Select Date Range"
range
double
auto-close
color="primary"
/>
</template>
<script setup>
import { ref } from 'vue'
const range = ref({
start: undefined,
end: undefined
})
</script>Range with Shortcuts
Provide predefined shortcuts for common date ranges:
<template>
<MazDatePicker
v-model="range"
label="Range with Shortcuts"
range
double
:shortcuts="shortcuts"
color="secondary"
/>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
const range = ref({
start: undefined,
end: undefined
})
const shortcuts = [
{
label: 'Today',
identifier: 'today',
value: {
start: dayjs().format('YYYY-MM-DD'),
end: dayjs().format('YYYY-MM-DD')
}
},
{
label: 'Last 7 days',
identifier: 'last7days',
value: {
start: dayjs().subtract(6, 'day').format('YYYY-MM-DD'),
end: dayjs().format('YYYY-MM-DD')
}
},
{
label: 'This month',
identifier: 'thisMonth',
value: {
start: dayjs().startOf('month').format('YYYY-MM-DD'),
end: dayjs().endOf('month').format('YYYY-MM-DD')
}
}
]
</script>Property shortcuts
Model
interface MazDatePickerShortcut {
identifier: string // should be uniq
label: string
value: {
start: string
end: string
}
}
type MazDatePickerShortcuts = MazDatePickerShortcut[]Example
import type { MazDatePickerShortcut } from 'maz-ui/components'
const shortcuts: MazDatePickerShortcut[] = [{
label: 'Next month',
identifier: 'nextMonth',
value: {
start: dayjs().add(1, 'month').set('date', 1).format('YYYY-MM-DD'),
end: dayjs()
.add(1, 'month')
.set('date', dayjs().add(1, 'month').daysInMonth())
.format('YYYY-MM-DD'),
},
}]View default shortcuts
const shortcuts = [
{
label: 'Last 7 days',
identifier: 'last7Days',
value: {
start: dayjs().subtract(6, 'day').format('YYYY-MM-DD'),
end: dayjs().format('YYYY-MM-DD'),
},
},
{
label: 'Last 30 days',
identifier: 'last30Days',
value: {
start: dayjs().subtract(29, 'day').format('YYYY-MM-DD'),
end: dayjs().format('YYYY-MM-DD'),
},
},
{
label: 'This week',
identifier: 'thisWeek',
value: {
start: dayjs().startOf('week').format('YYYY-MM-DD'),
end: dayjs().endOf('week').format('YYYY-MM-DD'),
},
},
{
label: 'Last week',
identifier: 'lastWeek',
value: {
start: dayjs()
.subtract(1, 'week')
.startOf('week')
.format('YYYY-MM-DD'),
end: dayjs().subtract(1, 'week').endOf('week').format('YYYY-MM-DD'),
},
},
{
label: 'This month',
identifier: 'thisMonth',
value: {
start: dayjs().set('date', 1).format('YYYY-MM-DD'),
end: dayjs()
.set('date', dayjs().daysInMonth())
.format('YYYY-MM-DD'),
},
},
{
label: 'This year',
identifier: 'thisYear',
value: {
start: dayjs().startOf('year').format('YYYY-MM-DD'),
end: dayjs().endOf('year').format('YYYY-MM-DD'),
},
},
{
label: 'Last year',
identifier: 'lastYear',
value: {
start: dayjs()
.subtract(1, 'year')
.startOf('year')
.format('YYYY-MM-DD'),
end: dayjs().subtract(1, 'year').endOf('year').format('YYYY-MM-DD'),
},
},
]Validation & Constraints
Min/Max Dates
Min: 2026-11-08 | Max: 2026-11-28
<template>
<MazDatePicker
v-model="date"
label="Limited Date Range"
:min-date="minDate"
:max-date="maxDate"
color="info"
/>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
const date = ref()
const minDate = dayjs().subtract(30, 'day').format('YYYY-MM-DD')
const maxDate = dayjs().add(30, 'day').format('YYYY-MM-DD')
</script>Property min-max-auto
Disable min-max auto check to not change the value when it is out of range
<template>
<MazDatePicker
v-model="date"
label="Not auto date range"
:min-date="minDate"
:max-date="maxDate"
:min-max-auto="false"
/>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
const date = ref()
const minDate = dayjs().subtract(30, 'day').format('YYYY-MM-DD')
const maxDate = dayjs().add(30, 'day').format('YYYY-MM-DD')
</script>Disabled Days & Dates
<template>
<!-- Disable weekends -->
<MazDatePicker
v-model="date1"
label="Weekends Disabled"
:disabled-weekly="[0, 6]"
color="warning"
/>
<!-- Disable specific dates -->
<MazDatePicker
v-model="date2"
label="Holidays Disabled"
:disabled-dates="holidays"
color="destructive"
/>
</template>
<script setup>
import { ref } from 'vue'
const date1 = ref()
const date2 = ref()
// 0 = Sunday, 6 = Saturday
const weekends = [0, 6]
// Specific holiday dates
const holidays = [
dayjs().subtract(2, 'day').format('YYYY-MM-DD'),
dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
dayjs().format('YYYY-MM-DD'),
dayjs().add(1, 'day').format('YYYY-MM-DD'),
dayjs().add(2, 'day').format('YYYY-MM-DD'),
dayjs().add(3, 'day').format('YYYY-MM-DD'),
dayjs().add(4, 'day').format('YYYY-MM-DD'),
]
</script>Disabled Hours
<template>
<MazDatePicker
v-model="dateTime"
format="YYYY-MM-DD hh:mm a"
time
label="Disabled Hours"
:disabled-hours="disabledHours"
color="info"
/>
<MazDatePicker
v-model="time"
format="HH:mm"
only-time
label="Disabled Hours"
:disabled-hours="disabledHours"
color="info"
/>
</template>
<script setup>
import { ref } from 'vue'
const date = ref()
const time = ref()
const disabledHours = [0, 1, 2, 11, 22, 23]
</script>Internationalization
MazDatePicker supports full internationalization. By default, it uses the locale from the MazUiTranslations plugin, but you can override it:
<template>
<!-- French -->
<MazDatePicker
v-model="frenchDate"
label="French Locale"
locale="fr-FR"
:first-day-of-week="1"
color="primary"
/>
<!-- German -->
<MazDatePicker
v-model="germanDate"
label="German Locale"
locale="de-DE"
:first-day-of-week="1"
color="secondary"
/>
<!-- Japanese -->
<MazDatePicker
v-model="japaneseDate"
label="Japanese Locale"
locale="ja-JP"
color="accent"
/>
<!-- Arabic -->
<MazDatePicker
v-model="arabicDate"
label="Arabic Locale"
locale="ar-SA"
:first-day-of-week="6"
color="warning"
/>
</template>
<script setup>
import { ref } from 'vue'
const frenchDate = ref()
const germanDate = ref()
const japaneseDate = ref()
const arabicDate = ref()
</script>Types
// Value types
type MazDatePickerValue = string | undefined | MazDatePickerPartialRangeValue
interface MazDatePickerRangeValue {
start: string
end: string
}
type MazDatePickerPartialRangeValue = Partial<MazDatePickerRangeValue>
// Shortcut type
interface MazDatePickerShortcut {
identifier: string
label: string
value: {
start: string
end: string
}
}Accessibility
- The input is a
comboboxopening adialog(aria-haspopup="dialog",aria-expanded,aria-controls). - Each month is a
gridlabelled by the month and the year, the days of the week are its column headers and each day has its full date as label (aria-current="date"for today,aria-selectedon the selected days). - Keyboard in the calendar: only one day is in the tab sequence, the arrows move by day (← →) and by week (↑ ↓), Home / End go to the start / end of the week, Page Up / Page Down to the previous / next month (with Shift: year). Disabled days are skipped and the calendar follows the focus to the displayed month.
- The navigation buttons labels come from
@maz-ui/translations(arianamespace).
Props
| Name | Description | Type | Required | Default | Possible values |
|---|---|---|---|---|---|
| id | The unique identifier of the component | string | No | - | - |
| input-props | The props to apply to the input component | MazInputProps<MazInputValue> | No | - | - |
| model-value | v-model The value of the date picker component If an object is provided, the picker will be a range picker | MazDatePickerValue | No | - | - |
| format | The format pattern for date display and parsing | string | No | "YYYY-MM-DD" | - |
| open | v-model:open Controls whether the picker window is open | boolean | No | false | - |
| label | The label text displayed above the input field | string | No | - | - |
| placeholder | The placeholder text shown when no value is selected | string | No | - | - |
| input-date-format | The Intl.DateTimeFormatOptions for styling the input date display | Intl.DateTimeFormatOptions | No | { dateStyle: "medium", timeStyle: "short" } | - |
| input-date-transformer | Custom function to transform the formatted date display | ((payload: { formattedDate?: string | undefined; value?: MazDatePickerValue; locale: string; }) => string) | No | - | - |
| locale | v-model:locale The locale string for date formatting and localization | string | No | "" | - |
| hide-header | Controls whether the calendar header is hidden | boolean | No | false | - |
| disabled | Controls whether the component is disabled | boolean | No | false | - |
| first-day-of-week | The first day of the week in the calendar | 0 | 1 | 2 | 3 | 4 | 5 | 6 | No | 0 | '0' | '1' | '2' | '3' | '4' | '5' | '6' |
| auto-close | Controls whether the picker closes automatically after date selection | boolean | No | false | - |
| custom-element-selector | CSS selector for a custom element that triggers the picker | string | No | - | - |
| double | Controls whether the picker displays two months side by side | boolean | No | false | - |
| inline | Controls whether the picker is displayed inline without input field | boolean | No | false | - |
| color | The color theme of the component | "primary" | "secondary" | "accent" | "info" | "success" | "warning" | "destructive" | "contrast" | "transparent" | No | "primary" | 'primary' | 'secondary' | 'accent' | 'info' | 'success' | 'warning' | 'destructive' | 'contrast' | 'transparent' |
| picker-position | The position where the picker popover should appear | MazPopoverPosition | No | "auto" | 'top' | 'bottom' | 'left' | 'right' | 'top-end' | 'bottom-end' | 'left-end' | 'right-end' | 'top-start' | 'bottom-start' | 'left-start' | 'right-start' |
| picker-prefer-position | The preferred position of the picker popover | MazPopoverPreferPosition | No | "bottom-start" | 'top' | 'bottom' | 'left' | 'right' | 'top-end' | 'bottom-end' | 'left-end' | 'right-end' | 'top-start' | 'bottom-start' | 'left-start' | 'right-start' |
| picker-fallback-position | The fallback position of the picker popover | MazPopoverFallbackPosition | No | "top-start" | 'top' | 'bottom' | 'left' | 'right' | 'top-end' | 'bottom-end' | 'left-end' | 'right-end' | 'top-start' | 'bottom-start' | 'left-start' | 'right-start' |
| time | Controls whether the picker includes a time selector | boolean | No | false | - |
| only-time | Controls whether the picker shows only time selection (no date) | boolean | No | false | - |
| minute-interval | The interval in minutes for the time picker minute selection | number | No | 5 | '1' | '5' | '10' | '15' | '30' |
| use-browser-locale | Controls whether to automatically detect and use the browser's locale | boolean | No | true | - |
| fetch-local | Controls whether to fetch locale data dynamically | boolean | No | true | - |
| shortcuts | Array of predefined date range shortcuts or false to disable | boolean | MazDatePickerShortcut[] | No | true | - |
| shortcut | The identifier of the currently selected shortcut | string | No | - | - |
| min-date | The minimum selectable date in ISO format | string | No | - | - |
| max-date | The maximum selectable date in ISO format | string | No | - | - |
| min-max-auto | When minDate or maxDate are provided, if the current date is not between minDate and maxDate, the current date will be set to the minDate or maxDate | boolean | No | true | - |
| disabled-weekly | Array of weekday numbers to disable (0 = Sunday, 6 = Saturday) | number[] | No | [] | - |
| disabled-dates | Array of specific dates to disable in ISO format | string[] | No | [] | - |
| disabled-hours | Array of hour numbers to disable in the time picker (0-23) | number[] | No | [] | - |
| block | Controls whether the input displays in full width | boolean | No | false | - |
| range | Controls whether the picker operates in range selection mode | boolean | No | false | - |
| transition | The transition name of the popover | string | No | "scale-fade" | - |
Events
| Event name | Payload | Description |
|---|---|---|
| update:model-value | value: MazDatePickerValue | Emitted when the picker value changes |
| close | (void | undefined)? | Emitted when the picker closes |
| update:locale | value: string | |
| update:open | value: boolean |
Slots
| Name | Description | Bindings |
|---|---|---|
| trigger | Replace the default input with your own element | isOpen boolean - Current open state of the popoverclose () => void - Function to close the popoveropen () => void - Function to open the popovertoggle () => void - Function to toggle the popover |