Web component

<p-datetime>

Date, time and date range picker with a calendar dialog

Import
@parallelogram-js/core/components/PDatetime
Tag
p-datetime

Playground

<form class="form" action="#chosen">
  <div class="form__group">
    <label class="form__label" for="visit-date">Date</label>
    <div class="form__control">
      <p-datetime id="visit-date" name="date" mode="date" show-quick-dates required></p-datetime>
    </div>
  </div>
  <div class="form__actions">
    <button type="submit">Continue</button>
  </div>
</form>

Submits the local date and time chosen, such as 2024-01-15T14:30, as <input type="datetime-local"> does. In time mode it submits hh:mm, and format changes what is sent.

<form class="form" action="#chosen">
  <div class="form__group">
    <label class="form__label" for="appointment">Appointment</label>
    <div class="form__control">
      <p-datetime id="appointment" name="appointment" mode="datetime" value="2024-01-15T14:30"></p-datetime>
    </div>
  </div>
  <div class="form__actions">
    <button type="submit">Book</button>
  </div>
</form>
Stay
<form class="form" action="#chosen">
  <div class="form__group">
    <span class="form__label">Stay</span>
    <div class="form__control">
      <p-datetime name="check-in" range range-to="check-out" from-label="Check in" to-label="Check out"></p-datetime>
    </div>
  </div>
  <div class="form__actions">
    <button type="submit">Search rooms</button>
  </div>
</form>

About

The value fields and the calendar button open a dialog with a day grid and, in datetime and time modes, time selects. Values are local and follow the native inputs: yyyy-mm-dd in date mode, yyyy-mm-ddThh:mm in datetime mode like datetime-local, and hh:mm in time mode, with :ss when the seconds are set. An ISO instant with Z or an offset is read as the local date and time it stands for. The element is form-associated: it submits its value, and in range mode the end of the range under range-to, in that format or the one format names.

min and max disable days outside them, and min-from-field and max-from-field follow another field, such as a check-in date limiting check-out.

Accessibility

In the day grid the arrow keys move by day and week, Home and End go to the start and end of the week, Page Up and Page Down change month (with Shift, year), Enter or Space picks the focused day, and Escape closes the dialog and returns focus. In the month and year views the arrow keys move between months or years, and Home and End go to the start and end of the row. Moving focus outside the picker closes the dialog.

Without JavaScript

Until the module loads this element is empty markup with no field and no calendar in it, and the package stylesheet hides it while scripts are running. It is the form field, so a form submitted before it upgrades carries no date and required cannot hold the form back. Where that matters, render a native <input type="date"> on the server and replace it once the module is in.

Usage

Register the component and the framework loads it the first time a page contains p-datetime.

import { Parallelogram } from '@parallelogram-js/core';

const app = Parallelogram.create();
app.components.add('p-datetime', () => import('@parallelogram-js/core/components/PDatetime'));
app.run();

Attributes

