Skip to main content

DatePicker

The DatePicker component is used to select a date value. At mobile viewports, the browsers native input is used.

Import

// with @dhl-official/react-library:
import { DhlDatePicker } from "@dhl-official/react-library"
// with @dhl-official/ui-libraries/react-library:
import { DhlDatePicker } from "@dhl-official/ui-libraries/react-library"
info

Please ensure all date values are passed in the international ISO-8601 format: YYYY-MM-DD.

Accessibility

The DatePicker is built with consideration for accessibility standards and keyboard support.

Choose Date Button

  • Space, Enter : Toggles DatePicker visibility and moves focus to month and year text.

DatePicker Dialog

  • Esc : Close DatePicker dialog and move focus to "choose date" button.
  • Tab : Move focus to next focusable element.
  • Shift + Tab : Move focus to previous focusable element
note

The calendar used inside DatePicker uses role="grid" meaning only one 'day button' is in the tab sequence at any one time.

DatePicker Dialog: Calendar Grid

  • Space, Enter : Selects a date, closes the dialog, and moves focus back to the “Choose Date” button.
    • Additionally updates the value of the Duet Date Picker input with the selected date, and adds selected date to “Choose Date” button label.
  • Arrow up : Moves focus to the same day of the previous week.
  • Arrow down : Moves focus to the same day of the next week.
  • Arrow right : Moves focus to the next day.
  • Arrow left : Moves focus to the previous day.
  • Home : Moves focus to the first day (e.g Monday) of the current week.
  • End : Moves focus to the last day (e.g. Sunday) of the current week.
  • Page Up : Changes the grid of dates to the previous month and sets focus on the same day of the same week.
  • Shift + Page Up: Changes the grid of dates to the previous year and sets focus on the same day of the same week.
  • Page Down : Changes the grid of dates to the next month and sets focus on the same day of the same week.
  • Shift + Page Down : Changes the grid of dates to the next year and sets focus on the same day of the same week.
caution

Please ensure the prop localeLabels is supplied and matches the locale language. This ensures screen-reader users can leverage voice-over technology in the context of DatePicker.

Using Events

The DatePicker can be used with DOM events and listeners. Additionally, custom events are available (see Events table below) which include a custom detail object. This object contains fields designed to increase ease of use. The example below demonstrates how the detail object can be used to retrieve the value as a date through the valueAsDate field.

// Select the DatePicker component
const date = document.querySelector("dhl-date-picker");

// Listen for when date is selected
date.addEventListener("dhlChange", function (e) {
console.log("selected date", e.detail.valueAsDate);
});

With an output:

Tue Feb 14 2023 00:00:00 GMT+0000 (Greenwich Mean Time)

Using Custom Formats

By default, the DatePicker uses the yyyy-mm-dd (DE locale) format.

To use a different format, the prop dateAdapter is available for use. The example below demonstrates how the prop dateAdapter can be used with a en-GB locale format DD-MM-YYYY.

const picker = document.querySelector("dhl-date-picker");
const DATE_FORMAT = /^(\d{1,2})\.(\d{1,2})\.(\d{4})$/;

picker.dateAdapter = {
parse(value = "", createDate) {
const matches = value.match(DATE_FORMAT);

if (matches) {
return createDate(matches[3], matches[2], matches[1]);
}
},
format(date) {
const day = date.getDate().toString().padStart(2, "0"); // Get the day of the month as a two-digit string
const month = (date.getMonth() + 1).toString().padStart(2, "0"); // Get the month as a two-digit string
const year = date.getFullYear().toString(); // Get the year as a string
return `${day}/${month}/${year}`;
},
};

Known Issues

  • Currently, the NVDA screen-reader on the Windows platform does not automatically switch from browse mode to focus mode within the DatePicker calendar grid, as they do with native <input type="date" /> elements.

Code

<DhlDatePicker></DhlDatePicker>

Interactive Demo

Migrating from DUIL 1.0

  • Aria labels now passed through required localeLabels prop - please see documentation for all available aria fields found within this object.
  • Rename firstDayOfTheWeek to firstDayOfWeek
  • Remove date
  • Remove externalValidation
  • Rename minDate to min
  • Rename maxDate to max
  • Remove isBlock
  • Remove variant
  • Remove displayFormat see new prop dateAdapter for new implementation
  • Add dataAriaLabelledby
  • Add inputLabel
  • Add isDisabled
  • Add role
  • Add direction
  • Add dateAdapter
  • Add isDateDisabled
  • Add dhlChange
  • AdddhlBlur
  • Add new event dhlChange
  • Add new event dhlFocus
  • Add new event dhlOpen
  • Add new event dhlClose
  • Add public method setFocus
  • Add public method show
  • Add public method hide

