Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting the display month to a value outside of the selectable range causes the DayButton component to not render #2671

Open
anthony-bonta-gaf-energy opened this issue Jan 22, 2025 · 4 comments

Comments

@anthony-bonta-gaf-energy
Copy link

anthony-bonta-gaf-energy commented Jan 22, 2025

To reproduce

  1. Set both startMonth and endMonth to a range value
  2. Set the month prop to a value outside of the startMonth and endMonth
  3. Render the component

If you’re unable to easily reproduce this bug, consider opening a support thread to discuss it further.

import { useMemo, useState } from 'react';
import { addYears, startOfYear, endOfYear } from 'date-fns';
import { DayPicker } from 'react-day-picker';

export function App() {
  const today = useMemo(() => new Date(), []);
  const oldDays = useMemo(() => addYears(today, -10), [today]);
  const [month, setMonth] = useState(oldDays);
  const yearsFuture = endOfYear(addYears(today, 2));
  const yearsAgo = startOfYear(addYears(today, -2));

  return (
    <DayPicker
      captionLayout='dropdown'
      endMonth={yearsFuture}
      month={month}
      onMonthChange={setMonth}
      mode='single'
      hideNavigation
      required={false}
      selected={oldDays}
      startMonth={yearsAgo}
      style={{ backgroundColor: 'white' }}
    />
  );
}

CodeSandbox: https://playcode.io/2231858

Actual Behavior

The table cells render for the month and the actual months in the drop down are correctly disabled. However, the buttons in each cell do not render at all.

Note that you can still work around this by selecting a year in the range.

Expected Behavior

I would expect a set of buttons to be rendered even if they're outside of the range. The use case for this is a range of +-1 year and the user selected a value over a year ago and we want to reflect that in the selection and make them update it.

Screenshots

Image

@rodgobbi
Copy link
Contributor

Hi @anthony-bonta-gaf-energy
Even if the day buttons would be displayed outside the valid range, they would be displayed disabled, besides all the month options being disabled, which can feel confusing for a user, and in the behavior you described it's expected that the user should select an year that is already selected by default in the dropdown to enable the calendar for selection, therefore the steps to put the DayPicker in a valid month is very hidden.
Is there a specific reason for this use case?
Wouldn't it be better to programmatically put the DayPicker in a state where the user can start selecting valid dates?

@gpbl
Copy link
Owner

gpbl commented Jan 23, 2025

I agree that this is an unexpected state of the calendar.

Should DayPicker handle this case, or should the developer take care of the values passed in? Should the days be clickable - or should we render the closest available month?

@anthony-bonta-gaf-energy
Copy link
Author

anthony-bonta-gaf-energy commented Jan 23, 2025

@rodgobbi the use case for this is as follows:

  1. Calendar is set so that only the current year, previous year, and next year are valid dates to update to.
  2. User enters a value 2 years ago which was valid at the time.
  3. User needs to update this value today
  4. User goes back to the form and views the calendar but now it's empty and they don't see the previous date they entered.

They can correct it by selecting a year in the range, but it would be nice to show a read-only view of the previous date they selected. This is a data flow issue. When the data comes in, the drop downs correctly reflect the old date, but it doesn't show the day.

@gpbl The main concern with trying to auto correct this is that you'll be lying to the user about the value that is actually set. If data is flowing in a single direction, as it should be, the value coming into the calendar is a valid date but needs to be corrected. I want to be transparent with the user about what the current value is and force them to tell me what to update it to. If you show them the latest month, many will get confused and think the currently selected day is not what they originally chose.

@rodgobbi
Copy link
Contributor

Agree with @anthony-bonta-gaf-energy, better not have any side effects caused by mounting the DayPicker.

For me, it's still a valid approach to show the outside days as disabled, need to check @gpbl's thoughts.
For the question "Should the days be clickable", the days would be at least disabled because they are outside the valid range.
For "should we render the closest available month?", by detault the DayPicker does that, but in the example in this issue the month is explicitly set, so the DayPicker uses it, which is correct IMO. After selecting a valid month through the dropdown the DayPicker goes back to a visible month.

@anthony-bonta-gaf-energy I have the feeling that just displayeing the day picker all disabled wouldn't be providing enough clarity to the users. The day picker only got to the inconsistent state because the month prop is being explicitly set to an invalid value, which the day picker wouldn't get there with the normal flow.

If the valid date range changes when loading the form, and the previous selected date is invalid, this could be considered an invalid input.
What do you think of displaying the day picker starting from a valid month, as it is the expected behavior, but displaying an error message / validation error for the input saying the previously selected date is not valid anymore?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants