Skip to content

DateField

DateField is a set of inputs to define a date, accompanied by the DatePicker.
Breakdown of the input and its individual components.
Anatomy of a DateField
Anatomy of the DateField component
ItemNameDescription
AContainer<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
Different spacing and annotated sizes of the componentes pieces.
A blueprint of DateField
Breakdown of the date picker and its individual components.
Anatomy of DatePicker, and it’s subcomponents, that opens when the calendar IconButton is selected
Anatomy of the DateField component
ItemNameDescription
AContainerThe parent container
B<DatePickerHeader />The header of the <DatePicker />
C<DatePickerGrid />The main content of the <DatePicker />
Breakdown of the header of the date picker and its components.
Anatomy of the DatePickerHeader
Anatomy of the DateField component
ItemNameDescription
AContainerThe parent container
BLabelA label to indicate what day the link below it represents
CLabelA 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.
ILabelA <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.
Different spacing and annotated sizes of the heading of the blueprint pieces.
Blueprint of a DatePickerHeader
Breakdown of the components grid showing month dates.
Anatomy of a DatePickerGrid
Anatomy of the DateField component
ItemNameDescription
AContainerThe parent container
BLabelThe day of the week
C<DateCell/>The <button /> to select a day
DToday indicatorAn underline to indicate the today’s date
Different spacing and annotated sizes of the grid components pieces.
Blueprint of a DatePickerGrid

A basic DateField filter implementation using Formik and Yup to require selection.

Date of birth

(mm/dd/yyyy)

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.

Start date

(mm/dd/yyyy)

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>
  );
};
Date of birth

(mm/dd/yyyy)

Show code
import { DateField } from '@gusto/workbench';
import React from 'react';

export const Uncontrolled = () => {
  return <DateField label="Date of birth" helperText="(mm/dd/yyyy)" />;
};
ReadOnly
Selected date: Friday, May 26, 2023
Disabled
Selected date: Friday, May 26, 2023
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>
  );
};
React props
NameTypeDefaultDescription
id  stringThe ID of the input element.
label  RequiredstringLabel associated with the input.
optionalText  stringText used to indicate that a field is not required.
helperText  ReactNodeA brief description or hint for the input; can be used to link to an external resource.
validationText  ReactNodeValidation message associated with the input.
locales  stringstring[]Locale code, e.g. ”en”, ”en-US”, or ”fr-FR”. Forwarded to Intl.DateTimeFormat.
YearInputProps  objectProps passed to the year input.
MonthInputProps  objectProps passed to the month input.
DayInputProps  objectProps passed to the day input.
onChange  funcCallback triggered when a new date is entered.

The following testing snippet(s) offer suggestions for testing the component using React Testing LibraryExternal link with occasional help from JestExternal link.

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),
);
  1. The tap target for all interactive elements are at least 44px X 44px.For more information, see footnote 1,
  2. 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,
  3. All text meets the minimum contrast requirement of 4.5:1.For more information, see footnote 3,
  4. 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,
  5. The DatePicker follows the Dialog pattern to allow for an accessible focus trap.For more information, see footnote 5,