react-spectrum icon indicating copy to clipboard operation
react-spectrum copied to clipboard

useCalendarCell equates "outside of visible range" with "disabled".

Open rglazebrook opened this issue 2 years ago โ€ข 4 comments

๐Ÿ› Bug Report

useCalendarCell returns true for isDisabled when calendar dates are outside the visible date range (i.e. isOutsideVisibleRange is true), but are still within minValue and maxValue, and are not passed an isDisabled prop. This is preventing click/press events on those dates.

๐Ÿค” Expected Behavior

You should be able to click on dates that are outside the "visible" date range of the current month, but aren't otherwise marked as unavailable or disabled. This would mirror the behavior in the native HTML5 datepicker.

๐Ÿ˜ฏ Current Behavior

Dates outside of the visible date range are being marked as isDisabled internally. This prevents any of the click/press events from firing. Based on the description of isDisabled , I believe this could be a bug.

E.g., If I'm looking at June 2022, July 1st can be made visible, but cannot be made clickable (because it is being marked internally as isDisabled). However, July 1st is enabled and clickable from the July 2022 calendar.

๐Ÿ’ Possible Solution

Dates outside of the current month should not be marked as isDisabled. From a styling perspective, we still have isOutsideVisibleRange to work with, and the dates would still be properly disabled if they fell outside of the min/max values.

If this is expected behavior and changing this would constitute a breaking change, adding a calendar-level prop something like disableOutsideVisibleRange and defaulting it to true would provide users a viable workaround.

๐Ÿ”ฆ Context

I am trying to replicate behavior found in the standard HTML5 datepicker, wherein selecting a date from the previous/next month, if it is visible in the calendar, is possible. My goal is to not lose features when switching over.

๐Ÿ’ป ~~Code~~ GIF Sample

Here's a GIF of my implementation of useDatepicker, useCalendar, etc: aria-dateinput-cant-click

And here's an example of the same behavior with a standard HTML5 <input type="date" />: html-dateinput-clicking

๐ŸŒ Your Environment

Software Version(s)
react-spectrum 3.0.0
Browser Chrome
Operating System macOS Big Sur

๐Ÿงข Your Company/Team

N/A

๐Ÿ•ท Tracking Issue (optional)

N/A

rglazebrook avatar Jun 22 '22 18:06 rglazebrook

One problem with this design is the dates still look disabled visually (grayed out). If they are interactive, they'd need to meet WCAG contrast minimums as well to be accessible. Not to say we shouldn't support more control here though.

devongovett avatar Jun 22 '22 19:06 devongovett

I'm also running into this with my implementation. From an a11y perspective, I think determining how to style the out of range but enabled options would be left to the user, but I agree they should be clickable. They are focusable, however focusing will trigger a focus of the next page.

garand avatar Jun 27 '22 14:06 garand

I think this would need to be opt-in but does seem like something we should support. I see three main use cases:

  1. Dates outside current month are hidden (possible currently).
  2. Visible but greyed out and non-interactive (possible currently).
  3. Visible and interactive (not possible).

Reason it must be opt-in is so that we don't have hidden and/or low contrast elements that are interactive unintentionally.

Behaviorally, the easiest thing to do would be to make them simply non-disabled and focusable. However, the current behavior when navigating with a keyboard is to switch to the next/previous month when navigating to a date outside the current month. Would this be what expected or would you only expect to switch months when navigating to a date fully outside the view?

devongovett avatar Jun 29 '22 21:06 devongovett

I would expect the current focus behavior but be able to click dates outside of the current month.

garand avatar Jun 29 '22 23:06 garand

I support this change, at least a configuration prop to follow the behaviour of the native HTML5 datepicker will be very welcome!

ingro avatar Oct 10 '22 16:10 ingro

I face the same problem while trying to implement a DateRangePicker based on the RangeCalendar. Is there currently any status update or workaround?

Drogglbecher avatar Dec 08 '22 10:12 Drogglbecher

any updates?

GregorGabric avatar Apr 02 '23 21:04 GregorGabric

Want to introduce react-aria-components and replace couple of standalone libraries in the app our company builds, started from <Calendar /> and <DatePicker />, yet ran into the same issue.

For <DatePicker /> one could probably live with the issue, but here's different use case, where having next / previous month days disabled / hidden feels wrong. We have events screen with calendar in the sidebar - having only current month days clickable seems weird. Here's the screen, hope this gives more context for the problem:

image

arzatskis avatar Apr 21 '23 07:04 arzatskis

I'm working on this but I have many questions. Maybe some of you can help me determine what the right behavior is.

Basically it gets really weird when you have multiple months visible at a time, because the same date might be displayed twice.

image
  • Would you expect the selection state to show twice like in the above image? Or only on the first one (which is inside its month)?
  • When clicking on one of these dates, where should focus go? Is it weird that clicking on the second copy of a date might actually send keyboard focus to the first one?
  • If this was a RangeCalendar, what should we show as the selection state if the selected range spans across multiple months (see below video)? It can look like dates are selected twice, or that there are breaks in the selected range. Would we should the same dates selected twice? Only one of them?

https://github.com/adobe/react-spectrum/assets/19409/3e4f55e6-40a0-44d6-a209-c78f2374756e

  • Even with a single month, the range selection behavior is really weird (see below video). As you hover over days, we focus the cell so that keyboard and mouse input can be used together, but for cells outside the month this causes the month to change (as discussed above for keyboard navigation).

