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

fix: ensure date/time segments are ordered correctly in RTL #7423

Open
wants to merge 43 commits into
base: main
Choose a base branch
from

Conversation

yihuiliao
Copy link
Member

@yihuiliao yihuiliao commented Nov 21, 2024

Close #4711

Need to double check that nothing broke in #6562 with these changes.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 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

🧢 Your Project:

@rspbot
Copy link

rspbot commented Nov 21, 2024

@adobe adobe deleted a comment from rspbot Nov 21, 2024
@sadeghbarati
Copy link

sadeghbarati commented Dec 2, 2024

Hey, Thanks for working on this PR

Is this also going to fix keyboard focus management on RTL too?

For example DateField component in the storybook link, if you pick Farsi locale, in order to focus DateSegments with arrow key you need to do it opposite direction to focus next date segment


  • DateField with Farsi locale:

    • yyyy/mm/dd (روز/ماه/سال) format is right ✅
    • focus management with arrow keys is not right ❌
  • DatePicker and DateRangePicker with Farsi locale:

    • dd/mm/yyyy (سال/ماه/روز) format is not right ❌
    • focus management with arrow keys is right ✅

@yihuiliao
Copy link
Member Author

@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.

@rspbot
Copy link

rspbot commented Dec 4, 2024

@rspbot
Copy link

rspbot commented Dec 6, 2024

@rspbot
Copy link

rspbot commented Dec 20, 2024

@adobe adobe deleted a comment from rspbot Jan 7, 2025
@rspbot
Copy link

rspbot commented Jan 8, 2025

@adobe adobe deleted a comment from rspbot Jan 9, 2025
@yihuiliao yihuiliao changed the title wip: fix incorrect date/time order in rtl (pt 2) wip: fix incorrect date/time order in rtl Jan 15, 2025
@rspbot
Copy link

rspbot commented Jan 15, 2025

@@ -181,6 +181,9 @@ export function useDateField<T extends DateValue>(props: AriaDateFieldOptions<T>
if (props.onKeyUp) {
props.onKeyUp(e);
}
},
style: {
unicodeBidi: 'isolate'
Copy link
Member Author

@yihuiliao yihuiliao Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added for DateRangePicker because things were looking a little funky without it. wraps around each datefield. see codepen for reproduction

i could update this so that it only applies in rtl locales but it also doesn't seem to have any affect for ltr locales.

@@ -170,6 +173,7 @@ function PopoverInner({state, isExiting, UNSTABLE_portalContainer, ...props}: Po
ref={ref}
slot={props.slot || undefined}
style={style}
dir={props.dir}
Copy link
Member Author

@yihuiliao yihuiliao Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

popovers are portaled outside which means they don't get the direction of the locale causing the keyboard navigation to behave incorrectly for rac datepickers in rtl. in v3, we wrap the popovers in a provider so this doesn't happen. happy to change the implementation if there's a better way to do this

@rspbot
Copy link

rspbot commented Jan 15, 2025

@adobe adobe deleted a comment from rspbot Jan 15, 2025
@rspbot
Copy link

rspbot commented Jan 17, 2025

@adobe adobe deleted a comment from rspbot Jan 17, 2025
@@ -104,3 +129,19 @@ export function useDatePickerGroup(state: DatePickerState | DateRangePickerState

return mergeProps(pressProps, {onKeyDown});
}

function orderSegments(editableSegments: NodeListOf<Element> | undefined) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adjacent segments might not necessarily be adjacent in the DOM. therefore, we can't just use focusPrevious and focusNext. instead, calculate their positions and use those to determine which segment to move to

@rspbot
Copy link

rspbot commented Jan 17, 2025

@rspbot
Copy link

rspbot commented Jan 17, 2025

@rspbot
Copy link

rspbot commented Jan 17, 2025

@rspbot
Copy link

rspbot commented Jan 17, 2025

@rspbot
Copy link

rspbot commented Jan 17, 2025

@yihuiliao yihuiliao changed the title wip: fix incorrect date/time order in rtl fix incorrect date/time order in rtl Jan 17, 2025
@yihuiliao yihuiliao changed the title fix incorrect date/time order in rtl fix: ensure date/time segments are ordered correctly in RTL Jan 17, 2025
@yihuiliao yihuiliao marked this pull request as ready for review January 17, 2025 23:18
@@ -9,6 +9,8 @@ import {usePress} from '@react-aria/interactions';
export function useDatePickerGroup(state: DatePickerState | DateRangePickerState | DateFieldState, ref: RefObject<Element | null>, disableArrowNavigation?: boolean) {
let {direction} = useLocale();
let focusManager = useMemo(() => createFocusManager(ref), [ref]);
let editableSegments: NodeListOf<Element> | undefined = ref.current?.querySelectorAll('span[role="spinbutton"], span[role="textbox"]');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be done in a useLayoutEffect and the result should be stored in a ref as other parts of state will determine if the effects needs to update

let segmentArr = segments.map(node => {
return {
element: node as FocusableElement,
rectX: node?.getBoundingClientRect().left
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you run segments.filter(Boolean).map..., you may not need this ?

might need to do it the line above so you can set the type correctly

let segments = Array.from(editableSegments).filter...

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

Successfully merging this pull request may close these issues.

Incorrect date / time segment order in several components, for RTL languages
4 participants