Page MenuHomePhabricator

FloatingUI: Provide proper RTL support
Closed, ResolvedPublic5 Estimated Story Points



OOUI went to great lengths to ensure that floating, flipping, and clipping overlays worked as well in RTL contexts as in LTR ones. We need to meet that same level of support with overlaps in Codex.

Since we don't yet have a Popup component, this task just applies to components that use the Menu component internally.

FloatingUI's RTL support

FloatingUI does provide support out of the box for RTL contexts:

  • It detects when the floated element has a computed dir of rtl and adjusts its positioning calculations accordingly. Note that the translate-x value it provides is meant to be applied to the left edge of the container in both LTR and RTL (which is why we need left: 0 on dropdown menus in both directions)
  • It's aware of scrollbars being on the left side in RTL contexts
  • It flips left and right placements (not applicable here, since menus only open up or down)

Further investigation

So far with this proof-of-concept, we have gotten menu positioning to work in LTR and RTL both inside and outside of Dialogs. However, we should test this further to ensure we have sufficient RTL support, and if shortcomings in FloatingUI arise, we need to handle those situations on our own. Ideally, we could do this via the middleware system provided by FloatingUI.

Testing strategy
  • Test Select in a Dialog while scrolling, changing the window size, and a combination of the two
  • Test Select in a Dialog that has horizontal scrolling
  • Test horizontal clipping of the Select menu (in OOUI, menus are clipped from the end-edge)
  • More?

Acceptance criteria

  • Complete testing as listed above
  • Open new tasks for further fixes if needed

Related Objects


Event Timeline

AnneT renamed this task from FloatingUI: Determine the best way to support RTL behavior to FloatingUI: Provide proper RTL support.Sep 12 2023, 9:23 PM
AnneT updated the task description. (Show Details)
AnneT added subscribers: Mooeypoo, Catrope, AnneT.

@Catrope / @Mooeypoo Do you have any advice on how to test floating/clipping of a dropdown menu in an RTL context? I can think of a few ways where this could break (listed under "testing strategy" in the task description) but would love some more ideas/things to look out for.

The only thing I can think of is nesting of different directionalities. The most common way this appears in a MediaWiki context is if the user has an RTL language preference set on a wiki whose content is in an LTR language (e.g. ) or vice versa; then the top-level page will be RTL but the content area will be LTR. This can have some strange consequences that might trigger bugs, like:

  • If there is an input with a menu in the content area, everything in the menu's local environment is LTR, but everything to do with page-wide/viewport things will be in RTL (the viewport's scrollbar is on the left, scrollLeft values are negative, etc). This could confuse code to do with clipping to the viewport's edge or accounting for scroll bars
  • Relatedly, If a child of the content area is scrollable (this is not common in practice), then that element's vertical scrollbar will be on the right (because that element is LTR), even though the vertical scrollbar for the viewport is on the left (because the page as a whole is RTL); and scrollLeft values are positive for the scrollable container in the content area but negative for the viewport. Code to do with clipping or accounting for scroll bars could get confused if it doesn't account for the fact that each nested scrollable ancestor could have its own different directionality

To test for this, I suggest setting up a nested directionality test case, and testing both with a non-scrollable and a scrollable inner container, and testing both vertical and horizontal scrolling on both the viewport and the inner container.

Nested directionality cases aren't easy to test in Codex's existing sandbox or docs site, because those use bidirectional styles that require a single directionality be used on the whole page. You could disable the postcssRtlcss plugin locally to work around this issue (by commenting out lines 17-26 of packages/codex/vite.config.ts).

This looks promising! And.... honestly, anything would have outlier issues in RTL. There will be cases you'll have to run around fixing no matter what you do (OOUI had that too) so you might as well start from something solid that gives you 90% of the functionality. In that aspect, I'd just verify it allows you to tweak / extend properly because you likely will have to with specific edge cases.

As for testing, (as @Catrope mentions above) I think the most important ones I'd check are mixed directionality cases:

  • Go to an RTL wiki (arabic / hebrew) but set up the UI language to LTR (English). Test all your test strategies.
  • (and backwards) Go to an LTR wiki, set UI language to RTL, test all your test strategies.

One more edge-casey shenanigans we had to run around trying to figure out is the floatable-on-floatable that is not a dialog (as in popup in popup!).
I think UX-wise this shouldn't happen, but we do have some cases where a popup has a nested popup (so, the two need to clip/float/scroll/move/flip) Fun!

Echo has something like this in the menu inside the notification popup. You'd get the Echo popup and then open the dotdotdot menu and get a secondary popup. I don't know if that's a good UX in general regardless of LTR/RTL but since we already have it, you should probably test that.

MediaWiki-echo-popup-in-popup.png (155×502 px, 27 KB)

I think also there are some gadgets with that behavior, but I'm not sure which ones right now.

Change 960117 had a related patch set uploaded (by Catrope; author: Catrope):

[mediawiki/extensions/VueTest@master] [DO NOT MERGE] Test floating-ui menus in mixed directionality cases

Change 960118 had a related patch set uploaded (by Catrope; author: Catrope):

[mediawiki/core@master] [DO NOT MERGE] Testing next version of Codex

Test wiki created on Patch demo by Roan Kattouw (WMF) using patch(es) linked to this task:

I tried all sorts of combinations of nesting LTR and RTL in the attached patchdemo, both inside and outside a dialog, and everything seems to work well.

Catrope claimed this task.

Closing this since this seems done; we can reopen if new problems appear (or file a new task)

Awesome, thanks for testing @Catrope, and thanks @Mooeypoo for the recommendations!

Test wiki on Patch demo by Roan Kattouw (WMF) using patch(es) linked to this task was deleted: