Hacker0x01 / react-datepicker

A simple and reusable datepicker component for React
https://reactdatepicker.com/
MIT License
8.07k stars 2.24k forks source link

Current day highlighted across all months #2930

Open qasimalyas opened 3 years ago

qasimalyas commented 3 years ago

Describe the bug Current day is selected across all months which is bad for UX. It can cause confusion making it look like two dats might have been selected. This has been raised multiple times but no real solution exists to disabled the highlighting. https://github.com/Hacker0x01/react-datepicker/issues/2376, https://github.com/Hacker0x01/react-datepicker/issues/2456

To Reproduce Steps to reproduce the behavior:

  1. Go to https://reactdatepicker.com/ where you'll see the default calendar open image
  2. Click to go to next month image
  3. You'll see day 4 being highlighted
  4. This occurs for all months followed

Expected behavior There shouldn't be any highlight dates.

Screenshots See above

Desktop (please complete the following information):

Applicable on all browsers and devices

Additional context This is confusing and disabling keyboard navigation seems to be the only option but that breaks accessibility. Ideally this shouldn't be happening or at the very least be an optional opt-in.

relwiwa commented 3 years ago

The highlighting is necessary to know where keyboard focus is. @martijnrusschen Probably it would be a good idea to change the styling to make it more different from the selected day styling?

A workaround is to change the styling via this class: .react-datepicker__day--keyboard-selected

qasimalyas commented 3 years ago

I don't have anything against keyboard focus - which is absolutely necessary for usability & accessibility. But I don't think this is about that. The issue is this:

  1. todays date is 19 may 2021
  2. As a user I click to open the date picker
  3. 19th is selected by default
  4. I click next month
  5. The same date 19th is selected

I could be missing something but I don't see how this is useful. It adds to the confusion as I haven't even selected a date yet but it makes it seems so. If I change keyboard specific styling then that will change point 5 but will also affect any keyaboard navigation - which I don't want to do.

I think the solution would be to exclude highlighting dates like this from future months. If its necessary for whatever reason then make it optional.

relwiwa commented 3 years ago
  1. The same date 19th is selected

This is not correct. The day is not "selected", because in the input field is still 19 may 2021, not 19 june 2021. There is a (probably too) subtle styling difference between the selected date and the highlighted date

annika-linke commented 3 years ago

