• Molecule
  • CORE COMPONENT
  • Taxonomic name: M-DATE-RANGE
  • Extension: FORMS-EXTENDED-A
  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.5.0 (23/03/21)

Date range

For inputing a pair of dates, eg. start and end dates for cover.


Design and usage

For further information about single date entry, see the date input page.

For documentation on date range prior to v4.9.0 see our retired date range documentation. If you are using v4.9.0 or above, please move to using this version of the date range as soon as possible.

Structure

  • Mandatory explanatory text to ensure date range format is inputted correctly into From/To text boxes ie. 'Please enter your dates in the following date format dd/mm/yyyy'.
  • The standard form fields are individual text boxes for manual entry which will automatically format the date as the user types. The placeholders for these fields should read 'From' and 'To' only (or local language equivalent).
  • Single date picker trigger to aid users in their date selection. Replays date selections (From and To) if they have been entered and are valid.
  • Datepicker:

    • Dual month view where screen width allows, otherwise single month view only.
    • Previous/Next chevrons allowing single month navigation.
    • Month and year dropdowns allow for quick navigation to any month or year within the allowed date range.
    • Date buttons for selecting dates.
    • Today's date, indicated on relevant date button via notification blue marker.
    • Bottom actions area: Mandatory - 'Confirm dates' primary and 'Clear' tertiary buttons. Optional - Total Days playback.
    • Clear: Clears all date/s selected.

Errors

  • Displayed above date range field ie. 'Please select a date or date range'.

Accessibility and screen readers

  • Users can choose to enter their dates manually or by using the datepicker.
  • Aria-invalid must be used to indicate when an error has occurred with this element
  • Aria-describedby must be used to link any help, instructional and/or error text with the element/form fields

Non-JS requirements and considerations

  • No datepicker or auto formatting of date entry made available.

Use cases and exception scenarios

  • Date range is only saved if user submits chosen date selection via 'Confirm dates' button.
  • Date picker can be closed by navigating away from the date picker and associated date range fields. Note: Date/s will not be saved in this instance.
  • Component can be configured to:

    • Display the total days selected, indicated both within calendar UI and beside replay fields (below if the text will not fit beside).
    • Allow/prevent the same date from being selected for both starte and end date.
    • Automatically set an end date a given number days, months or years after a selected start date.

Examples

Standard date range

Interactive example

Code example

<fieldset class="m-form-row [ Modifier ]" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__instruction" id="...">...</p>
		<ul class="m-date-range" data-module="m-date-range" data-min="..." data-max="..." >
			<li class="m-date-range__item m-date-range__item--start">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
			<li class="m-date-range__item m-date-range__item--end">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Date range with total number of days selected

Valid date range

Interactive example

Code example

<fieldset class="m-form-row is-valid [ Modifier ]" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__instruction" id="...">...</p>
		<p class="m-form-row__validation-message" id="...">...</p>
		<ul class="m-date-range" data-module="m-date-range" data-min="..." data-max="...">
			<li class="m-date-range__item m-date-range__item--start">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
			<li class="m-date-range__item m-date-range__item--end">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Errored date range

Interactive example

Code example

<fieldset class="m-form-row is-error [ Modifier ]" aria-invalid="true" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__instruction" id="...">...</p>
		<p class="m-form-row__error-message" id="..."><span class="u-hidden--visually">Error: </span>...</p>
		<ul class="m-date-range" data-module="m-date-range" data-min="..." data-max="..." >
			<li class="m-date-range__item m-date-range__item--start">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
			<li class="m-date-range__item m-date-range__item--end">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="..." />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Disabled date range

Interactive example

Code example

<fieldset class="m-form-row is-disabled [ Modifier ]" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__instruction" id="...">...</p>
		<ul class="m-date-range" data-module="m-date-range" data-min="..." data-max="...">
			<li class="m-date-range__item m-date-range__item--start">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="Start date" disabled />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
			<li class="m-date-range__item m-date-range__item--end">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" placeholder="End date" disabled />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Required date range

<fieldset class="m-form-row [ Modifier ]" aria-describedby="...">
	<legend class="a-label">...</legend>
	<div class="m-form-row__content">
		<p class="m-form-row__instruction" id="...">...</p>
		<ul class="m-date-range" data-module="m-date-range" data-min="..." data-max="...">
			<li class="m-date-range__item m-date-range__item--start">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" aria-required="true" placeholder="Start date" />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
			<li class="m-date-range__item m-date-range__item--end">
				<label for="..." class="m-date-range__date">
					<span class="a-label">...</span>
					<input type="text" value="..." id="..." name="..." pattern="..." class="a-date" aria-required="true" placeholder="End date" />
					<span class="m-date-range__ui"></span>
				</label>
			</li>
		</ul>
	</div>
</fieldset>

Development and test

Notes for developers

The inputs must be of type text ensuring a consistent experience for all users. The pattern attribute must be set on both text inputs eg. for DD/MM/YYYY the attibute should have a value of \d{2}\/\d{2}\/\d{4}.

The m-date-range component must have the attributes data-min and data-max, in the format YYYY-MM-DD, set to limit the date pickers to a date range. These values should always be set server side, if they are not present the min date will default to 1901-01-01 and the max date will default to today's date.

When disabling form elements, do not solely rely on the is-disabled class, but ensure that the disabled attribute is also set on the relevant form element or input. If an entire set of form elements is to be disabled, the is-disabled class and disabled attribute should be added directly to the fieldset instead, and not to each individual element within it. However if only one element from the set is disabled, then the class and attribute should be applied to that element only.

Any validation (including server-side) on the input fields must validate against the entry format that has been specified eg. DD/MM/YYYY. If the native form validation needs to be disabled set the novalidate attribute on the form.

To enable the total number of days selected, simply include the class m-date-range--total on the date range component.

Aria usage for errors and help text

To aid screen reader users in completing forms without error and also with understanding and fixing any errors that have occured, some additional aria attributes are now recommended to be applied across all form fields/rows.

All form row help, explanatory text, form row instructions and form row errors must have a unique id assigned to them and be appropriately linked to either the individual form input or the form row using aria-describedby. This ensures that the help text is read out immediately on focus of the form input/fieldset. When there is more that one item that requires referencing within the aria-describedby attribute the id values must be supplied in the form of a space separated list. For example if there is an error with id of 'err1' and help text with id of 'help1' the value for the aria-describedby attribute would be 'err1 help1'.

All inline form error messages should start with the hidden text 'Error: ' so that when read by out by a screen reader it is immediately clear that the text being read is an error message.

All erroring form fields (or fieldset if a group or radios/checkboxes) must have aria-invalid="true" set on them, ensuring that when a user focus' on an errored form field, the field will be announced as invalid, so the user is then aware that there in an issue that requires fixing.

When linking help or errors, or even adding aria-invalid to the markup careful consideration must be taken as to where it is most appropriate to apply the value. The following rules should be used to decide where the attribute(s) should be applied.

  • Single form field - All attributes should be applied directly to that form field
  • Group of form fields but only one in error or help text applies to only one - Apply the attribute(s) to the only field in error or where the help text applies
  • Group of form field where all in error or the help text applies to all - Apply the attribute(s) to the groups surrounding fieldset (form row)

There may situations where more than one of these rules applies to the overall form row for example a date range where the instruction text applies to both fields so should be linked to the fieldset for the date range but one of the two fields is in error so the error should be linked to just that field not to the fieldset.

Important messages

To help those using assistive technologies, make sure that success/error messages which need to be announced to users have their aria attributes updated to role="alert" and/or aria-live="assertive".

Configuration

When using the date range component, additional settings can be set/updated programatically after the initial load. To do this, the function setSettings should be called from the m-date-range element with a JavaScript object containing settings in the same format as below being passed into the function:

Attribute Type Default Description
startValue String null Date must be in the format the user is expected to enter
endValue String null Date must be in the format the user is expected to enter
sameDay Boolean true Set to false if the start and end dates must not be the same
autosetEndDate Boolean false Set to true if when a start date is selected the end date should automatically be set to X days, X months or X years in the future
autosetEndDateValue Array []

Must be set if autosetEndDate is set to true. First value in the array must be 'day', 'month' or 'year'. The second value must be the number to increment by eg.

'autosetEndDate': true,
'autosetEndDateValue': [ 'day', 10 ]
autosetMaxDate Boolean false Set to true if when a start date is selected the maximum end date should automatically be set to X days, X months or X years in the future
autosetMaxDateValue Array []

Must be set if autosetMaxDate is set to true. First value in the array must be 'day', 'month' or 'year'. The second value must be the number to increment by eg.

'autosetEndDate': true,
'autosetMaxDateValue': [ 'day', 10 ]
minDate String null Update the minimum date post load. Date must be in the format 'YYYY-MM-DD'
maxDate String null Update the maximum date post load. Date must be in the format 'YYYY-MM-DD'

For example:

document.addEventListener( 'frameworkready', function () {
	FRAMEWORK.require([ 'blocks/m-date-range' ], function ( mDateRangeModule ) {
		var dateRangeEl = document.querySelector( '#dateInput' ),
			dateRangeInstance = mDateRangeModule.initInstance( dateRangeEl );		dateRangeInstance.setSettings({
			autosetEndDate: true,
			autosetEndDateValue: [ 'month', 3 ],
			sameDay: false,
		});
	});
});

See Interacting with Framework components example for further details on how to safely interact with framework components.

Changing locale settings

The date format and labels within the datepicker can be updated for a particular locale.

en: {
	aDate : {
		locale : 'en-gb',
		format : 'DD/MM/YYYY',
		previousMonth : 'Previous month',
		nextMonth : 'Next month',
		months : [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
		weekdays : [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
		weekdaysShort : [ 'S', 'M', 'T', 'W', 'T', 'F', 'S' ],
		interactionInstruction : 'Use the arrow keys to pick a date',
		triggerLabelSingle : 'Select date',
		confirmLabelSingle : 'Confirm date',
		triggerLabelRange : 'Select dates',
		confirmLabelRange : 'Confirm dates',
		clearLabel : 'Clear',
		totalSelectedSingular : 'Total days selected: <strong>{days} day</strong>',
		totalSelectedPlural : 'Total days selected: <strong>{days} days</strong>',
		yearLabel : 'Year',
		monthLabel : 'Month',
		startDateTitle : 'Set start date',
		endDateTitle : 'Set end date',
	},
},

For more information on this, see our page on how to change locale settings within JavaScript.

Extension component

This component forms part of the 'forms-extended-a' extension and so requires an additional stylesheet to be loaded in order to be used; include the following code in the header of your page to attach the relevant additional stylesheet:

<link media="all" href="./assets/[ theme type ]/[ release version ]/[ organisation ]/[ theme name ]/css/forms-extended-a.css" rel="stylesheet" />

Notes for testers

  • In IE11 the date icon will look fuzzy; this is a rendering issue with the browser when a background is on an element that has rounded corners.
  • The form must have validation in place to catch any errors with the dates entered and present an error message back to the user. This message does not have to be shown real-time, but can appear once the user has attempted to submit the form.
  • Ensure that the field has a correctly associated label; this not only provides context to the field for assistive technology users, but also a larger clickable area to select the field. Clicking / pressing on the label should cause the date field to gain focus.
  • Users should be able to copy and paste if necessary.
  • Highlight today's date and the selected date with clear variation between them
  • Users should be able to easily identify and distinguish between selectable and non-selectable dates, today's date, the selected date and weekends.
  • The calendar should have a clear hover state to help users identify the correct date.
  • For some applications, past dates may need to be disabled.
  • Clickable / tappable area of each day should be an appropriate size.

Classes overview

The following table gives you a quick overview of the CSS classes that can be applied.

Class Outcome Required Applied to Comments
.m-date-range Base style for a date range Yes .m-form-row__content > ul  
.m-date-range--total Modifer to include the total number of days selected along side the date range fields and within the datepicker itself Yes .m-date-range  
.m-date-range__item Base style for a date range input wrapper Yes .m-date-range > li  
.m-date-range__item--start Modifier for the start date wrapper Yes .m-date-range > li:first-child  
.m-date-range__item--end Modifier for the end date wrapper Yes .m-date-range > li:last-child  
.m-date-range__ui Styling for UI elements required for the date range input Yes .m-date-range__item > span:last-child  

Keyboard operations

TAB

Tabbing to an input field should make the input clearly visually different so that the focus point on the page is obvious to the user.

Component releases

  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.5.0 (23/03/21)

Latest update:

  • updated: The disabled dates colour within the datepicker has been updated from #9b9b9b to #b8b8b8, to provide better consistency in the colours used within Framework.
  • updated: Additional aria attributes are now recommended to be applied across all form fields/rows so as to aid screen reader users in completing forms without error and also with understanding and fixing any errors that have occurred.

Full version history

A full history of changes and enhancements detailing all minor and major updates to the component.

View full version history

Want something new in Framework, or to chat about an issue you're having with it?

Contact the team