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

Support for RN0.63 PlatformColor #6113

Closed
jfrolich opened this issue Apr 9, 2020 · 15 comments · Fixed by #6477
Closed

Support for RN0.63 PlatformColor #6113

jfrolich opened this issue Apr 9, 2020 · 15 comments · Fixed by #6477

Comments

@jfrolich
Copy link

jfrolich commented Apr 9, 2020

Currently there is a problem with implementing dark mode with RNN, as the API is imperative we need to update the UI with mergeoptions when the mode changes from light to dark (and the other way around). This is especially tricky when multiple screens are active (like in a stack). Also sometimes it plainly doesn't work (probably unrelated bugs in mergeOptions). React-Native is going to implement colors that are resolved at runtime (and are a primitive on iOS). These colors automatically update based on the light/dark theme. This would also solve the problem with RNN. We can imperatively set colors, and and they are automatically updated to the right theme on an operating system level.

Explanation about the new feature here: facebook/react-native-website#1813.

@jfrolich
Copy link
Author

jfrolich commented Apr 9, 2020

Actually PlatformColor will expose DynamicColorIOS to do this, didn't interpret the PR correctly. This also means this solution will only work on iOS, and not Android. Does anyone have an idea how to best resolve this? Perhaps RNN can implement a way to elegantly handle dark mode colors.

@stale
Copy link

stale bot commented May 9, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest version and report back. Thank you for your contributions.

@stale stale bot added the 🏚 stale label May 9, 2020
@jfrolich
Copy link
Author

jfrolich commented May 9, 2020

Not stale..

@stale stale bot removed the 🏚 stale label May 9, 2020
@stale
Copy link

stale bot commented Jun 9, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest version and report back. Thank you for your contributions.

@stale stale bot added the 🏚 stale label Jun 9, 2020
@jfrolich
Copy link
Author

jfrolich commented Jun 9, 2020

Not stale

@jinshin1013
Copy link
Contributor

@jfrolich Hi there ✋, currently the recommended approach is to call setRoot again with the updated theme. I know this is not the optimal method as the navigation state is lost.

Hmm reading through the PR that implements the PlatformColor, it does not seem like it's solving the problem that RNN is currently having.

I guess the more ideal way would be declaring the light and dark theme color for the navigation element and on the native side listen to the theme change and adjust the color based on the user input (don't quote me on this 😅):

setDefaultOptions({
  topBar: {
    background: {
      light: 'black', // light theme, set it to black color.
      dark: 'white', // dark theme, set it to white color.
    }
  },
  bottomTabs: {
    backgroundColor: {
      light: 'black', // light theme, set it to black color.
      dark: 'white', // dark theme, set it to white color.  
    }
  }
})

@jfrolich
Copy link
Author

jfrolich commented Jun 9, 2020

@jinshin1013: A better approach is with a useEffect hook and mergeOptions. PlatformColors allow you to set a color that has a light and dark version on a OS level. So the transition from light=>dark mode will be nicer. Also you don't need to imperatively update the colors using a useEffect hook (some other downsides to that for instance with multiple screens in a stack). When PlatformColor is released it also needs to be implemented in RNN anyway otherwise you need a specific "string" set of colors just for navigation (that is different to the UI theme that may contain PlatformColor's).

@jinshin1013
Copy link
Contributor

@jfrolich Are you saying PlatformColor will allow us to do:

setDefaultOptions({
  topBar: {
    background: {
      color: IOSDynamicColor({ light: 'black', dark: 'white' })
    }
  },
  bottomTabs: {
    backgroundColor: IOSDynamicColor({ light: 'black', dark: 'white' })
  }
})

If so, that's a great news! That means the RNN wouldn't have to listen to the theme change and apply the colors.
setRoot({ ... }) // Start the app.

@jfrolich
Copy link
Author

jfrolich commented Jun 9, 2020

Yes. You can define platform colors on the native side with a light and dark appearance. IOSDynamicColor is a way to create a UIColor dynamically, but that is only available on IOS. But when you have a fixed theme, you can statically define the platform colors (have to do it both on iOS and Android).

@jfrolich
Copy link
Author

jfrolich commented Jun 9, 2020

Btw for now you should have a look at mergeOptions because setRoot will just wipe out the whole app (navigation) state indeed.

@jfrolich
Copy link
Author

jfrolich commented Jun 9, 2020

We use this technique quite heavily at https://familyfive.app, with a custom hook, having been featured by Apple quite heavily for our dark mode. And it works quite well! (With a few annoying edge cases).

@jinshin1013
Copy link
Contributor

@jfrolich The app looks fantastic! Yeah we also looked into using mergeOptions and Appearance event listener to change the background colors but it wasn't an ideal solution 😓 So I've asked the developers and it was recommended to use setRoot as it guarantees the theme change. Can't wait for Android support of IOSDynamicColor!

@stale
Copy link

stale bot commented Jul 11, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest version and report back. Thank you for your contributions.

@jfrolich
Copy link
Author

Not stale

@danilobuerger
Copy link
Collaborator

PR at #6477

guyca added a commit that referenced this issue Aug 23, 2020
See https://reactnative.dev/docs/platformcolor for an intro to PlatformColor

Internally react-native uses ColorPropConverter to convert the color on Android. Since it was added in RN63, this PR adds a new build flavor.

ColorPropConverter expects a Context object to resolve named colors from resources. Thus, context is now drilled down into the parser.

ColorPropConverter expects the color to be of type ReadableMap. Since we use JSONObject internally, I added methods to JSONParser to convert those back into the react-native Map format.

Related to #6113

Co-authored-by: Guy Carmeli <guyca@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants