Skip to main content
Version: 10.0.0-next.6

Upgrading from v8 to v10

DayPicker v10 removes the compatibility APIs that were deprecated in v9 and introduces @daypicker/react as the preferred package name. If your app is on v8, you can upgrade directly to v10 by applying the v9 migration changes and the v10 package changes in one pass.

This guide is written for direct v8 to v10 upgrades. If your app is already on v9 and does not use deprecated v9 APIs, use the shorter v10 upgrade guide.

The main migration work is:

  • Replace the package and imports with @daypicker/react.
  • Update CSS imports and custom DayPicker styles.
  • Add onSelect wherever your app passes a selected prop.
  • Replace removed navigation, focus, event, component, formatter, label, hook, utility, and TypeScript aliases.

Upgrade checklist

Most apps can migrate in this order:

  1. Upgrade the package: install @daypicker/react and update imports.
  2. Update CSS imports and styles: replace v8 CSS imports, CSS variables, class names, and styles keys.
  3. Add onSelect when using selected: make controlled selections explicit.
  4. Replace navigation boundary props: move from from* and to* props to startMonth, endMonth, and hidden.
  5. Update custom components: replace renamed or removed component slots.
  6. Update formatters, labels, and tests: return strings from formatters and update ARIA label overrides or assertions.
  7. Replace removed props, hooks, aliases, and types: remove APIs that v9 kept only for compatibility.

If your app wraps DayPicker in a shared Calendar or DatePicker component, update that wrapper first, then check the screens that use it.

1. Upgrade the package

The recommended v10 package name is @daypicker/react. While v10 is in prerelease, install the next tag:

npm remove react-day-picker
npm install @daypicker/react@next

The react-day-picker package name remains available in v10 for compatibility, but use @daypicker/react for upgraded code.

- import { DayPicker } from "react-day-picker";
+ import { DayPicker } from "@daypicker/react";

In v8, locale objects were commonly imported from date-fns/locale. In v10, you can import them from @daypicker/react/locale:

- import { es } from "date-fns/locale";
+ import { es } from "@daypicker/react/locale";

If your app installed date-fns only because v8 required it as a peer dependency or for DayPicker locale objects, you can remove it after moving those locale imports. Keep date-fns if your app uses it directly, for example for formatting, parsing, or date calculations outside DayPicker.

npm remove date-fns

2. Update CSS imports and styles

Replace the v8 bundled CSS import:

- import "react-day-picker/dist/style.css";
+ import "@daypicker/react/style.css";

If you import the CSS module, update that import path as well:

- import classNames from "react-day-picker/dist/style.module.css";
+ import classNames from "@daypicker/react/style.module.css";

The default CSS and the rendered markup changed after v8. If you only import DayPicker's default CSS and do not override it, updating the CSS import path may be enough. If your app has custom CSS selectors, CSS variables, classNames, or styles, review them carefully.

Common style updates:

  • CSS variables are now scoped under .rdp-root. Move overrides there if they were previously set on :root or .rdp.
  • The old day element is now day_button; the old cell element is now day.
  • Class names for several UI elements and day states changed.
  • Deprecated v8 compatibility keys were removed from classNames and styles.

Example class name prop update:

<DayPicker
classNames={{
- day_disabled: "day-disabled",
+ disabled: "day-disabled",
}}
/>

Example day cell and button update:

<DayPicker
classNames={{
- cell: "day-cell",
+ day: "day-cell",
- day: "day-button",
+ day_button: "day-button",
}}
/>

Example CSS selector update:

-.rdp-day_selected {
+.rdp-selected {
font-weight: bold;
}

-.rdp-cell {
+.rdp-day {
padding: 0;
}

-.rdp-day {
+.rdp-day_button {
border-radius: 999px;
}
Class name changes from v8

3. Add onSelect when using selected

When you pass selected, DayPicker expects you to handle selection changes with onSelect. Add state in your component and pass the state setter or a custom handler.

+ const [selected, setSelected] = useState<Date | undefined>(undefined);

<DayPicker
mode="single"
selected={selected}
+ onSelect={setSelected}
/>

The same rule applies to mode="multiple" and mode="range":

const [range, setRange] = useState<DateRange | undefined>();

<DayPicker mode="range" selected={range} onSelect={setRange} />;

If you only need to mark days visually and do not want DayPicker to manage a selection mode, use custom modifiers instead of selected.

4. Replace navigation boundary props

The old navigation boundary props were deprecated in v9 and removed in v10. Replace them with startMonth, endMonth, and hidden.

Replace year boundaries:

<DayPicker
- fromYear={2010}
- toYear={2021}
+ startMonth={new Date(2010, 0)}
+ endMonth={new Date(2021, 11)}
/>

Replace month boundaries:

<DayPicker
- fromMonth={new Date(2010, 0)}
- toMonth={new Date(2021, 11)}
+ startMonth={new Date(2010, 0)}
+ endMonth={new Date(2021, 11)}
/>

Replace date boundaries:

<DayPicker
- fromDate={new Date(2010, 11, 3)}
+ startMonth={new Date(2010, 11)}
+ hidden={{ before: new Date(2010, 11, 3) }}
/>
<DayPicker
- toDate={new Date(2010, 11, 3)}
+ endMonth={new Date(2010, 11)}
+ hidden={{ after: new Date(2010, 11, 3) }}
/>

Use both startMonth or endMonth and hidden when you need to limit navigation and hide individual days outside the allowed range.

5. Update custom components

If you use the components prop, update custom component names and props.

Navigation icons now use one Chevron component:

<DayPicker
components={{
- IconRight: MyRightIcon,
- IconLeft: MyLeftIcon,
+ Chevron: (props) => {
+ if (props.orientation === "left") {
+ return <ChevronLeftIcon {...props} />;
+ }
+ return <ChevronRightIcon {...props} />;
+ },
}}
/>
Component changes from v8

6. Update formatters, labels, and tests

Formatters now return strings. If a v8 formatter returned a React element, move the React rendering into a custom component.

<DayPicker
formatters={{
- formatCaption: (month) => <strong>{format(month, "LLLL y")}</strong>,
+ formatCaption: (month) => format(month, "LLLL y"),
}}
/>

Use a custom component when you need React markup:

<DayPicker
formatters={{
formatCaption: (month) => format(month, "LLLL y"),
}}
components={{
CaptionLabel: ({ children, ...props }) => (
<span {...props}>
<strong>{children}</strong>
</span>
),
}}
/>

Rename formatter and label aliases:

DayPicker's ARIA labels changed for accessibility. Update label overrides, translations, and tests that query buttons by accessible name.

Update test selectors as needed:

- screen.getByRole("button", { name: "Go to next month" });
+ screen.getByRole("button", { name: "Go to the Next Month" });

7. Replace removed props, hooks, aliases, and types

Several v8 names still worked in v9 for compatibility. They were removed in v10.

Removed props

For week-based selections, follow the week selection example. For extra DOM event handlers on days, compose around the default DayButton in a custom component.

Removed hooks and internal providers

The v8 custom component guide exposed several hooks and providers that are no longer part of the public API. If your app imported any of them, replace that code while migrating custom components.

Removed utility aliases

Removed TypeScript and exported names

If you use TypeScript, replace deprecated v8 type names with the shorter current names.

- import type { DayPickerDefaultProps } from "@daypicker/react";
+ import type { PropsBase } from "@daypicker/react";
TypeScript and exported name changes from v8

Useful search patterns

Use these patterns to find the most common v8 code that needs review:

rg "react-day-picker/dist/style|react-day-picker/dist/style.module|fromDate|toDate|fromMonth|toMonth|fromYear|toYear"
rg "selected=|initialFocus|onWeekNumberClick|onDayKeyUp|onDayKeyPress|onDayPointerEnter|onDayPointerLeave|onDayTouch"
rg "day_selected|day_disabled|day_today|day_range_|cell|table|tbody|head_cell|nav_button"
rg "IconLeft|IconRight|IconDropdown|DayContent|Caption|HeadRow|Row"
rg "formatMonthCaption|formatYearCaption|labelDay|labelCaption|isMatch|isDateInRange"
rg "DayPickerSingleProps|DayPickerMultipleProps|DayPickerRangeProps|DayPickerDefaultProps|useInput|useNavigation|useDayRender"
rg "useActiveModifiers|useFocusContext|useSelectSingle|useSelectMultiple|useSelectRange|DayPickerProvider|NavigationProvider|FocusProvider"