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
onSelectwherever your app passes aselectedprop. - Replace removed navigation, focus, event, component, formatter, label, hook, utility, and TypeScript aliases.
Upgrade checklist
Most apps can migrate in this order:
- Upgrade the package: install
@daypicker/reactand update imports. - Update CSS imports and styles: replace
v8 CSS imports, CSS variables, class names, and
styleskeys. - Add
onSelectwhen usingselected: make controlled selections explicit. - Replace navigation boundary props:
move from
from*andto*props tostartMonth,endMonth, andhidden. - Update custom components: replace renamed or removed component slots.
- Update formatters, labels, and tests: return strings from formatters and update ARIA label overrides or assertions.
- 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
- Yarn
- pnpm
- Bun
npm remove react-day-picker
npm install @daypicker/react@next
yarn remove react-day-picker
yarn add @daypicker/react@next
pnpm remove react-day-picker
pnpm add @daypicker/react@next
bun remove react-day-picker
bun add @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
- Yarn
- pnpm
- Bun
npm remove date-fns
yarn remove date-fns
pnpm remove date-fns
bun 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:rootor.rdp. - The old
dayelement is nowday_button; the oldcellelement is nowday. - Class names for several UI elements and day states changed.
- Deprecated v8 compatibility keys were removed from
classNamesandstyles.
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
| Old name | New name |
|---|---|
button | button_previous, button_next |
button_reset | button_previous, button_next |
caption | month_caption |
caption_between | Removed |
caption_dropdowns | dropdowns |
caption_end | Removed |
caption_start | Removed |
cell | day |
day | day_button |
day_disabled | disabled |
day_hidden | hidden |
day_outside | outside |
day_range_end | range_end |
day_range_middle | range_middle |
day_range_start | range_start |
day_selected | selected |
day_today | today |
dropdown_icon | chevron |
dropdown_month | months_dropdown |
dropdown_year | years_dropdown |
head | Removed |
head_cell | weekday |
head_row | weekdays |
multiple_months | Removed. Use the data-multiple-months data attribute. |
nav_button | button_previous, button_next |
nav_button_next | button_next |
nav_button_previous | button_previous |
nav_icon | chevron, button_next, button_previous |
row | week |
table | month_grid |
tbody | weeks |
tfoot | footer |
vhidden | Removed |
weeknumber | week_number |
with_weeknumber | Removed. Use the data-week-numbers data attribute. |
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.
| Removed prop | Use instead |
|---|---|
fromMonth | startMonth |
fromYear | startMonth with the first month of that year |
toMonth | endMonth |
toYear | endMonth with the last month of that year |
fromDate | hidden with a before matcher, and optionally startMonth |
toDate | hidden with an after matcher, and optionally endMonth |
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
| v8 component | v10 replacement |
|---|---|
Caption | MonthCaption |
Day | Still available, but interactive days now render a DayButton. |
DayContent | Removed. Use formatDay for text content, or customize DayButton. |
Head | Removed |
HeadRow | Weekdays |
IconDropdown | Removed. Use Chevron. |
IconLeft | Removed. Use Chevron. |
IconRight | Removed. Use Chevron. |
Row | Week |
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:
| Removed API | Use instead |
|---|---|
formatMonthCaption | formatCaption |
formatYearCaption | formatYearDropdown |
labelDay | labelDayButton |
labelCaption | labelGrid |
DayPicker's ARIA labels changed for accessibility. Update label overrides, translations, and tests that query buttons by accessible name.
| Label | Old label | New label |
|---|---|---|
labelDayButton | 21st November (Monday) | Monday, November 21st, 2024Monday, November 21st, 2024, selectedToday, November 21st, 2024 |
labelPrevious | Go to previous month | Go to the Previous Month |
labelNext | Go to next month | Go to the Next Month |
labelWeekNumber | Week nr. ## | Week ## |
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
| Removed prop | Use instead |
|---|---|
fromDate | hidden={{ before: date }} and optionally startMonth |
toDate | hidden={{ after: date }} and optionally endMonth |
fromMonth | startMonth |
toMonth | endMonth |
fromYear | startMonth={new Date(year, 0)} |
toYear | endMonth={new Date(year, 11)} |
initialFocus | autoFocus |
onWeekNumberClick | A custom WeekNumber component |
onDayKeyUp | A custom DayButton component |
onDayKeyPress | A custom DayButton component |
onDayPointerEnter | A custom DayButton component |
onDayPointerLeave | A custom DayButton component |
onDayTouchCancel | A custom DayButton component |
onDayTouchEnd | A custom DayButton component |
onDayTouchMove | A custom DayButton component |
onDayTouchStart | A custom DayButton component |
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 API | Use instead |
|---|---|
useInput | Manage the input value, selected date, and visible month in your component state. See the input fields guide. |
useNavigation | useDayPicker, which exposes goToMonth, nextMonth, and previousMonth. |
useActiveModifiers | useDayPicker and its getModifiers helper. |
useDayRender | A custom Day or DayButton component. |
useFocusContext | A custom DayButton component with the focus handlers your app needs. |
useSelectSingle, useSelectMultiple, useSelectRange | Controlled selected and onSelect props, or select from useDayPicker inside a custom component. |
DayPickerProvider, RootProvider, NavigationProvider, FocusProvider, SelectSingleProvider, SelectMultipleProvider, SelectRangeProvider | Do not import DayPicker providers directly. Render DayPicker and use custom components or useDayPicker. |
Removed utility aliases
| Removed API | Use instead |
|---|---|
isMatch | dateMatchModifiers |
isDateInRange | rangeIncludesDate |
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
| Removed name | Use instead |
|---|---|
Caption | MonthCaption |
Button | Use your own button, or customize PreviousMonthButton and NextMonthButton. |
CaptionDropdowns | Removed |
CaptionNavigation | Removed |
CaptionProps | MonthCaptionProps |
HeadRow | Removed |
Row | Week |
RowProps | WeekProps |
ButtonProps | Use React.ComponentProps<"button">, PreviousMonthButtonProps, or NextMonthButtonProps depending on the button. |
DayPickerSingleProps | PropsSingle |
DayPickerMultipleProps | PropsMulti |
DayPickerRangeProps | PropsRange |
DayPickerDefaultProps | PropsBase, or a more specific prop type |
DaySelectionMode | Mode |
Modifier | string |
InternalModifier | DayFlag or SelectionState |
SelectSingleEventHandler | PropsSingle["onSelect"] |
SelectMultipleEventHandler | PropsMulti["onSelect"] |
SelectRangeEventHandler | PropsRange["onSelect"] |
DayPickerProviderProps | Removed |
UseInputOptions | Removed with useInput |
UseInputValue | Removed with useInput |
InputDayPickerProps | Removed with useInput |
InputProps | Use React.ComponentProps<"input"> |
NavigationContextValue | Removed. Use useDayPicker |
FocusContextValue | Removed |
RootContext | Removed |
SelectSingleContextValue | Removed |
SelectMultipleContextValue | Removed |
SelectRangeContextValue | Removed |
SelectSingleProviderProps | Removed |
SelectMultipleProviderProps | Removed |
SelectRangeProviderProps | Removed |
useNavigation | useDayPicker |
useDayRender | A custom Day or DayButton component |
useActiveModifiers | useDayPicker and its getModifiers helper |
useFocusContext | Removed |
useInput | Manage input state in your component |
useSelectSingle | Controlled selected and onSelect, or useDayPicker |
useSelectMultiple | Controlled selected and onSelect, or useDayPicker |
useSelectRange | Controlled selected and onSelect, or useDayPicker |
ContextProvidersProps | Removed |
DayLabel | typeof labelDayButton |
NavButtonLabel | typeof labelNext or typeof labelPrevious |
WeekdayLabel | typeof labelWeekday |
WeekNumberLabel | typeof labelWeekNumber |
DayClickEventHandler | DayEventHandler<React.MouseEvent> |
DayFocusEventHandler | DayEventHandler<React.FocusEvent | React.KeyboardEvent> |
DayKeyboardEventHandler | DayEventHandler<React.KeyboardEvent> |
DayMouseEventHandler | DayEventHandler<React.MouseEvent> |
DayPointerEventHandler | DayEventHandler<React.PointerEvent> |
DayTouchEventHandler | DayEventHandler<React.TouchEvent> |
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"