NameTypeDefaultDescription
modedate | datetime | timedateWhat the picker chooses Property mode.
valuestringnoneThe value, or the start of the range, in local time: yyyy-mm-dd in date mode, yyyy-mm-ddThh:mm in datetime mode and hh:mm in time mode. An ISO instant with Z or an offset is read as the local date and time Property value.
namestringnoneThe form field name Property name.
time-format12 | 2424Hour format of the time selects Property timeFormat.
show-quick-datesflagnoneShow quick date buttons Property showQuickDates.
quick-datesstringyesterday,today,tomorrowComma-separated quick dates Property quickDates.
rangeflagnoneChoose a start and end Property range.
range-tostringnoneForm field name for the end of the range Property rangeTo.
range-to-valuestringnoneThe end of the range, in the same format as value Property rangeToValue.
date-nounstringdateThe word for a date inside the sentences below, where {what} stands For every instance, PDatetime.defaults.dateNoun.
datetime-nounstringdate and timeThe same for a date and time For every instance, PDatetime.defaults.datetimeNoun.
time-nounstringtimeThe same for a time For every instance, PDatetime.defaults.timeNoun.
placeholderstringSelect {what}...Shown in an empty field For every instance, PDatetime.defaults.placeholder.
from-placeholderstringStart {what}...Shown in an empty start field of a range For every instance, PDatetime.defaults.fromPlaceholder.
to-placeholderstringEnd {what}...Shown in an empty end field of a range For every instance, PDatetime.defaults.toPlaceholder.
choose-labelstringChoose {what}The accessible name of the calendar button and the panel For every instance, PDatetime.defaults.chooseLabel.
choose-range-labelstringChoose {what} rangeThe accessible name of the panel while choosing a range For every instance, PDatetime.defaults.chooseRangeLabel.
value-labelstring{label}: {value}The accessible name of a field: its form label, or the mode's noun, and its value For every instance, PDatetime.defaults.valueLabel.
empty-valuestringnot setThe {value} in that name while the field is empty For every instance, PDatetime.defaults.emptyValue.
from-labelstringFromLabel for the start of the range Property fromLabel. For every instance, PDatetime.defaults.fromLabel.
to-labelstringToLabel for the end of the range Property toLabel. For every instance, PDatetime.defaults.toLabel.
prev-month-labelstringPrevious monthThe accessible name of the previous button over the days For every instance, PDatetime.defaults.prevMonthLabel.
next-month-labelstringNext monthThe same for the next button For every instance, PDatetime.defaults.nextMonthLabel.
prev-year-labelstringPrevious yearThe previous button over the months For every instance, PDatetime.defaults.prevYearLabel.
next-year-labelstringNext yearThe next button over the months For every instance, PDatetime.defaults.nextYearLabel.
prev-years-labelstringPrevious yearsThe previous button over the years For every instance, PDatetime.defaults.prevYearsLabel.
next-years-labelstringNext yearsThe next button over the years For every instance, PDatetime.defaults.nextYearsLabel.
hour-labelstringHourThe accessible name of the hour select For every instance, PDatetime.defaults.hourLabel.
minute-labelstringMinuteThe accessible name of the minute select For every instance, PDatetime.defaults.minuteLabel.
ampm-labelstringAM or PMThe accessible name of the AM/PM select For every instance, PDatetime.defaults.ampmLabel.
clear-labelstringClearThe clear button For every instance, PDatetime.defaults.clearLabel.
apply-labelstringApplyThe apply button For every instance, PDatetime.defaults.applyLabel.
range-start-hintstringClick to select start dateAnnounced while choosing a range, before a start is chosen For every instance, PDatetime.defaults.rangeStartHint.
range-end-hintstringStart date selected. Now select end dateAnnounced once the start is chosen For every instance, PDatetime.defaults.rangeEndHint.
range-done-hintstringRange selected. Click dates to modify.Announced once both ends are chosen For every instance, PDatetime.defaults.rangeDoneHint.
yesterday-labelstringYesterdayThe quick date for yesterday For every instance, PDatetime.defaults.yesterdayLabel.
today-labelstringTodayThe quick date for today For every instance, PDatetime.defaults.todayLabel.
tomorrow-labelstringTomorrowThe quick date for tomorrow For every instance, PDatetime.defaults.tomorrowLabel.
required-messagestringPlease choose a {what}.The form's validity message while a required field is empty For every instance, PDatetime.defaults.requiredMessage.
required-range-messagestringPlease choose a start and end {what}.The same for a required range For every instance, PDatetime.defaults.requiredRangeMessage.
min-messagestringPlease choose a date on or after {date}.The validity message for a date before min, with {date} formatted in the page's language For every instance, PDatetime.defaults.minMessage.
max-messagestringPlease choose a date on or before {date}.The same for a date after max For every instance, PDatetime.defaults.maxMessage.
langstringnoneThe language for month and weekday names and every formatted date, taken from the nearest ancestor's lang when the picker has none, and from the browser when the page has none either. A language without a region keeps the visitor's own: lang="en" shows an Australian visitor 15 Jan 2024, lang="en-US" shows everyone Jan 15. Changing it on the picker re-renders; changing an ancestor's does not
minstringnoneEarliest selectable date, as yyyy-mm-dd, a local date and time, or ISO Property min.
maxstringnoneLatest selectable date, as yyyy-mm-dd, a local date and time, or ISO Property max.
min-from-fieldstringnoneName of a field whose value also sets the earliest date Property minFromField.
max-from-fieldstringnoneName of a field whose value also sets the latest date Property maxFromField.
formatstringnoneFormat of the submitted value: iso, iso-tz, iso-datetime, iso-datetime-tz, us-date, us-datetime, eu-date, eu-datetime, mysql, or tokens yyyy mm dd hh ii ss tz tzz Property format.
requiredflagnoneThe value, both ends in range mode, must be set for the form to submit Property required.
disabledflagnoneDisables the picker; a disabled fieldset does the same Property disabled.

Properties

NameTypeDescription
valuestringThe value, or the start of the range, as a local string in the format of the mode
rangeToValuestringThe end of the range, in the same format as value
rangebooleanReflects the range attribute
formread onlyHTMLFormElement | nullThe owning form
validityread onlyValidityStateThe validity state

Methods

NameSignatureDescription
open() => voidOpen the calendar dialog
close(options?: { returnFocus?: boolean }) => voidClose the dialog, optionally returning focus to the control that opened it
toggle() => voidOpen or close the dialog
checkValidity() => booleanCheck the value
reportValidity() => booleanCheck the value and show the browser message

Events

NameDetailDescription
change{ value: string; complete: boolean; toValue?: string; from?: string; to?: string }The value changed; complete is true once both ends of a range are set. Bubbles out of shadow roots DOM event
p-datetime:open{ value: string; toValue?: string }The dialog opened DOM event
p-datetime:close{ changed: boolean; value: string; toValue?: string }The dialog closed; changed says whether the value differs from when it opened DOM event

Shadow parts

NameDescription
fieldThe row holding the value buttons and the calendar button
inputEach value button, which shows the date and opens the panel
triggerThe calendar button at the end of the field
panelThe dialog holding the calendar, the time and the actions
navThe month navigation row
month-yearThe month and year button in that row
gridThe day grid
dayEach day button in the grid
time-selectEach time select: the hour, the minute and AM/PM
ampmThe AM/PM select, which also carries time-select
actionEach button in the actions row
primaryThe Apply button, which also carries action

CSS custom properties

NameDefaultDescription
--datetime-shadow-colorvar(--color-shadow)Colour the panel shadow is built from
--datetime-btn-hover-bgvar(--color-hover)Background of a hovered navigation button
--datetime-placeholder-opacity0.6Opacity of the placeholder in an empty field
--datetime-icon-opacity0.7Opacity of the calendar and chevron icons
--datetime-disabled-opacityvar(--form-control-disabled-opacity)Opacity of a disabled field; follows the form control family
--datetime-padding-x0.75emHorizontal padding of the value buttons
--datetime-padding-y0.375emVertical padding of the value buttons
--datetime-gap0.5emSpace between the parts of the field and the panel
--datetime-radius-lgvar(--panel-border-radius)The panel's corner radius; follows the panel family
--datetime-border-width1pxWidth of the field and panel borders
--datetime-focus-ring-width2pxWidth of the focus ring on days and controls
--datetime-today-border-width2pxWidth of the ring marking today's date
--datetime-transition0.15s easeLength and easing of hover and focus changes
--datetime-panel-paddingvar(--panel-padding)Padding inside the panel; follows the panel family
--datetime-preset-bgvar(--color-surface-muted)Background of a quick-date pill; follows the muted surface
--datetime-preset-colorvar(--color-text)Text of a quick-date pill; follows the text colour
--datetime-preset-hover-bgvar(--color-accent)Background of a quick-date pill under the pointer; follows the accent
--datetime-preset-hover-colorvar(--color-accent-contrast)Text of a quick-date pill under the pointer; follows the accent contrast
--datetime-action-btn-bgvar(--button-secondary-bg)Background of an action button; follows the secondary button
--datetime-action-btn-colorvar(--button-secondary-color)Text of an action button
--datetime-action-btn-bordervar(--button-secondary-border)Border of an action button
--datetime-action-btn-hover-bgvar(--button-secondary-hover-bg)Background of a hovered action button
--datetime-action-btn-hover-bordervar(--button-secondary-hover-border)Border of a hovered action button
--datetime-action-btn-primary-bgvar(--button-primary-bg)Background of the Apply button; set the button token to change every component, or this one for the picker alone
--datetime-action-btn-primary-colorvar(--button-primary-color)Text of the Apply button
--datetime-action-btn-primary-hover-bgnoneBackground of the hovered Apply button
--datetime-action-btn-radiusvar(--button-border-radius)Corner radius of an action button
--datetime-action-btn-paddingvar(--button-padding-y) var(--button-padding-x)Padding of an action button
--datetime-action-btn-min-heightvar(--button-min-height)Least height of an action button
--datetime-action-btn-font-sizevar(--button-font-size)Font size of an action button
--datetime-action-btn-font-weightvar(--button-font-weight)Font weight of an action button
--datetime-action-btn-text-transformnoneText transform of an action button
--datetime-action-btn-letter-spacingnormalLetter spacing of an action button
--datetime-accentvar(--color-accent)Focus rings, today, hovered buttons and the tint behind days in a range
--datetime-accent-strongvar(--color-accent-hover)Selected days and primary buttons, which carry text
--datetime-bgvar(--surface-dropdown-color-bg)Field and panel background
--datetime-textcurrentColorText colour
--datetime-mutedvar(--color-text-muted)Muted text
--datetime-bordervar(--color-border)Panel border and dividers
--datetime-control-bordervar(--surface-control-border-color)Border of the field and the time selects
--datetime-radiusnoneCorner radius
--datetime-shadow0 4px 6px var(--color-shadow)Panel shadow
--datetime-hovervar(--color-hover)Background of hovered days and buttons
--datetime-cell-sizenoneSize of each day in the grid
--datetime-panel-min-widthnoneNarrowest the panel gets
--datetime-animation-durationnoneLength of the panel animation