Localized month calendar (Intl, week starts on the locale’s first day): single, range with hover preview, or multiple selection, min/max and disabled dates, full keyboard navigation, month/year views and a sliding transition.
Category
Data display
Type
Web Component (<mv-calendar>)
Status
stable
Keywords
calendar, date, range, month, day-picker, intl, form-associated
When to use
An always-visible month grid lets users pick a date, a range or several days, such as booking nights
Availability must be shown inline with blocked dates, weekends disabled and min/max bounds
Two to four months must be shown side by side to choose a stay or a reporting period
Avoid when
A compact form field is needed that opens the calendar only on demand → use Date Picker instead
The need is to schedule or display events inside days; this grid only selects dates
ISO: “2026-09-22”, range “2026-09-10/2026-09-18”, multiple “2026-09-01,2026-09-08”.
min / max
YYYY-MM-DD
Bounds: out-of-range days are disabled and navigation is blocked.
disabled-dates
string
Comma-separated disabled dates or ranges (“2026-09-17,2026-09-29/2026-10-02”).
disable-weekends
boolean
Disables Saturdays and Sundays.
months
number
1
Number of months shown side by side (1–4).
month
YYYY-MM
Initially displayed month (otherwise the value’s month or today’s).
locale
string
en-US
Language of month and day names (Intl.DateTimeFormat) and, unless week-start is set, first day of the week.
week-start
0–6
locale
Forces the first day of the week (0 = Sunday, 1 = Monday … 6 = Saturday). Without it, the week follows locale (Sunday for en-US, Monday for en-GB or fr-FR), read from Intl.Locale week info with a built-in CLDR fallback.
today
YYYY-MM-DD
Overrides today’s date (tests, time zones).
name
string
Form field name (ISO value).
required
boolean
Native validation; a range must be complete.
readonly
boolean
Navigation allowed, selection frozen.
disabled
boolean
Disables the whole calendar.
data-variant
plain
No border or background (for use inside a popover).
Properties
Name
Type
Description
value
string
ISO value (read/write; also accepts Date or Date[]).
valueAsDate
Date | null
First selected date.
dates
Date[]
All selected dates, sorted.
range
{ start, end }
Range bounds (Date | null).
displayedMonth
string
Displayed month “YYYY-MM” (read-only).
isDateDisabled
(date: Date) => boolean
Extra predicate for disabled dates.
Methods
Name
Description
goTo(date, { focus })
Shows the date’s month (Date or ISO), with a slide.
isDisabled(date)
Whether a date (Date or ISO) cannot be selected.
focusDay()
Moves focus to the active day.
checkValidity() / reportValidity()
Native validation.
Events
Name
Description
mv-change
detail: { value, date, dates, start, end, complete } (complete = false while a range has no end).
mv-month
detail: { month: "YYYY-MM" } when the displayed month changes.
CSS classes
Name
Description
mv-calendar-day
Day button: data-selected, data-today, data-outside, aria-disabled.
APG “Date Picker Dialog” pattern (grid): role=grid table labeled by the month title (announced via a live region), weekday headers with a full abbr, a single tabbable day (roving tabindex). Arrows ±1 day / ±1 week, Page Up/Down ±1 month (Shift: ±1 year), Home/End = start/end of week, Enter/Space selects. Every day has a full aria-label (“Tuesday, September 22, 2026, today”), aria-current=date, aria-selected on the cell, aria-disabled (still focusable). Clickable title → month then year views, Esc returns to days.