Readme

Usage

Dhl-date-picker

Snippets of code in HTML and JavaScript to show some of the use cases for the component. The code is not meant to be executed, but to be used as a reference for the usage of the component.
Angular, React and Vue usages are not included in this documentation, but can be easily derived from the html and javascript code.

default usage

<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-1"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>

<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
form.addEventListener("submit", async (e) => {
e.preventDefault();
console.log("datePicker - isValid", await datePicker.checkValidity());
console.log(Object.fromEntries(new FormData(form)));
return await e.target.checkValidity();
});
</script>

usage with validation (required) and (browser) default validation message

<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
required
name="date-picker-1"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>

<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
form.addEventListener("submit", async (e) => {
e.preventDefault();
console.log("datePicker - isValid", await datePicker.checkValidity());
console.log(Object.fromEntries(new FormData(form)));
return await e.target.checkValidity();
});
</script>

usage with validation (required) and custom validation message

<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-1"
input-label="Example text"
required
>
</dhl-date-picker>
</dhl-grid-cell>

<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>

<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");
const validationMessageInvalid = "This field is required";
const validationMessageValid = "This field is valid";

form.addEventListener("submit", async (e) => {
e.preventDefault();
const isValid = await datePicker.checkValidity();
if (isValid) {
datePicker.validation = {
type: "valid",
message: validationMessageValid,
};
} else {
datePicker.validation = {
type: "invalid",
message: validationMessageInvalid,
};
}
return await form.checkValidity();
});
</script>

usage with custom events

<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
required
name="date-picker-1"
input-label="Example text"
>
</dhl-date-picker>
</dhl-grid-cell>
<dhl-grid-cell>
<dhl-button
type="reset"
variant="text"
>RESET</dhl-button
>
<dhl-button
type="submit"
variant="primary"
>SUBMIT</dhl-button
>
</dhl-grid-cell>
</dhl-grid-container>
</form>

<script type="module">
const form = document.querySelector("form");
const datePicker = document.querySelector("dhl-date-picker");

const validationMessageInvalid = "This field is required";
const validationMessageValid = "This field valid";
const text = document.querySelector("dhl-text");

const isElementValid = async () => {
const isValid = await datePicker.checkValidity();
if (isValid) {
datePicker.validation = {
type: "valid",
message: validationMessageValid,
};
} else {
datePicker.validation = {
type: "invalid",
message: validationMessageInvalid,
};
}
return isValid;
};

form.addEventListener("submit", async (e) => {
e.preventDefault();
await isElementValid();
});

datePicker.addEventListener("dhlChange", async (e) => await isElementValid());
datePicker.addEventListener("dhlBlur", async (e) => isElementValid());
</script>

usage with disabling specific dates

<form novalidate>
<dhl-grid-container columns="2">
<dhl-grid-cell span-columns="2">
<dhl-date-picker
name="date-picker-123"
input-label="Example text"
></dhl-date-picker>
</dhl-grid-cell>
</dhl-grid-container>
</form>

<script type="module">
const datePicker = document.querySelector("dhl-date-picker");

const disabledDates = [
1, 2, 10, 11, 12, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
];

datePicker.isDateDisabled = (date) => {
const day = date.getDate();
return disabledDates.includes(day);
};
</script>

Properties

