Skip to content

datetime2 component migration

Adi Dahiya edited this page Nov 2, 2022 · 15 revisions

To prepare for the Popover changes coming in Blueprint v5.0, we're providing "v2" variants of @blueprintjs/datetime and @blueprintjs/timezone components which use Popover2 instead of Popover. Migrate to these now in order to ensure a smooth migration path.

These components are available in the new @blueprintjs/datetime2 package:

Replacement for DateInput, with notable changes:

  • The component now uses Popover2 instead of Popover, so there are some DOM layout changes and the type of popoverProps has changed to Popover2Props. Two popover wrapper elements have been removed, and the popover interactions are now attached directly to the InputGroup. See Popover2 migration for more info.
  • The controlled value and uncontrolled defaultValue API have changed to use an ISO string instead of a JS Date value. ISO strings are also returned in the onChange callback. This allows the component to be more explicit about timezones.
  • ⭐ NEW: fill prop matches behavior of <Popover2 fill> (moved from popoverProps={{ fill }}, which no longer supports that key).
  • The component optionally embeds a TimezoneSelect inside the input which allows the user to change the timezone of the selected datetime. This can be enabled with the new prop showTimezoneSelect={true}.
  • Key event handlers have been updated to use non-deprecated KeyboardEvent APIs. This may affect testing code which relies on setting event.which key codes to simulate keyboard behavior. Tests should be updated to use the event.key property instead.
  • The component is now a function component instead of a class component. This has implications for Enzyme tests suites which attempt to get a handle on the <DateInput> instance with .find(DateInput).
    • In general, we do not recommend Enzyme for testing with Blueprint components or React in general; prefer react-testing-library
    • If you must keep those tests working which rely on <DateInput> being a class component, you can use a Jest mock like this.

API changes

Before:

const [date, setDate] = React.useState(new Date());

return (
  <DateInput value={date} onChange={setDate} />
);

After:

const [date, setDate] = React.useState(new Date().toISOString());
// alternatively, you can specify the string explicitly, like "2022-07-14T15:01:08.859Z" or "2022-07-14T11:01:08.859-4:00"

return (
  <DateInput value={date} onChange={setDate} />
);

Migration utilities

For automated migrations to the new string-based API, we provide some adapter utility functions to convert your data and callbacks to use the updated types. You can test out these adapters in this code sandbox. Here's a code example:

import { DateInput2, DateInput2MigrationUtils } from "@blueprintjs/datetime2";
import React, { useCallback, useState } from "react";

function Example() {
  const [dateValue, setDateValue] = useState<Date | null>(null);
  const handleChange = useCallback(setDateValue, [setDateValue]);
  const formatDate = useCallback((date: Date) => date.toLocaleString(), []);
  const parseDate = useCallback((str: string) => new Date(str), []);

  return (
    <DateInput2
      formatDate={formatDate}
      onChange={DateInput2MigrationUtils.onChangeAdapter(handleChange)}
      parseDate={parseDate}
      placeholder="M/D/YYYY"
      value={DateInput2MigrationUtils.valueAdapter(dateValue)}
    />
  );
}

Rendered DOM changes

- <span class="bp4-popover-wrapper">
-   <span aria-haspopup="true" class="bp4-popover-target">
-     <div class="bp4-input-group">
-       <input type="text" autocomplete="off" placeholder="JS Date" class="bp4-input" value="7/14/2022">
-     </div>
-   </span>
- </span>
+ <div class="bp4-input-group bp4-date-input bp4-popover2-target">
+   <input type="text" autocomplete="off" placeholder="MM/dd/yyyy" class="bp4-input" value="07/14/2022">
+   <!-- optional timezone select here -->
+ </div>

Replacement for DateRangeInput, with notable changes:

  • The component now uses Popover2 instead of Popover, so there are some DOM changes and the type of popoverProps has changed to Popover2Props. Two popover wrapper elements have been removed, and the popover interactions are now attached directly to the InputGroup. See Popover2 migration for more info.

Rendered DOM changes

- <span class="bp4-popover-wrapper">
-   <span aria-haspopup="true" class="bp4-popover-target">
-     <div class="bp4-control-group">
-         <div class="bp4-input-group">...</div>
-         <div class="bp4-input-group">...</div>
-     </div>
-   </span>
- </span>
+ <div aria-haspopup="true" class="bp4-control-group bp4-date-range-input bp4-popover2-target">
+     <div class="bp4-input-group">...</div>
+     <div class="bp4-input-group">...</div>
+ </div>

Replacement for TimezonePicker, with notable changes:

  • Component name has changed to better match semantic naming patterns of other Blueprint components:
    • It is a specialized select component, not a picker component.
    • Note that we use the term "picker" to refer to DatePicker / DateRangePicker, which do not rely on popovers.
  • 🔥 BREAKING: New component name means that CSS class names have changed:
    • .bp4-timezone-picker.bp4-timezone-select
    • .bp4-timezone-picker-popover.bp4-timezone-select-popover
    • ℹ️ remember to always use the $bp-ns variable in Sass and the Classes constants in TS/JS when referencing Blueprint class names
  • 🔥 BREAKING: Component uses Select2 instead of Select, so there are some DOM changes — see Select2 migration for more info.
  • ⭐ NEW: fill prop matches behavior of <Select2 fill>.
  • 🔥 BREAKING: The type of popoverProps has changed to Popover2Props, which means a few properties have changed. See Popover2 migration for more info.
    • popover positioning may be specified with "placement" or "position"
    • boundary has been replaced with rootBoundary, which better matches popper.js' definition of what a "boundary" is
    • modifiers type has changed
    • targetClassName and targetTagName properties have been removed
  • Timezone display formatting has changed slightly to use more legible location labels rather than IANA codes. Support for displaying IANA codes still remains, but it is now more explicit via TimezoneDisplayFormat.CODE (equivalent to TimezoneDisplayFormat.NAME, which is now deprecated).
    • These location labels are used in the default composite display format:

      Before: TimezonePicker After: TimezoneSelect
      image image
    • ⭐ NEW: long names like "Hawaii-Aleutian Standard Time" are now available with TimezoneDisplayFormat.LONG_NAME

  • 🔥 BREAKING: The type of TimezoneMetadata has changed to reflect the data available from date-fns-tz. The getTimezoneMetadata utility function is still available in the public API, but its return type has changed. Inspect the new types to update your usage of this API.

Rendered DOM changes

- <span class="bp4-popover-wrapper bp4-timezone-picker">
-   <span aria-haspopup="true" class="bp4-popover-target">
-     <div class="">
-       <button type="button" class="bp4-button">
-         ...
-       </button>
-     </div>
-   </span>
- </span>
+ <div
+   aria-controls="listbox-1"
+   aria-expanded="false"
+   aria-haspopup="listbox"
+   class="bp4-timezone-select bp4-popover2-target"
+   role="combobox"
+ >
+   <button type="button" class="bp4-button">
+     ...
+   </button>
+ </div>
Clone this wiki locally