DateField
DateField is a set of inputs to define a date, accompanied by the DatePicker.

Item | Name | Description |
---|---|---|
A | Container | <DateField /> uses the TextField styles under the hood |
B | <IconButton /> | Used to open the <DatePicker /> |
C | <input /> | An input to enter the desired month |
D | <input /> | An input to enter the desired day |
E | <input /> | An input to enter the desired year |
F | <IconButton /> | Used to clear the date |


Item | Name | Description |
---|---|---|
A | Container | The parent container |
B | <DatePickerHeader /> | The header of the <DatePicker /> |
C | <DatePickerGrid /> | The main content of the <DatePicker /> |

Item | Name | Description |
---|---|---|
A | Container | The parent container |
B | Label | A label to indicate what day the link below it represents |
C | Label | A label to indicate the selected day |
D | <button /> | A <button> to the current day |
E | <button /> | A <button> to the current selected day |
F | <IconButton /> | The button to close the <Datepicker /> rendered on mobile with the <Close /> icon |
G | <IconButton /> | The <button> used to navigate to a previous year. It uses the <DoubleChevronLeft /> icon. |
H | <IconButton /> | The <button> used to navigate to a previous month. It uses the <DoubleChevronLeft /> icon. |
I | Label | A <button> to the selected day |
J | <IconButton /> | The <button> used to navigate to the next month. It uses the <ChevronRight /> icon. |
K | <IconButton /> | The <button> used to navigate to the next year. It uses the <DoubleChevronRight /> icon. |


Item | Name | Description |
---|---|---|
A | Container | The parent container |
B | Label | The day of the week |
C | <DateCell/> | The <button /> to select a day |
D | Today indicator | An underline to indicate the today’s date |

A basic DateField
filter implementation using Formik and Yup to require selection.
Show code
import { Actions, Flex } from '@gusto/workbench';
import { Formik } from 'formik';
import * as Yup from 'yup';
import {
DateField as DateFieldFormik,
Form,
SubmitButton,
} from '@gusto/workbench-formik';
import React from 'react';
export const Basic = () => {
return (
<Formik
initialValues={{
dateOfBirth: '',
}}
validationSchema={Yup.object().shape({
dateOfBirth: Yup.date().required('Date of birth required'),
})}
onSubmit={async values => alert(JSON.stringify(values))}
>
<Form>
<Flex flexDirection="column" maxWidth={550} rowGap={6}>
<DateFieldFormik
name="dateOfBirth"
label="Date of birth"
helperText="(mm/dd/yyyy)"
/>
<Actions>
<SubmitButton>Submit</SubmitButton>
</Actions>
</Flex>
</Form>
</Formik>
);
};
Using Formik and Yup to control the minimum and maximum dates for DateField
.
Show code
import { Actions, Flex } from '@gusto/workbench';
import { Formik } from 'formik';
import * as Yup from 'yup';
import {
DateField as DateFieldFormik,
Form,
SubmitButton,
} from '@gusto/workbench-formik';
import { addYears, formatISO } from 'date-fns';
import React from 'react';
export const MinimumAndMaximumDates = () => {
const today = new Date();
// representation: 'date' omits the time component of the date leaving
// just '1970-01-01' and not '1970-01-01T00:00:00.000Z'
const min = formatISO(today, { representation: 'date' });
const max = formatISO(addYears(today, 1), { representation: 'date' });
return (
<Formik
initialValues={{
startDate: '',
}}
validationSchema={Yup.object().shape({
startDate: Yup.date()
.required('Start date required')
.min(min, 'Start date must be on or after today')
.max(max, 'Start date must be within one year of today'),
})}
onSubmit={async values => alert(JSON.stringify(values))}
>
<Form>
<Flex flexDirection="column" maxWidth={550} rowGap={6}>
<DateFieldFormik
name="startDate"
label="Start date"
helperText="(mm/dd/yyyy)"
min={min}
max={max}
/>
<Actions>
<SubmitButton>Submit</SubmitButton>
</Actions>
</Flex>
</Form>
</Formik>
);
};
Show code
import { DateField } from '@gusto/workbench';
import React from 'react';
export const Uncontrolled = () => {
return <DateField label="Date of birth" helperText="(mm/dd/yyyy)" />;
};
Show code
import { DateField, Flex } from '@gusto/workbench';
import { formatISO } from 'date-fns';
import React from 'react';
export const States = () => {
const today = new Date();
// representation: 'date' omits the time component of the date leaving
// just '1970-01-01' and not '1970-01-01T00:00:00.000Z'
const value = formatISO(today, { representation: 'date' });
return (
<Flex flexDirection="column" rowGap={6}>
<DateField readOnly label="ReadOnly" value={value} />
<DateField disabled label="Disabled" value={value} />
</Flex>
);
};
Name | Type | Default | Description |
---|---|---|---|
id | string | The ID of the input element. | |
label Required | string | Label associated with the input . | |
optionalText | string | Text used to indicate that a field is not required. | |
helperText | ReactNode | A brief description or hint for the input ; can be used to link to an external resource. | |
validationText | ReactNode | Validation message associated with the input . | |
locales | string string[] | Locale code, e.g. ”en” , ”en-US” , or ”fr-FR” . Forwarded to Intl.DateTimeFormat . | |
YearInputProps | object | Props passed to the year input. | |
MonthInputProps | object | Props passed to the month input. | |
DayInputProps | object | Props passed to the day input. | |
onChange | func | Callback triggered when a new date is entered. |
The following testing snippet(s) offer suggestions for testing the component using React Testing Library with occasional help from Jest.
jest.useFakeTimers();jest.setSystemTime(parseISO('2020-09-03'));const user = userEvent.setup({ delay: null });const onSubmit = jest.fn().mockResolvedValue(null);render(<Formik initialValues={{ startDate: '2020-09-15' }} onSubmit={onSubmit}><Form><DateField label="Start date" name="startDate" /><button type="submit">Submit</button></Form></Formik>,);const group = screen.getByRole('group', {name: 'Start date',});const hiddenInput = within(group).getByRole('presentation', {hidden: true,});const [monthInput, dayInput, yearInput] = within(group).getAllByRole('spinbutton');expect(yearInput).toHaveAccessibleName('Year (yyyy)');expect(monthInput).toHaveAccessibleName('Month (mm)');expect(dayInput).toHaveAccessibleName('Day (dd)');const submitButton = screen.getByRole('button', {name: 'Submit',});expect(hiddenInput).toHaveValue('2020-09-15');expect(yearInput).toHaveValue('2020');expect(monthInput).toHaveValue('9');expect(dayInput).toHaveValue('15');expect(yearInput).toBeValid();expect(monthInput).toBeValid();expect(dayInput).toBeValid();await act(async () => user.click(submitButton));expect(onSubmit).toHaveBeenCalledTimes(1);expect(onSubmit).toHaveBeenCalledWith(expect.objectContaining({ startDate: '2020-09-15' }),expect.any(Object),);
- The tap target for all interactive elements are at least 44px X 44px.For more information, see footnote 1,
- Icons and their backgrounds meet the minimum requirements of 3:1 contrast ratio for non-text content and interactions.For more information, see footnote 2,
- All text meets the minimum contrast requirement of 4.5:1.For more information, see footnote 3,
- The calendar in DatePicker follows the accessible grid format of a table to ensure both the keyboard navigation and screen reader experience behaves as expected.For more information, see footnote 4,
- The DatePicker follows the Dialog pattern to allow for an accessible focus trap.For more information, see footnote 5,