-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
fix: correctly format date/time in RTL #7423
Conversation
Hey, Thanks for working on this PR Is this also going to fix keyboard focus management on RTL too? For example
|
@sadeghbarati Yes, the plan is to also correct the keyboard navigation for RTL as well. The PR is still in the early stages so there's a lot that has yet to be implemented. |
let el = this; | ||
|
||
if (el.getAttribute('role') === 'spinbutton') { | ||
if (el.parentElement.getAttribute('data-testid') === 'end-date') { |
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 thought the issue with some of these was that the dom order was not in alignment with the rendered order?
this test is a good base, but should we include some tests where the order differs? I think you could use el.getAttribute('data-type')
to order based on the day/month/hour/etc
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.
ah yes, it's more obvious with when using examples with time segments so i should update the examples to include those
@@ -92,11 +92,11 @@ export const DateRangePickerExample = () => ( | |||
<Label style={{display: 'block'}}>Date</Label> | |||
<Group style={{display: 'inline-flex'}}> | |||
<div className={styles.field}> | |||
<DateInput data-testid="date-range-picker-date-input" slot="start" style={{display: 'inline-flex'}}> | |||
<DateInput data-testid="date-range-picker-date-input" slot="start" style={{display: 'inline'}}> |
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.
sort of a breaking change
what will happen to people who have used this as an example to build their DatePicker's in the past?
Also, why is the style change different from DateField.mdx?
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.
so i experimented a bit and found that for the rtl segments to display in the correct order, DateInput needs to have display inline, inline-block, or block. hence why one is display inline and the other is display block. it would probably be a good idea to make it consistent and stick with display inline though.
and as for the sort of breaking change, i think folks can continue to use display: inline-flex
. i don't believe the changes here will affect that. the only thing that they'll run into is that if they do choose to render their datepicker in a rtl locale, it will be in the incorrect order.
updating the docs and stories here is to reflect the changes needed for rtl locales to display in the right order. that way, those who do end up copying the docs + styles afterwards will have the proper styling for it to work correctly.
unfortunately, i don't think there's a way to have rtl locales render their date/time segments correctly using display flex, so it might require updates on the users side.
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.
ok, so long as inline-flex doesn't break anything, I'm fine with this
we should add a little blurb to the Accessibility section for the docs
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.
yeah, that's a good idea to call it out in our docs somewhere. i think maybe the Internationalization section instead?
let update = () => { | ||
if (ref.current) { | ||
// TODO: For now, just querying this list of elements. However, it's possible that either through hooks or RAC that some users may include other focusable items that they would want to able to keyboard navigate to. In that case, we might want to utilize focusableElements in isFocusable.ts | ||
let editableSegments: NodeListOf<Element> | undefined = ref.current?.querySelectorAll('span[role="spinbutton"], span[role="textbox"], button'); |
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.
because this checks for span
in all the selectors, will this break people who are using div
s like we used to?
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 good point. hmm in that case, we could update it so that it also checks for divs as well?
although, my guess is that people aren't using this in rtl locales given that the time/date formats were so off.
|
||
// Not needed in aria-described by because each segment has a label already, so this would be duplicative. | ||
let group = getByRole('group'); | ||
expect(group).not.toHaveAttribute('aria-describedby'); | ||
|
||
expect(getByText('month / day / year')).toBeVisible(); |
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 removed this line since now each individual segment is in its own span and it would be hard to query those. we have a chromatic story to test this so it is covered. i kept the rest of the test since it would be good to continue checking the aria stuff.
(and the same goes for DatePicker.test and DateRangePicker.test)
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.
Noticed that "Delete" likely needs the same logical movement treatment that the arrow keys got. Otherwise, in Hebrew I start deleting from the year -> month -> day and then it stops, it never moves to the time field element
I'm ok for this to be in follow up, otherwise looks good
I think this is actually the correct behavior. "Delete" causes the focus to shift to the previous node. If you're deleting from year -> month -> day and then try deleting again, the focus never moves because there is no node before day. It's the same in LTR. In en-US, if you start deleting year -> day -> month, you'll also never move to the timefield. It just feels like you should in RTL because we're reading the entire field as LTR because that's what we're used to. |
|
||
update(); | ||
|
||
let observer = new MutationObserver(update); |
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.
Do we need the MutationObserver? When would the segments change order without the date picker itself re-rendering?
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.
hmm good point,,,i think it should be fine if we were to get rid of it
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.
it was for if users added more buttons to control the field, Yihui had an example with a <<
and <
button for jumping month and year I think
I don't know if those buttons would ever be removed or added dynamically
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.
Ah right, I think it was from the example in this issue #7645
isEditable | ||
} as DateSegment; | ||
|
||
if (segment.type === 'hour') { |
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.
We should add some comments to this function describing how it works and what the unicode characters do. Will be hard for future readers/contributors to understand what's going on if they aren't familiar with it. 😄
Close #4711
Need to double check that nothing broke in #6562 with these changes.
✅ Pull Request Checklist:
📝 Test Instructions:
Arabic should render in the following order:
TimeZone DayPeriod Hour:Minute Year/Month/Day
Hebrew should render in the following order:
TimeZone DayPeriod Hour:Minute Day/Month/Year
Tab order should be:
Day -> Month -> Year -> Hour -> Minute -> DayPeriod -> TimeZone
Arabic Placeholders:
يوم / شهر / سنة
Hebrew Placeholders:
שנה.חודש.יום
Also be sure to test keyboard navigation, deleting/backspace, resizing
Note that with backspacing, the focus should move the previous node. So basically the tab order above but go from right to left
🧢 Your Project: