gpbl / react-day-picker

DayPicker is a customizable date picker component for React. Add date pickers, calendars, and date inputs to your web applications.
https://daypicker.dev
MIT License
5.88k stars 702 forks source link

toDate and fromDate are not working as expected #2075

Closed Siignature closed 1 month ago

Siignature commented 3 months ago

Description

I'm encountering an issue with the toDate and the fromDate props of react-day-picker where it seems to behave more like toMonth and fromMonth. When setting a specific date as a limit using toDate, I expect the calendar to restrict the selection of days only up until that specific date. However, what happens is that the calendar allows any day within the month of the provided limit date to be selected, not just up to the exact date. Same case for fromDate.

Expected Behavior

I expect that when using the toDate prop to set a date limit on the calendar, only days up to that specific date (inclusive) should be selectable. For example, if toDate is set to 2024-03-16T23:00:00.000Z, no day after March 16th, 2024, should be selectable.

Actual Behavior

When I set a limit using toDate, the calendar allows days beyond the provided limit date to be selected, up until the end of the month of the limit date. For example, if toDate is set to 2024-03-16, days after March 16th, 2024, are selectable, up until the end of March.

Steps to Reproduce

  1. Add the toDate prop to the DayPicker component with a specific value (e.g., new Date(2024, 2, 16)).
  2. Try selecting a day on the calendar after the provided date.

Possible Solution

A possible solution might involve reviewing how selectable dates are calculated in the context of the toDate prop to ensure that the exact day's time of the specified date is being respected, rather than allowing additional days within the same month to be selected.

Your Environment

dmvdven commented 1 month ago

Just encountered these problems when using the fromDate and toDate props.

I'm using fromDate and toDate with React Day Picker version 9.0.0-beta.3, where "toDate" already seems to work. The days after the toDate are not displayed in the calendar. Great!

But this doesn't seem te work for fromDate yet.

gpbl commented 1 month ago

Thanks for raising this up... I'm actually unsure what is the expected behavior by setting fromDate, toDate? I don't believe these props make much sense. If you want to hide the days, you can use the hidden or the disabled props:

<DayPicker disabled={{ before: someDate }} />

What is your use case? I'm really tempted to remove these props.

dmvdven commented 1 month ago

I'm creating a "birthdate" field where users can enter their birthdate. In my use case, the target audience is between 16 and 80 years old, so I want the birth years to be limited to between 1944 and 2008 (this changes dynamically based on the current year).

The "hidden" prop doesn't seem suitable for this use case because it only hides specific dates, not entire year ranges. If this prop allowed {{ before: someDate }} and {{ after: someDate }}, I think the "fromDate" and "toDate" options would indeed become obsolete.

Regarding your suggestion about disabling days, I believe that this is not the best option for my use case. Showing many years of disabled dates is in my opinion not optimal for the user experience.

gpbl commented 1 month ago

@dmvdven see this sandbox as example: https://codesandbox.io/p/devbox/rdp9-hidden-days-rc86d5?file=%2Fsrc%2FApp.tsx%3A1%2C1-24%2C1

const minAge = 16;
const maxAge = 89;

export default function App() {
  const fromMonth = addYears(new Date(), -1 * maxAge);
  const toMonth = addYears(new Date(), -1 * minAge);
  return (
    <DayPicker
      captionLayout="dropdown"
      mode="single"
      defaultMonth={toMonth}
      fromMonth={fromMonth}
      toMonth={toMonth}
      disabled={[{ before: fromMonth }, { after: toMonth }]}
    />
  );
}

You can toggle disabled with hidden to hide the days - yet, I think that hiding them provides a worse UX, e.g. when at the start of the month.

We will then remove fromDate, toDate for v9.

@Siignature to fix your issue, you should use the disabled prop as in the example above.