This Problem is also appearing in the range datepicker. The Range gets highlighted in every month (even on the official docs page https://reactdatepicker.com/#example-date-range).

I found a workaround that fixes the problem for me. I will just assign my own classes and disable the problem causing styles.

// value : string
// startDate?: Date
// endDate?: Date

const activeClass = (date: Date) => {
    const activeClass =
      date.getTime() === new Date(value).getTime()
        ? 'date-picker-field__active'
        : undefined;

    const startActiveClass =
      startDate && date.getTime() === startDate.getTime()
        ? 'date-picker-field__active--start'
        : undefined;

    const endActiveClass =
      endDate && date.getTime() === endDate.getTime()
        ? 'date-picker-field__active--end'
        : undefined;

    const rangeColor =
      startDate &&
      endDate &&
      date.getTime() >= startDate.getTime() &&
      date.getTime() <= endDate.getTime()
        ? 'date-picker-field__range'
        : undefined;

    // classNames from 'classnames'
    return classNames(
      rangeColor,
      startActiveClass,
      endActiveClass,
      activeClass,
    );
  };

return (
   <DatePicker
        {...someAttributes}
        dayClassName={activeClass}
    />
);
.date-picker-field__range {
  background-color: $pickerSelectionRangeColor !important;
}

.date-picker-field__active--start {
  background-color: $pickerSelectionRangeColor !important;
}

.date-picker-field__active--end {
  background-color: $pickerSelectionRangeColor !important;
}

.date-picker-field__active {
  background-color: $pickerSelectedColor !important;
}

.react-datepicker__day--in-selecting-range,
.react-datepicker__month-text--in-selecting-range,
.react-datepicker__quarter-text--in-selecting-range,
.react-datepicker__year-text--in-selecting-range {
  background-color: transparent;
  color: $pickerTextColor;
}
alex-streza commented 3 years ago

@annika-linke your solution is great but I don't think it allows for updating the range while hovering to select a new date as in the example below.

image image

The bug occurs when selecting a range and then editing either start or end dates

image

Even though I'm not hovering and the mouse is outside the calendar element react-datepicker__day--in-selecting-range class is added to every day in other months that is included within the original interval.

image

image

annika-linke commented 3 years ago

@alex-streza that wasnt a dealbreaker for me, but its true! For me it was a better solution than the bug. It still needs to be handled in react-datepicker though...

kidroca commented 3 years ago

I think a similar issue is happening for the month picker as well - the selected month is highlighted for different years Even when the date is disabled

ezgif com-gif-maker

kidroca commented 3 years ago

Related #3051

mpiorowski commented 3 years ago

Guys, try setting the selected value to sth, or null. Then this problem dissaper. I encounter similar probolem trying to set up datepicker for multiple day selection (not range). So from my another issue -> "I was able to do it using highlightDates option. On onChange concat or filter array of dates, set selectedDate to null, and style everything so that selected dates wont be visible. Now your highlightDates is the new value of datepicker."

as-zlynn-philipps commented 3 years ago

Had the same issue, had to basically remove the styles for the class @relwiwa mentioned. I don't really get why it's showing what day the keyboard would tab to, when the focus outline clearly illustrates that once it's tabbed to. Maybe I'm missing something. 🤷‍♂️

Here's the SCSS I used if anyone's interested:

.react-datepicker__day--keyboard-selected {
  background-color: inherit;
  color: inherit;

  &:hover {
    background-color: #f0f0f0;
  }
}
bhavin-a commented 3 years ago

This is happening in the date range example as well.

  1. Select the start date
  2. Navigate to the previous month, a couple of dates are highlighted.

I've tried disabling keyboard navigation as well but still having this issue. Any idea?

In the below screenshot, I have selected 29 Jan, 2014 but navigating to the previous month is highlighting 29 Dec, 2013 as well 😕

image

Am I missing something? This is really confusing 😭

blackPantherOS commented 2 years ago

The bad dates (one day difference) maybe Qt5 bug again. Few days ago all Plasma widget date is wrong date highlighted,

snax4a commented 2 years ago

Im also having this issue, when we are switching months, the focus should stay on arrow buttons so i don't understand why its keyboard selecting same day number

JohnDDuncanIII commented 2 years ago

@annika-linke @Bhavin789 per-https://github.com/Hacker0x01/react-datepicker/issues/2872#issue-853667583, I was able to fix this in my range datepicker by manually passing disabledKeyboardNavigation/minDate={null}

https://user-images.githubusercontent.com/9257785/158491032-b78f959d-6956-4a80-aa56-09d685787c46.mov

first example in vid is the default minDate (i.e., not passing the prop down at all) second example is minDate={null} behavior

mohanbalasubramani commented 2 years ago

I think a similar issue is happening for the month picker as well - the selected month is highlighted for different years Even when the date is disabled

ezgif com-gif-maker

Peter Velkov you got any solution for this?

omer-alon commented 2 years ago

I think a similar issue is happening for the month picker as well - the selected month is highlighted for different years Even when the date is disabled ezgif com-gif-maker

Peter Velkov you got any solution for this?

Having the same issue too It would be great if I could disable the highlighted month

kidroca commented 2 years ago

I think a similar issue is happening for the month picker as well - the selected month is highlighted for different years Even when the date is disabled

Peter Velkov you got any solution for this?

Having the same issue too It would be great if I could disable the highlighted month

@mohanbalasubramani, @omer-alon No we just live with it the way it is, for our use case it rarely happens and no one notices but QA

Seijinx commented 2 years ago

I think a similar issue is happening for the month picker as well - the selected month is highlighted for different years Even when the date is disabled ezgif com-gif-maker

Peter Velkov you got any solution for this?

I used this workaround in CSS

.react-datepicker__day--keyboard-selected,
.react-datepicker__month-text--keyboard-selected,
.react-datepicker__quarter-text--keyboard-selected,
.react-datepicker__year-text--keyboard-selected {
  border-radius: inherit;
  background-color: inherit;
  color: inherit;
}
.react-datepicker__month--selected,
.react-datepicker__month--in-selecting-range,
.react-datepicker__month--in-range,
.react-datepicker__quarter--selected,
.react-datepicker__quarter--in-selecting-range,
.react-datepicker__quarter--in-range {
  border-radius: 0.3rem;
  background-color: #216ba5;
  color: #fff;
}
knoefel commented 2 years ago

Just integrated react-datepicker into a new project and stumbled upon this bug. Are there any news when this will get resolved? I think from an UI perspective it's critical!! Thanks in advance!!

theresa-de-ocampo commented 2 years ago

I want to remove just the default highlights whenever the user hasn't selected a date yet. Adding the following isn't working for me since it also removes the highlight when the user actually chose a date. Any workaround?

.react-datepicker__day.react-datepicker__day--keyboard-selected {
    background-color: inherit;
    color: inherit;
    font-weight: inherit;
}
luddensdesir commented 2 years ago

This is happening because of the &--keyboard-selected style and this part of the code getclassnames in day.jsx

I made some css changes that fix this issue. If anyone wants I can make a pull request for it.

ghost commented 2 years ago

@luddens please!

luddensdesir commented 2 years ago

Alright, I made a PR here:

https://github.com/Hacker0x01/react-datepicker/pull/3782

modified colors

seong-ji-sue commented 1 year ago

The issue can be resolved by using the 'disabledKeyboardNavigation' option.

rajesh2020in commented 1 year ago

The issue can be resolved by using the 'disabledKeyboardNavigation' option.

Thanks.

date Issue has resolved. but in time if i navigate to other month / day, time is auto selected as same as selected time.

example : selected date and time - 23-09-2023 21:30

when i navigate to January 2024 time auto highlighted as 21:30 (as Selected date time)

image

tfazekas commented 9 months ago

To limit the highlight mechanism only for the selected date (or other specific dates) you can use Highlight dates with custom class names and ranges combining with the onMonthChange prop.

const [displayedMonth, setDisplayedMonth] = useState<null | number>(null);

const highlightedDates = useMemo(() => {
    const highlights = [];
    // if selected date is in the same month, as the displayed month, or no display month
    if (selected && (selected.getMonth() === displayedMonth || displayedMonth === null)) {
      highlights.push(new Date(rest.selected));
    }

   // optional: push specific dates other than the selected date here  (for example `openToDate`)

    if (highlights.length) {
      return [
        {
          'react-datepicker__day--highlighted-custom': highlights
        }
      ];
    }

    return null;
  }, [selected, displayedMonth]);

Use the props like this:

   <DateInput
       {...yourProps}
       {...(highlightedDates && { highlightDates: highlightedDates })} 
       onMonthChange={(date) => setDisplayedMonth(date.getMonth())}
     />

Don't forget to apply css properties for the highlighted-custom class:

.react-datepicker__day--highlighted-custom {
    color: white;
    background-color: orange;
}
paduck1408 commented 9 months ago

In case of DateRangePicker, I passed minDate={null} into my endDate datePicker and it works, based on @JohnDDuncanIII. Didn't add disabledKeyboardNavigation

rezamajidi commented 4 months ago

Everyone talks about passing minDate={null} for the endDate but then in that case you can have an endDate before the startDate. It shouldn't count as a fix for this problem

laraepcosta commented 1 month ago

I found a solution to this problem by setting the background-color in CSS to transparent for all selecting-range dates. Then, I applied the desired hover color using a function that determines if the date is between the day hovered over and the day before the startDate, or the day hovered over and the day after the endDate. This function then adds an "is-true" to the class name.

Here is the CSS I used:

.my-custom-calendar .react-datepicker__day--in-selecting-range {
  background-color: transparent !important;
}

.my-custom-calendar .react-datepicker__day--in-selecting-range.is-true {
  background-color: #e9e0f6 !important;
}

In my app, I manage the hover state using the useState hook

ps. I'm using the classnames lib import classNames from "classnames";

const [dayOnHover, setDayOnHover] = useState<Date | null>(null);

const activeClassOnStartDate = (date: Date) => {
  const isBetweenNewRange =
    startDate && dayOnHover
      ? date.getTime() <= startDate.getTime() - 1 &&
        date.getTime() >= dayOnHover.getTime()
        ? true
        : false
      : false;

  return classNames("react-datepicker__day--in-selecting-range", {
    "is-true": isBetweenNewRange,
  });
};

const activeClassOnEndDate = (date: Date) => {
  const isBetweenNewRange =
    endDate && dayOnHover
      ? date.getTime() >= endDate.getTime() + 1 &&
        date.getTime() <= dayOnHover.getTime()
        ? true
        : false
      : false;

  return classNames("react-datepicker__day--in-selecting-range", {
    "is-true": isBetweenNewRange,
  });
};

For each date picker, I set the day hovered state with onDayMouseEnter and reset it with onMonthMouseLeave.

On the startDate datepicker I use activeClassOnStartDate for the dayClassName property

And on the endDate datepicker I use activeClassOnEndDate for the dayClassName property

ps. The disabledKeyboardNavigation is not necessary with this solution

DatePicker for the startDate

<DatePicker
  {...otherAttributes}
  selected={startDate}
  selectsStart
  startDate={startDate}
  endDate={endDate}
  dayClassName={activeClassOnStartDate}
  onDayMouseEnter={(dateOnHover) => {
    setDayOnHover(dateOnHover);
  }}
  onMonthMouseLeave={() => {
    setDayOnHover(null);
  }}
/>

DatePicker for the endDate


<DatePicker
  {...otherAttributes}
  selected={endDate}
  selectsEnd
  startDate={startDate}
  endDate={endDate}
  minDate={startDate}
  maxDate={new Date()}
  dayClassName={activeClassOnEndDate}
  onDayMouseEnter={(dateOnHover) => {
    setDayOnHover(dateOnHover);
  }}
  onMonthMouseLeave={() => {
    setDayOnHover(null);
  }}
/>

Here is the calendar in the selected month image

On the previous month image

And the hover works just fine when selecting outside the range you alredy picked.