https://github.com/adobe/react-spectrum/assets/19409/c5c1216e-76b4-4b53-8162-7ddabfd8a41f

Any thoughts on the above issues would be appreciated.

devongovett avatar Jun 20 '23 00:06 devongovett

@devongovett yes, multiple calendars may look weird, but it's not related to this change we are discussing here. Just implemented date range picker last week at work - at the moment dates are highlighted multiple times (I hide them in production code, made them dimmed / visible for screenshot): image

There are data- CSS selectors for every state, so developers can style things how they like (hide, show different color for selected out-of-month day etc.)

Focus seems work ok at the moment (I'd expect focus to stay on cell I've just clicked)

arzatskis avatar Jun 20 '23 15:06 arzatskis

@arzatskis so you are hiding the dates that are outside the month (e.g. in the middle), but showing the ones outside the visible range (e.g. at the ends)? I'm curious why not just hide both in that case? And if you're hiding them, then this issue doesn't really apply to you right?

devongovett avatar Jun 20 '23 18:06 devongovett

Sorry for confusion - that was quick/incorrect sketch to show that it's already happening, not related to change we are discussing here.

My use case, where I believe displaying and allowing clicking on outside dates are:

  • Date input popover image

  • Calendar widget in the sidebar image

(using different calendar lib. just to achieve this, would like to switch to react-aria-components just as we did for date range inputs ๐Ÿ˜„)

arzatskis avatar Jun 21 '23 07:06 arzatskis

๐Ÿ‘†๐Ÿป This is also what I want. I want users to be able to click the final dates of May and the beginning dates of July.

brandonpittman avatar Jun 21 '23 07:06 brandonpittman

I get that, but we cannot simply ignore the edge cases. The issues I've pointed out surface because of this change, so we need to have answers to them before we can proceed.

devongovett avatar Jun 21 '23 15:06 devongovett

We don't personally use the multi-month view in the range picker (primarily single calendar picker here), but I would think the overlapping days between visible shouldn't be visible to not duplicate focus / functionality. The ones at the edges however do make sense to me. I'm no UX expert though, so perhaps we have someone that can chime in there?

As far as the drag goes, can it be kept consistent with the current behavior without navigating between months unexpectedly? Allow someone to drag the end of a month that overlaps with the beginning of the following, without switching over to the next month. Or, if it does automatically switch, switch on drag end / change rather than just on hover? If someone wanted to select between months the current patterns (selecting start date -> navigating to next month [either via keyboard or next / prev button] -> selecting end date) both work.

omacranger avatar Jun 26 '23 13:06 omacranger

The team discussed this again at length today, and we decided that there are too many UX problems with enabling dates outside the month / visible range. Therefore, we are unfortunately not planning to support it at this time. Mainly we feel that this UX only works for one specific case (a single month non-range calendar) out of many that we support, and that exposing an override would open us up to additional behavioral/accessibility issues in many other cases. I'll go into detail about our reasoning below.

  • In multi-month calendars, multiple "instances" of the same date may be visible at a time, and it's not clear which one should show the selection style or receive focus. Showing only one of them as selected might be unexpected too โ€“ if you clicked on the other one, selection/focus would not go to the element you clicked on.
  • We could theoretically refactor the way our state is managed to keep track of each instance of a date separately so that the selection would be preserved on the one you actually interacted with, but this would be pretty complicated. Even then, the UX might be unexpected when switching pages, because you may then want to see the other instance as selected (if the one you clicked on went out of view).
  • We considered restricting this to only single month calendars. However, with range calendars, we would still need to either differentiate between instances of the same date, or differentiate between hover and focus. Right now, the range selection is entirely driven by the focused date. When you hover over a date, we focus that date, and you can use your arrow keys to move the focus as well. Focus and hover are one and the same. When a date becomes focused, we switch the month so it comes into view. This works well for keyboard, but if we enable hovering over a date that is outside the current month, then it will switch months on hover which would be unusual. We would need to maintain a separate hover vs focused date, and it would be unclear which one should win (what selected range to display).
  • At this point, that only leaves non-range single month calendars. One common problem with displaying dates outside the current month is that it is tempting to "dim" them visually. Chrome does this, as shown in the original issue. However, this is not accessible. Interactive elements must have sufficient contrast so that users can see them. Some of the other designs in this thread would be fine as they are not dimmed, but others may be tempted to follow Chrome's lead on this. On it's own this is not a strong enough reason (React Aria is a style-less library after all), but we don't want to encourage bad practices either.

Even with all of these drawbacks, we still considered adding a prop to override the behavior for this narrow use case. However, we are worried that adding such a prop that is broken in many of the other scenarios outlined above would lead to additional issues in the future, either from folks expecting it to work in all cases, or with future behaviors we might implement. Therefore, the costs to adding such a feature outweighed the benefits in our estimation.

Our recommendation UX-wise would be to either dim the dates outside the month and keep them non-interactive, or hide them completely. We think this is the best experience overall, and the one that can be the most consistent between different calendar views. This is also how many common calendar experiences such as Airbnb and Google Flights work.

We are going to close this issue for now. If anyone has additional brilliant ideas to solve these issues you are welcome to share them, but we don't feel comfortable ignoring these problems and adding a feature for such a narrow use case.

devongovett avatar Jul 20 '23 23:07 devongovett