Date picker

Lets users select a date through a calendar without the need to manually type it in a field.

Props

type
calendar | input
Sets the date picker type. 'calendar' shows a calendar popup, 'input' shows just a date input.
Defaults to calendar.
name
string
Name of the date field.
value
string
Value of the calendar date.
error
boolean
Sets the input to an error state.
Defaults to false.
min
string
Minimum date value allowed.
max
string
Maximum date value allowed.
relative
string
This property has no effect and will be removed in a future version.
disabled
boolean
Disables the date picker.
Defaults to false.
testId
string
Sets a data-testid attribute for automated testing.
width
string
Sets the width of the date picker input.
size
default | compact
Sets the size of the date picker. 'compact' reduces height for dense layouts.
Defaults to default.
mt, mr, mb, ml
none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl
Apply margin to the top, right, bottom, and/or left of the component.

Events

onChange
(event: Event) => void
_change
CustomEvent
Examples

Ask a user for a birthday

const [birthdate, setBirthdate] = useState<Date | undefined>(undefined);
<GoabxFormItem label="What is your date of birth?">
      <GoabxDatePicker
        name="birthdate"
        type="input"
        value={birthdate}
        onChange={(e) => setBirthdate(e.value)}
      />
    </GoabxFormItem>
birthdate: Date | undefined;

  onDateChange(event: { value: Date }) {
    this.birthdate = event.value;
  }
<goabx-form-item label="What is your date of birth?">
  <goabx-date-picker
    name="birthdate"
    type="input"
    [value]="birthdate"
    (onChange)="onDateChange($event)">
  </goabx-date-picker>
</goabx-form-item>
const datePicker = document.getElementById("birthdate");
datePicker.addEventListener("_change", (e) => {
  console.log("Selected date:", e.detail.value);
});
<goa-form-item version="2" label="What is your date of birth?">
  <goa-date-picker version="2" name="birthdate" type="input" id="birthdate"></goa-date-picker>
</goa-form-item>

The date picker component handles accessibility automatically. Ensure the form-item label clearly describes what date is being requested.

Confirm a change

const [open, setOpen] = useState(false);
  const [effectiveDate, setEffectiveDate] = useState<Date | undefined>(new Date());

  const onChangeEffectiveDate = (detail: GoabDatePickerOnChangeDetail) => {
    setEffectiveDate(detail.value as Date);
  };
<GoabxButton onClick={() => setOpen(true)}>Save and continue</GoabxButton>

      <GoabxModal
        heading="Address has changed"
        open={open}
        onClose={() => setOpen(false)}
        actions={
          <GoabButtonGroup alignment="end">
            <GoabxButton type="secondary" size="compact" onClick={() => setOpen(false)}>
              Undo address change
            </GoabxButton>
            <GoabxButton type="primary" size="compact" onClick={() => setOpen(false)}>
              Confirm
            </GoabxButton>
          </GoabButtonGroup>
        }>
        <GoabContainer type="non-interactive" accent="filled" padding="compact" width="full">
          <GoabText as="h4" mt="none" mb="s">Before</GoabText>
          <GoabText mt="none">123456 78 Ave NW, Edmonton, Alberta</GoabText>
          <GoabText as="h4" mt="none" mb="s">After</GoabText>
          <GoabText mt="none" mb="none">881 12 Ave NW, Edmonton, Alberta</GoabText>
        </GoabContainer>
        <GoabxFormItem label="Effective date" mt="l">
          <GoabxDatePicker
            onChange={onChangeEffectiveDate}
            name="effectiveDate"
            value={effectiveDate}
          />
        </GoabxFormItem>
      </GoabxModal>
open = false;
  effectiveDate = new Date();

  toggleModal(): void {
    this.open = !this.open;
  }

  onChangeEffectiveDate(event: GoabDatePickerOnChangeDetail): void {
    this.effectiveDate = event.value as Date;
  }
<goabx-button (onClick)="toggleModal()">Save and continue</goabx-button>

<goabx-modal [open]="open" (onClose)="toggleModal()" heading="Address has changed" [actions]="actions">
  <goab-container type="non-interactive" accent="filled" padding="compact" width="full">
    <goab-text as="h4" mt="none" mb="s">Before</goab-text>
    <goab-text mt="none">123456 78 Ave NW, Edmonton, Alberta</goab-text>
    <goab-text as="h4" mt="none" mb="s">After</goab-text>
    <goab-text mt="none" mb="none">881 12 Ave NW, Edmonton, Alberta</goab-text>
  </goab-container>
  <goabx-form-item label="Effective date" mt="l">
    <goabx-date-picker (onChange)="onChangeEffectiveDate($event)" name="effectiveDate" [value]="effectiveDate"></goabx-date-picker>
  </goabx-form-item>
  <ng-template #actions>
    <goab-button-group alignment="end">
      <goabx-button type="secondary" size="compact" (onClick)="toggleModal()">
        Undo address change
      </goabx-button>
      <goabx-button type="primary" size="compact" (onClick)="toggleModal()">
        Confirm
      </goabx-button>
    </goab-button-group>
  </ng-template>
</goabx-modal>
const modal = document.getElementById('change-modal');
const openBtn = document.getElementById('open-modal-btn');
const undoBtn = document.getElementById('undo-btn');
const confirmBtn = document.getElementById('confirm-btn');
const datePicker = document.getElementById('effective-date');

let effectiveDate = new Date();
datePicker.setAttribute('value', effectiveDate.toISOString());

openBtn.addEventListener('_click', () => {
  modal.setAttribute('open', 'true');
});

undoBtn.addEventListener('_click', () => {
  modal.removeAttribute('open');
});

confirmBtn.addEventListener('_click', () => {
  modal.removeAttribute('open');
});

modal.addEventListener('_close', () => {
  modal.removeAttribute('open');
});

datePicker.addEventListener('_change', (e) => {
  effectiveDate = e.detail.value;
});
<goa-button version="2" id="open-modal-btn">Save and continue</goa-button>

<goa-modal version="2" id="change-modal" heading="Address has changed">
  <goa-container type="non-interactive" accent="filled" padding="compact" width="full">
    <goa-text as="h4" mt="none" mb="s">Before</goa-text>
    <goa-text mt="none">123456 78 Ave NW, Edmonton, Alberta</goa-text>
    <goa-text as="h4" mt="none" mb="s">After</goa-text>
    <goa-text mt="none" mb="none">881 12 Ave NW, Edmonton, Alberta</goa-text>
  </goa-container>
  <goa-form-item version="2" label="Effective date" mt="l">
    <goa-date-picker version="2" id="effective-date" name="effectiveDate"></goa-date-picker>
  </goa-form-item>
  <div slot="actions">
    <goa-button-group alignment="end">
      <goa-button version="2" type="secondary" size="compact" id="undo-btn">
        Undo address change
      </goa-button>
      <goa-button version="2" type="primary" size="compact" id="confirm-btn">
        Confirm
      </goa-button>
    </goa-button-group>
  </div>
</goa-modal>

Reset date picker field

const [date, setDate] = useState<Date | undefined>();

  const setNewDate = (value: Date | undefined) => {
    setDate(value);
  };

  function setValue() {
    const d = new Date();
    d.setDate(d.getDate() - 7);
    setDate(d);
  }

  function clearValue() {
    setDate(undefined);
  }
<GoabxFormItem label="Date Picker">
        <GoabxDatePicker
          name="item"
          value={date}
          onChange={(e) => setNewDate(e.value as Date)}
          mb="xl"
        />
      </GoabxFormItem>

      <GoabButtonGroup mt="xs" alignment="start">
        <GoabxButton onClick={setValue}>
          Set Value
        </GoabxButton>
        <GoabxButton onClick={clearValue}>Clear Value</GoabxButton>
      </GoabButtonGroup>
item: Date | undefined = undefined;

  onChange(event: { value: Date | undefined }): void {
    this.item = event.value;
  }

  setValue(): void {
    const d = new Date();
    d.setDate(d.getDate() - 7);
    this.item = d;
  }

  clearValue(): void {
    this.item = undefined;
  }
<goabx-form-item label="Date Picker">
  <goabx-date-picker
    (onChange)="onChange($event)"
    name="item"
    [value]="item">
  </goabx-date-picker>
</goabx-form-item>

<goab-button-group alignment="start" mt="xs">
  <goabx-button (onClick)="setValue()">Set Value</goabx-button>
  <goabx-button (onClick)="clearValue()">Clear Value</goabx-button>
</goab-button-group>
const datePicker = document.getElementById("date-picker");
const setValueBtn = document.getElementById("set-value-btn");
const clearValueBtn = document.getElementById("clear-value-btn");

datePicker.addEventListener("_change", (e) => {
  console.log("Date changed:", e.detail.value);
});

setValueBtn.addEventListener("_click", () => {
  const d = new Date();
  d.setDate(d.getDate() - 7);
  datePicker.setAttribute("value", d.toISOString());
});

clearValueBtn.addEventListener("_click", () => {
  datePicker.removeAttribute("value");
});
<goa-form-item version="2" label="Date Picker">
  <goa-date-picker version="2" id="date-picker" name="item"></goa-date-picker>
</goa-form-item>

<goa-button-group alignment="start" mt="xs">
  <goa-button version="2" id="set-value-btn">Set Value</goa-button>
  <goa-button version="2" id="clear-value-btn">Clear Value</goa-button>
</goa-button-group>

Types

Use the calendar date picker for selecting dates relative to today, or when seeing the day of week is helpful.
Use the input date picker for known dates far in the past or future, such as a birthday.

Other

Indicate unavailable dates to help users avoid invalid selections.

The form item automatically associates the label with the input for screen readers, ensuring your form is accessible.

Use a form item wrapper on all inputs to add a label, helper text, error message, and more.

States

Submit

When you must disable a button or input:

  • Provide nearby text explaining what needs to happen first
  • Consider showing the element enabled with validation on submit instead
  • Use aria-describedby to link the disabled element to explanatory text
Don't disable buttons or inputs without explaining why. Disabled controls can be confusing and users may not understand why they can't interact with an element.
All GoA Design System components are built to meet WCAG 2.2 AA standards. The following guidelines provide additional context for accessible implementation.

No accessibility-specific guidelines have been documented for this component yet.