react-native-paper
react-native-paper copied to clipboard
fix: rtl not being detected correctly on web
Summary
RTL detection didn't work on web (#3736) because RN I18nManager only works on native (See breaking changes from [email protected]).
My solution involved the following:
-
Adding a prop named
direction
to theProvider
, so the user can define if the components should be displayed in RTL or LTR. -
Adding an effect that forces RTL on native when
direction === 'rtl'
. -
Wrapping children of the
Provider
with aView
that injects a prop nameddir
to all it's subtree that will define if components should be displayed in RTL or LTR on web (See new features from [email protected]). -
Change all
paddingLeft
topaddingStart
(See RN RTL support article). -
Change all
paddingRight
topaddingEnd
(See RN RTL support article). -
Change all
marginLeft
tomarginStart
(See RN RTL support article). -
Change all
marginRight
tomarginEnd
(See RN RTL support article).
The mobile version of example app from this branch is ready! You can see it here.
Hey @pac-guerreiro, thank you for your pull request 🤗. The documentation from this branch can be viewed here.
~Not sure why the pop-up menu is still LTR on web:~
We also need Views for content in Portals otherwise we end up with popups in LTR on web:
will pick up this task for the time being. Also, I like @DimitarNestorov approach 👍 removed the View
already and added docs instead
Ok, since this PR becomes too ridiculous to review I'll try to pinpoint a couple of issues.
First things first, react-native-web
mocks out the whole I18nManager
and relies text positioning on dir
property of parent element (e.g. <View dir="rtl>
). As far as I know, RN does not support this property so linter throws error trying to use it. Effectively there's no way around it so I added this convenient wrapper to silent the linter. With or without this, there's the key problem:
Since react-native-web
parses RTL layouts differently to RN
we will need to support two ways of defining LTR/RTL layouts (web & mobile).
Most concerns I have regard this useEffect where I'd assign dir to the root <html>
element of a page (<html dir="rtl">
). This handles most cases since the react-native-web
looks all the way to the top of the tree to find this prop. Without top element with dir
attribute we'd have to add this in multiple places:
- below
<Provider>
, - in each
<Modal>
- and as far as I know inside each
<Surface>
too
Surprisingly, this is not a breaking change, since to apply this direction
has to be manually passed into <Provider>
( as explained here ) , and the prop itself is added in this PR.
Other than that, we need a few hacks since we're basically retrofitting the RTL support at this point:
- https://github.com/callstack/react-native-paper/pull/3777/files#diff-46327c8e0610e196d2eec4ef16e3fee3fe0b9f69c0451f9e43e331b7f26ed08bR163
- https://github.com/callstack/react-native-paper/pull/3777/files#diff-40a7ac238bd91da69419785da41b78053017736cab9ece62b22639c8537174e2R61
- https://github.com/callstack/react-native-paper/pull/3777/files#diff-a4dba4502c98f41455802b906263f5842e6a67881b016e03d6d8a9b5718dcbe7R8
- https://github.com/callstack/react-native-paper/pull/3777/files#diff-5146ee7e7b0598cc2982fcdd8c7f9f6cd3eb0d891f87203ebfc5a3255a6d24beR82
And there's also a couple things I couldn't get to work properly:
-
Animated FAB
does not work on web at the moment (both LTR and RTL are broken) -
Material Bottom Tab Navigator
does not turn the content RTL automatically (need to investigate RTL support in Navigator) -
TextInput
- absolutely no way of getting this component to work on both web & mobile RTL
Most concerns I have regard this useEffect where I'd assign dir to the root element of a page (). This handles most cases since the react-native-web looks all the way to the top of the tree to find this prop.
This won't work with SSR on Web. What I'm planning for React Navigation is to ask users to pass dir
to HTML and call I18nManager.forceRTL
if they need to support RTL
. The direction
prop on the Provider
is simply to inform the library about which direction needs to be used. The library itself shouldn't be trying to call I18nManager.forceRTL
or mutate the DOM. Doing that affects far more than the library's scope.
Other than that on React Navigation side the changes are essentially replacing usage of I18nManager
with the direction
from Provider
.
Can I close this PR?
No, huge chunk of work left
The mobile version of example app from this branch is ready! You can see it here.
Hello @tjaniczek , do you guys plan to continue to work on this feature? We'd love to be able to use it, we've had to swap out our texts and inputs for others from other library on web
lots of stuff has to be done!