-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add possibility to disable multiple date intervals in Calendar
and Datepicker
components
#2793
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
Add possibility to disable multiple date intervals in Calendar
and Datepicker
components
#2793
Conversation
@@ -60,6 +61,15 @@ export function CalendarCell({state, currentMonth, ...props}: CalendarCellProps) | |||
|
|||
let nativeDate = useMemo(() => date.toDate(state.timeZone), [date, state.timeZone]); | |||
let formatted = useMemo(() => dateFormatter.format(nativeDate), [dateFormatter, nativeDate]); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if I should move this code somewhere else, it depends on the disabled & selected state, as well as the cell's ref 🤔
const previousCell = currentCell?.parentElement?.previousElementSibling?.firstElementChild; | ||
const nextCell = currentCell?.parentElement?.nextElementSibling?.firstElementChild; | ||
|
||
const isCellDisabled = (cell: Element): boolean => cell?.classList.value.includes('is-disabled'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is the ideal way to verify if the sibling cell is disables, I am open to suggestions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better to use state if you can
I see there is already a function on the state for checking if the date is disabled
https://github.com/adobe/react-spectrum/pull/2793/files#diff-fd8b93994dbea995798535e4fb0d1323e12e7290667d0329b10ab4209db5199fR199
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and there are functions for getting the next day and the previous day I believe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens for this if we're on the first cell or the last cell of a grid? just undefined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use state for the current cell, but from what I've seen, each cell has its own state. You can either control the state for the whole calendar or the state for one cell. I don't think you can use the states of two adjacent cells simultaneously (though I might be wrong) 🤔
There are functions for focusing the next day or calculating the next date. However, what I need is a function that returns the state of the next cell (or the effect of the state, like having a certain class), and I didn't find something like that (again, I might be wrong).
And about the last questions: yes, in that case, it returns undefined. Should I add a fallback to false (... || false
), so that the API would be more consistent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, can't you check it like this?
state.isCellDisabled(props.date.subtract({days: 1}))
state.isCellDisabled(props.date.add({days: 1}))
code pulled from just below the link I shared, isPreviousVisibleRangeInvalid
which I feel like you might just be able to use that function directly?
I'm quite sure we do not want to look in the dom for this state though. My suggestion may not pan out, I'm not super familiar with this code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see now what you meant and you're 100% right. Thank you, I've updated this logic and it's way cleaner now 👌 7d9032c
/** Callback that is called for each date of the calendar. If it returns true, then the date is disabled. */ | ||
isDateDisabled?: (date: DateValue) => boolean, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open discussion for team, how do we feel about this api versus say something like disabledDates
? Was mulling over this and I feel like the current api is more flexible especially when it comes to disabling a range of dates or specifying a special filter (like even days).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@LFDanLu is comparing this to the disabledKeys API
given that a collection will always be available in memory and you can change the disabledkeys based on what is shown, that API is fine for collections
however, for dates, there is always an infinite number of dates and you don’t have the ability to track what month or week or whatever is currently being shown, so you can’t update the disabled dates props
therefore a callback makes the most sense to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we go for disabledDates
it would not be possible to make all the weekends disabled (for example). So, I think isDateDisabled
is more flexible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed something, and I'm not sure the answer, but right now if you use the arrow keys to keyboard navigate the available dates, when you reach a disabled date, it looks like focus gets lost. Either we need to skip disabled dates or we need to keep the focus ring visible even on disabled dates
It used to be that focus just couldn't move past the boundaries of min/max dates. But we do need to be able to traverse these disabled dates.
I'm leaning towards them being navigable with a visible focus ring because:
You could technically provide a disable range of infinite dates, and we wouldn't necessarily know that, so we can't just skip to the next non-disabled date
Up/Down arrow navigating becomes less predictable
The `isDateDisabled` callback prop makes it possible to disable custom dates from the `Calendar`. It is being called for each date and if it returns `true`, the date cell is disabled. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind updating the wording in the rest of the docs files (Calendar, RangeCalendar, DatePicker) to match DateRangePicker's change?
The `isDateDisabled` callback prop makes it possible to disable custom dates from the `Calendar`. It is being called for each date and if it returns `true`, the date cell is disabled. | |
The `isDateDisabled` callback prop acts like a filter function. It is called for each visible date and if it returns `true`, the date cell is disabled. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated it in all files 👌
Hey we're in the midst of determining how the disabled ranges should work with keyboard navigation. Does your product team have any opinions or insight? |
From what I see, the AirBnb datepicker keeps the focus on disabled dates: http://react-dates.github.io/react-dates/?path=/story/drp-day-props--with-some-blocked-dates |
Haha, yeah, we were looking at AirBnb as well as the Chrome native input. One issue with navigating them is that they are disabled dates, but they are focusable, so we're following up with Accessibiliy if those "disabled" dates would need to meet contrast because they are focusable and are therefore interactable even if you can't select them. It'd look pretty weird to someone who is visually impaired, it might look like an empty focusring. |
Do you have any timeline for this? We would like to know if it would impact our next release. |
Hey, so we are going to have the dates be navigable within the disabled ranges (as they currently are in this PR), we still need to determine the styling of it, but the team can always handle that in a followup. If you wouldn't mind putting the focus ring around the date that is currently being navigated, that should tie up the loose ends for this. |
Co-authored-by: Daniel Lu <dlu@livefyre.com>
Co-authored-by: Daniel Lu <dlu@livefyre.com>
4f49ab3
to
74d79cb
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Went ahead and made the above changes. I'll open a followup PR to implement the keyboard navigation changes. Thanks for the contribution!
Closes Add possibility to disable multiple date intervals in
Calendar
andDatepicker
components✅ Pull Request Checklist:
📝 Test Instructions:
After starting Storybook (
yarn start
), check out those stories:After starting the docs (
yarn start:docs
), check out those pages:The design should look like the following screenshot:

🧢 Your Project:
This feature is for the CJA app, inside Adobe DX.