Date Picker — <mv-date-picker>

Date picker: an input-style trigger showing the formatted date (ranges included) and a calendar in a popover, with presets like “Today”, “Last 7 days”…; form-associated.

CategoryForms
TypeWeb Component (<mv-date-picker>)
Statusstable
Also installscalendar
Keywordsdate-picker, datepicker, date, range, presets, popover, form-associated

When to use

Avoid when

Install

node scripts/add.mjs date-picker --out ./src/marvelous

AI agent with the Marvelous UI MCP server: install_components({ slugs: ["date-picker"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dismiss.js, core/dom.js, core/element.js, core/motion.js, core/position.js, components/date-picker/date-picker.js, components/date-picker/date-picker.css, components/calendar/calendar.js, components/calendar/calendar.css.

Usage

Canonical markup — start from it and customize with attributes, data-* and CSS variables:

<form id="date-picker-demo-form" style="display:flex;flex-wrap:wrap;gap:1.25rem;justify-content:center;align-items:flex-start">
  <div style="display:grid;gap:.4rem">
    <label for="date-picker-demo-delivery" style="font-size:.875rem;font-weight:500">Delivery date</label>
    <mv-date-picker id="date-picker-demo-delivery" name="delivery" min="2026-09-23" disable-weekends clearable presets placeholder="Pick a business day"></mv-date-picker>
  </div>
  <div style="display:grid;gap:.4rem">
    <label for="date-picker-demo-period" style="font-size:.875rem;font-weight:500">Report period</label>
    <mv-date-picker id="date-picker-demo-period" name="period" mode="range" presets value="2026-09-01/2026-09-22" format="long" style="--mv-date-picker-width:19rem"></mv-date-picker>
  </div>
</form>

API

Attributes

NameTypeDefaultDescription
modesingle | range | multiplesingleSelection type (forwarded to the calendar).
valuestringInitial ISO value (“2026-09-22” or “2026-09-01/2026-09-22”).
namestringForm field name (ISO value).
placeholderstringPick a dateText shown when nothing is selected.
formatshort | medium | long | fullmediumIntl style of the displayed date (ranges via formatRange: “Sep 1 – 22, 2026”).
presetsbooleanShows the default presets column (depends on the mode).
clearablebooleanButton to clear the date.
requiredbooleanNative validation; a range must be complete.
disabledbooleanDisables the trigger.
invalidbooleanError style + aria-invalid.
placementbottom-start | top-start…bottom-startPopover placement (flipped when there is no room).
min / max / disabled-dates / disable-weekends / months / locale / week-start / todayForwarded as-is to <mv-calendar>.
labelstringAccessible name without a <label for>.
data-sizesm | lgTrigger height.

Properties

NameTypeDescription
valuestringISO value (also accepts a Date).
valueAsDateDate | nullFirst date.
range{ start, end }Range bounds.
presetListArray<{ label, value: string | (today: Date) => string }>Custom presets (shown even without the presets attribute).
calendarMvCalendarInner calendar (isDateDisabled, goTo…).
isOpenbooleanWhether the popover is open.

Methods

NameDescription
open() / close({ focus })Opens or closes the popover.
clear()Clears the value.
checkValidity() / reportValidity()Native validation.

Events

NameDescription
mv-changedetail: { value, date, start, end, complete, preset? }.
mv-open / mv-closePopover opened and closed.

CSS classes

NameDescription
mv-date-picker-trigger / -value / -clear / -popup / -presets / -presetGenerated parts.

CSS variables

NameDefaultDescription
--mv-date-picker-width16rem (18rem for ranges)Trigger width.
--mv-date-picker-radiusvar(--mv-radius-md)Trigger radius.

Accessibility

<button> trigger with aria-haspopup=dialog and aria-expanded, named by the <label for> + the displayed value. The popover is a labeled non-modal role=dialog; on open, focus moves to the calendar's active day (full APG grid), Escape or picking a date/range closes it and returns focus to the trigger; tabbing out also closes it. ↓ on the trigger opens it. Presets are aria-pressed buttons.