Agriculture Design System
Beta
Design System for the Export Service

Date picker

The Date picker component allows users to select a single date via a calendar or text input.

View in FigmaView in StorybookView in Github
import { ... } from '@ag.ds-next/react/date-picker';
Open in Playroom, opens in a new tab
() => {
	const [value, setValue] = React.useState();
	return <DatePicker label="Select date" value={value} onChange={setValue} />;
};

Date picker is a controlled component which means consumers of this component need to manage the state of this component by using the value, onChange and onInputChange props.

For an example of using this component in a form built with react-hook-form and yup, please see the Single-page form template.

Do

  • always display the date format above the text input
  • prefer Australian date format 'dd/mm/yyyy'
  • allow users to navigate dates via the calendar
  • ensure users can enter dates via the calendar or text input
  • Make sure error messages are specific about what input is required.

Don’t

  • hide the date format
  • use international date formats such as USA mm/dd/yyyy
  • hijack built-in keyboard navigation behaviour.

Tracking the input value

The Date picker component has two methods of input:

  1. Typing in a date string (dd/mm/yyyy) via the text input
  2. Selecting a date via the calendar widget

As we do not have any sort of input masking due to accessibility and user experience concerns, it is possible for the user to enter an invalid value via the text input.

In this case, you can use the onInputChange prop to keep track of the user’s input. The value prop can also be set to a string, which represents the value of the text input.

() => {
	// Set the value to a value that the user might think is valid
	const [value, setValue] = React.useState('31/1o/2020');

	const onInputChange = (value) => {
		console.log('onInputChange', value);
		setValue(value);
	};

	const onChange = (date) => {
		console.log('onChange', date);
		setValue(date);
	};

	// This logic is for documentation purposes only. This should be done with `yup` or `zod`.
	const invalid = React.useMemo(() => {
		if (typeof value === 'undefined' || value == '') return false;
		if (value instanceof Date && !isNaN(value.getTime())) return false;
		return true;
	}, [value]);

	return (
		<DatePicker
			label="Select date"
			value={value}
			onChange={onChange}
			onInputChange={onInputChange}
			{...(invalid && {
				invalid: true,
				message: 'Enter a valid date',
			})}
		/>
	);
};

Hint

Use the hint prop to provide help that’s relevant to the majority of users, like how their information will be used, or where to find it.

Don’t use long paragraphs and lists in hint text. Screen readers read out the entire text when users interact with the form element. This could frustrate users if the text is long.

Don’t include links within hint text. While screen readers will read out the link text when describing the field, they will not tell users that the text is a link.

() => {
	const [value, setValue] = React.useState();
	return (
		<DatePicker
			label="Select date"
			hint="Hint text"
			value={value}
			onChange={setValue}
		/>
	);
};

Block

Use the block prop to expand the component to fill the available space.

() => {
	const [value, setValue] = React.useState();
	return (
		<DatePicker label="Select date" value={value} onChange={setValue} block />
	);
};

Invalid

Use the invalid prop to indicate if the user input is invalid.

() => {
	const [value, setValue] = React.useState();
	return (
		<DatePicker
			label="Invalid"
			invalid
			message="Enter a valid date"
			value={value}
			onChange={setValue}
		/>
	);
};

Disabled

Disabled input elements are unusable and can not be clicked. This prevents a user from interacting with the input element until another action is complete.

() => {
	const [value, setValue] = React.useState();
	return (
		<DatePicker
			label="Select date"
			value={value}
			onChange={setValue}
			disabled
		/>
	);
};

Minimum and maximum dates

The minDate property can be used to disable any days before a specific date.

The maxDate property can be used to disable any days after a specific date.

If a valid date is entered using the text input but it falls outside the constrained range, the closest valid date will be used.

() => {
	const [value, setValue] = React.useState();

	const today = new Date();
	const lastWeek = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
	const nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);

	return (
		<DatePicker
			label="Select date"
			minDate={lastWeek}
			maxDate={nextWeek}
			value={value}
			onChange={setValue}
		/>
	);
};

Custom year range

The yearRange prop can be used to change the range of options to display in calendar year select.

() => {
	const [value, setValue] = React.useState();
	const thisYear = new Date().getFullYear();
	const yearRange = { from: thisYear - 2, to: thisYear + 2 };
	return (
		<DatePicker
			label="Select date"
			yearRange={yearRange}
			value={value}
			onChange={setValue}
		/>
	);
};

Changing the date format

The Date picker component allows users to enter dates in various formats. To select the 18th February 2023, a user could input '18/02/2023', '18 Feb 2023', '18th February 2023', or any other supported date format.

When a valid date is typed, on blur, the date will be formatted using the dateFormat prop, which is set to 'dd/MM/yyyy' by default.

To modify the date format, you can change the dateFormat prop to one of these supported date formats:

  • 'dd/MM/yyyy' (e.g. 18/02/2023)
  • 'dd-MM-yyyy' (e.g. 18-02-2023)
  • 'dd MM yyyy' (e.g. 18 02 2023)
  • 'MM/dd/yyyy' (e.g. 02/18/2023)
  • 'MM-dd-yyyy' (e.g. 02-18-2023)
  • 'MM dd yyyy' (e.g. 02 18 2023)
  • 'do MMMM yyyy' (e.g. 8th February 2023)
  • 'do MMM yyyy' (e.g. 8th Feb 2023)
  • 'MMMM do yyyy' (e.g. February 8th 2023)
  • 'MMM do yyyy' (e.g. Feb 8th 2023)
  • 'd MMMM yyyy' (e.g. 8 February 2023)
  • 'd MMM yyyy' (e.g. 8 Feb 2023)
  • 'MMMM d yyyy' (e.g. February 8 2023)
  • 'MMM d yyyy' (e.g. Feb 8 2023)
  • 'dd MMMM yyyy' (e.g. 08 February 2023)
  • 'dd MMM yyyy' (e.g. 08 Feb 2023)
  • 'MMMM dd yyyy' (e.g. February 08 2023)
  • 'MMM dd yyyy' (e.g. Feb 08 2023)
() => {
	const [value, setValue] = React.useState();
	return (
		<DatePicker
			label="Select date"
			value={value}
			onChange={setValue}
			dateFormat="d MMM yyyy"
		/>
	);
};

Changing the allowed date formats

By default, all of the supported date formats are allowed, but should you need to restrict the formats that can be parsed and validated, you can pass in an array of date format strings to the allowedDateFormats prop.

Some applications may find it useful to remove US formats, since an invalid AU date could become a valid US date and cause confusion for users.

Date formats are parsed in order from first to last and stops when a valid date is found. The preferred dateFormat always becomes the first to check, even if omitted in allowedDateFormats.

() => {
	const [value, setValue] = React.useState();

	const onInputChange = (value) => {
		console.log('onInputChange', value);
		setValue(value);
	};

	const onChange = (date) => {
		console.log('onChange', date);
		setValue(date);
	};

	// This logic is for documentation purposes only. This should be done with `yup` or `zod`.
	const invalid = React.useMemo(() => {
		if (typeof value === 'undefined' || value == '') return false;
		if (value instanceof Date && !isNaN(value.getTime())) return false;
		return true;
	}, [value]);

	return (
		<DatePicker
			label="Select date"
			hint="Only short AU formats allowed"
			value={value}
			onChange={onChange}
			onInputChange={onInputChange}
			{...(invalid && {
				invalid: true,
				message: 'Enter a valid date',
			})}
			allowedDateFormats={['dd MM yyyy', 'dd-MM-yyyy']}
		/>
	);
};
  • Date range picker The Date range picker component allows users to select a range of dates via a calendar or text input.