PropertyAttributeDescriptionTypeDefault
dataAriaLabelledbydata-aria-labelledbyAn optional ariaLabelledby prop that establishes the relationships between objects and their label(s), and its value should be one or more element IDs, which refer to elements that have the text needed for labelling. List multiple element IDs in a space delimited fashion.stringundefined
dataIddata-idAn optional prop. Gives a valid HTML ID attribute value for the component.stringdhl-date-picker-${getRandomString()}
dataRoledata-roleAn optional prop defining the role attribute of the component.stringundefined
dataTestiddata-testidAn optional prop. The test id attached to the component as a data-testid attribute.stringundefined
directiondirectionAn optional prop which forces the opening direction of the calendar modal to be always left or right. This setting can be useful when the input is smaller than the opening date picker would be as by default the picker always opens towards right."left" \| "right"DHL_DATE_PICKER.DIRECTION.RIGHT
firstDayOfWeekfirst-day-of-weekAn optional prop used to set the first day of the week. Sunday is treated as index 0. The default is 1; Monday.DaysOfWeek.Friday \| DaysOfWeek.Monday \| DaysOfWeek.Saturday \| DaysOfWeek.Sunday \| DaysOfWeek.Thursday \| DaysOfWeek.Tuesday \| DaysOfWeek.WednesdayDaysOfWeek.Monday
inputLabelinput-labelAn optional prop used to set the label inside the DatePicker inputfield. This is also used as an aria label for the input. Please use the dataAriaLabelledby prop with an associated label should you choose to not supply this prop.stringundefined
isDateDisabled--An optional prop used to set which days are disabled and therefore disallowed. For example, this can be used to disallow selection of weekends.(date: Date) => boolean() => false
isDisabledis-disabledAn optional flag to define if the component is disabled.booleanfalse
localelocaleAn optional prop used to change the calendar locale - following the the BCP 47 standard Note that localeLabels is provided by default in English en-GB. If you want to use a different locale, you will need to provide your own localeLabels prop.string"default"
localeLabels--An optional prop used to set the DatePicker localization labels and aria labels. Defaults to English en-GB.{ buttonLabel: string; selectedDateMessage: string; selectedDateRangeMessage: string; prevMonthLabel: string; nextMonthLabel: string; prevYearLabel: string; nextYearLabel: string; monthSelectLabel: string; yearSelectLabel: string; closeLabel: string; invalidDateErrorMessage: string; invalidDateRangeErrorMessage: string; }defaultLocaleLabels
maxmaxAn optional prop used to set the maximum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD. This setting can be used alone or together with the min property.Date \| stringundefined
minminAn optional prop used to set the minimum date allowed to be picked. Must be in IS0-8601 format: YYYY-MM-DD. This setting can be used alone or together with the max property.Date \| stringundefined
namenameAn optional value to be set to the element HTML name attribute. It takes any valid value that can be used for the name attribute of an HTMLInputElement.string${getRandomString()}-date
openOnFocusopen-on-focusAn optional prop when set to true, the date picker option list will be shown on input focus.booleanfalse
requiredrequiredAn optional prop to flag the component as required within a form context.booleanfalse
validation--An optional DatePicker validation prop Required Fields type{ type: Variants.valid \| Variants.invalid \| Variants.note; message?: string; }undefined
valuevalueAn optional DatePicker value. Must be in IS0-8601 format: YYYY-MM-DD.stringundefined

Events

EventDescriptionType
dhlBlurEvent emitted when the component loses focus.CustomEvent<{ component: string; componentId: string; }>
dhlChangeEvent emitted when the component changes value.CustomEvent<{ component: string; componentId: string; value: string; valueAsDate: Date; short: string; long: string; }>
dhlCloseEvent emitted when the component is closed.CustomEvent<{ component: string; componentId: string; }>
dhlFocusEvent emitted when the component is focused.CustomEvent<{ component: string; componentId: string; }>
dhlOpenEvent emitted when the component is opened.CustomEvent<{ component: string; componentId: string; }>

Methods

checkValidity() => Promise<boolean>

Checks the validity of the component.

Returns

Type: Promise<boolean>

A promise that resolves to true if the component is valid, otherwise false.

getInputElement() => Promise<HTMLInputElement>

Retrieves the input element asynchronously.

Returns

Type: Promise<HTMLInputElement>

A promise that resolves to the input element.

getValidationMessage() => Promise<string>

Retrieves the validation message for the component.

Returns

Type: Promise<string>

A promise that resolves to a string representing the validation message.

hide(moveFocusToButton?: boolean) => Promise<void>

Hide the calendar modal. Set moveFocusToButton to false to prevent focus returning to the date picker's button. Default is true.

Parameters

NameTypeDescription
moveFocusToButtonboolean

Returns

Type: Promise<void>

reportValidity() => Promise<boolean>

Reports the validity of the component.

Returns

Type: Promise<boolean>

A promise that resolves to a boolean indicating whether the component is valid.

setFocus() => Promise<void>

Sets focus on the date picker's input. Use this method instead of the global focus().

Returns

Type: Promise<void>

setValidity(validity: ValidityState, validationMessage?: string) => Promise<void>

Sets the validity state of the component.

Parameters

NameTypeDescription
validityValidityState- The validity state to set.
validationMessagestring- An optional validation message to set.

Returns

Type: Promise<void>

A Promise that resolves when the validity state is set.

show() => Promise<void>

Show the calendar modal, moving focus to the calendar inside.

Returns

Type: Promise<void>

willValidate() => Promise<boolean>

Returns a promise that resolves to true if the element will successfully validate, or false otherwise.

Returns

Type: Promise<boolean>

A promise that resolves to a boolean value indicating whether the element will validate.

Dependencies

Depends on

Graph


Built by DHL User Interface Library Team!