wix / react-native-ui-lib

UI Components Library for React Native
https://wix.github.io/react-native-ui-lib/
MIT License
6.53k stars 712 forks source link

Dark mode view modifiers no longer working #2127

Open dariuscosden opened 2 years ago

dariuscosden commented 2 years ago

Description

Dark mode no longer works with view modifiers. Regardless of device scheme, the view background colors will be "light".

Related to

Steps to reproduce

  1. Load light and dark schemes using Colors.loadSchemes.
  2. Add background color modifier to any view
  3. Switch from light to dark color scheme on device
  4. Views stay light

More Info

I've traced it down to this commit, where the default scheme was changed from default to light. Currently I have patched the package to change it back to default and it works.

Environment

Affected platforms

lidord-wix commented 2 years ago

@dariusmandres please add the following require in your app, in an initial place, before importing react-native-ui-lib at the first time.

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});
ethanshar commented 2 years ago

@lidord-wix Let's add this to our docs. Under Foundation -> Colors

dariuscosden commented 2 years ago

@lidord-wix

I have tried that, it didn't work unfortunately. The dark mode is still not respected. I made sure to have it at the topmost level before anything else is imported.

Have you gotten this to work on your end? Was there anything else to keep in mind that could affect?

sallar commented 2 years ago

I investigated a little bit, 6.13.0 works perfectly but 6.14.0 breaks the color changes.

After adding this:

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});

6.18.0 works great, but 6.19.0 breaks. Maybe something related to #2146?


Update: backgroundColor doesnt work. Rest of the props work.

kanzitelli commented 2 years ago

The same happens to me with 6.20.* version. When downgrading to 6.18.*, View changes background color correctly when toggling appearance mode.

lidord-wix commented 2 years ago

I created a new react-native app with version 6.20.* of react-native-ui-lib and when I call

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});

at the very beginning point of the app, it works. Your issue might happen because you import your app (where you use ui-lib) before you require the config. (imports are hoisted and called before requires). I can suggest you the following solution:

  1. Add a new file to your project root called setup.js.
  2. Add the following line to your setup.js file:
    require('react-native-ui-lib/config').setConfig({appScheme: 'default'});
  3. import the setup file on your index.js, and make sure it's your first import (or at least before importing your app). Please check that and let me know if it works for you
sallar commented 2 years ago

Thanks @lidord-wix I did the exact thing you mentioned:

index.js:

import './setup';
import 'react-native-gesture-handler';
import {registerRootComponent} from 'rnn-screens';

// ...

setup.ts:

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});

and everything works, except background colors when appearance mode is updated:

Simulator Screen Recording - iPhone 13 - 2022-09-01 at 13 11 09

(using react-native-ui-lib's View: <View flex bg-bgColor>)

lidord-wix commented 2 years ago

@sallar do you load the bgColor using Colors.loadScheme()? can you share a code snippet?

sallar commented 2 years ago

@lidord-wix yes,

const colors: DesignSystemColors = {
  primary: '#5383b8', // blue
  secondary: '#469c57', // green
  accent: '#fed330', // yellow
  blackish: Colors.rgba(20, 20, 20, 1),
  blackish2: Colors.rgba(50, 50, 50, 1),
  whitish: Colors.rgba(250, 250, 250, 1),
  whitish2: Colors.rgba(230, 230, 230, 1),
};

const themes: Record<AppearanceMode, ThemeColors> = {
  light: {
    textColor: colors.blackish,
    bgColor: colors.whitish,
    bg2Color: colors.whitish2,
  },
  dark: {
    textColor: colors.whitish,
    bgColor: colors.blackish,
    bg2Color: colors.blackish2,
  },
};

Colors.loadColors(colors);
Colors.loadSchemes(themes);
sallar commented 2 years ago

Another issue, <Text> also only works between appearance modes when I explicitly set the color myself: <Text marginB-s2 text60R textColor>, otherwise the default colors from react-native-ui-lib's design tokens don't come through.

so this works between scheme changes: <Text marginB-s2 text60R textColor>

but this doesnt, and stays black: <Text marginB-s2 text60R>

lidord-wix commented 2 years ago

@sallar for now, after a scheme change you'll need to restart the app. after the restart, the Text color should be in the right color. for the background issue, where do you call this loadSchemes(themes)?

sallar commented 2 years ago

@lidord-wix if the app needs to reload then everything works as expected. all my comments regarding stuff not working are related to "dynamic" scheme changes. do you think this will be fixed in the future?

lidord-wix commented 2 years ago

@sallar we hope so, we're using react-native's platform color and we still have some issues there (mainly on android).

sallar commented 2 years ago

@lidord-wix thanks- if platformColor or dyanmicColorIOS is used then things should work at least on iOS

kanzitelli commented 2 years ago

hey @lidord-wix @sallar

after digging into the code and using the power of console.logs, I've found out that when toggling appearance in system mode, themeProps are not being updated for the views which are currently displayed (also for components on other tabs). And if you push a new screen, then themeProps will be depended on system appearance.

the problem is in useThemeProps() hook which is actually a pure function and doesn't have any deps. I have added useColorScheme() hook from react-native to the useThemeProps(), so themeProps will be updated for views with updated theme values and color scheme.

I'm not sure if it's the best solution for this case in terms of performance and etc., as I don't know the whole structure of the library. Maybe @ethanshar can comment on this, and if it's okay, here is PR #2234.

Patch file - rnn-starter/patches/react-native-ui-lib+6.20.3.patch. Working example - rnn-starter

sallar commented 2 years ago

Thanks @kanzitelli! I was actually testing this library with rnn-starter haha. But your patch works flawlessly. Thank you! Just one thing, the default design tokens, eg, $textDefault still don't work without reloading, even with this change. But that doesn't matter. I'll try to not use any of them :(

kanzitelli commented 2 years ago

hey @sallar! Great to hear that! It would be great if you could elaborate more on default design tokens. I couldn't find any information about them in RN UI Lib docs.

And thanks for using the rnn-starter haha. I've caught it on the video and it seems like you are using old version 😁

sallar commented 2 years ago

@kanzitelli I will use the new rnn-starter 👍 Design tokens are the colors that are used for light/dark mode by default in new versions of the library. For example Text component uses the colors from here: https://github.com/wix/react-native-ui-lib/blob/master/src/style/designTokens.ts

for example when you use <Text> the default color is used inside the component: <Text $textDefault>

kanzitelli commented 2 years ago

@sallar that's great! I've never used design tokens tbh, they seem nice to use. The only import of designTokens is here and seems to be loading schemes correctly. Probably it needs to reloaded somewhere but needs more digging. I'll see what I can to help with this.

dariuscosden commented 2 years ago

Seems to have been fixed as of 6.21.2 without any patch or extra configuration.

@sallar confirm?

izversky commented 1 year ago

Switching theme for View also does not work for me. Package version: 6.23.1. Components Text and Button work correctly, but the view does not respond to theme switching

DeveloperTheExplorer commented 1 year ago

Using Expo here. I did all of the suggested fixes however, even with an app reload, the colors still don't change at all when I change to dark mode on iOS. Any ideas? package: 6.25.0 expo: 47.0.6 react: 18.1.0 react-native: 0.70.5

uyasarkocal commented 1 year ago

@DeveloperTheExplorer I was having the same issue, If you are using expo don't forget to add
"userInterfaceStyle": "automatic" to your app.json. Also it is crucial to install "expo-system-ui" package when using development builds.

mr-menno commented 1 year ago

Struggled through the documentation, simply adding the require to set the scheme to default did not work in a new bare Expo application, and since import statements are evaluated before requires, the setConfig() function does not work. The trick was to move the require into a new file, and import that file before anything else.

The following did work:

  1. create a file called setup.js besides the App.js file
  2. import the ./setup file before all the other imports in the App.js file.

setup.js

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});

App.js line 1

import './setup';
sallar commented 1 year ago

It shouldn't be this hard to enable dark mode.

MrX1068 commented 1 year ago

Dark mode

any support for dark mode, still I'm not able to use dark mode for the latest versions.

in my case if I didn't use any wrapper like Redux or other then this dark mode background is applying for View. If I use redux provider it's not applying the dark background.

josegiufrida commented 1 year ago

Same here! Using "react-native-ui-lib": "7.2.1"

lidord-wix commented 1 year ago

@MrX1068, @josegiufrida Did you try the solution from this comment?

MrX1068 commented 1 year ago

Yes tried that, but as I mentioned it is working fine. If i try to use redux provider it is not taking that dark theme.

Dark mode

any support for dark mode, still I'm not able to use dark mode for the latest versions.

in my case if I didn't use any wrapper like Redux or other then this dark mode background is applying for View. If I use redux provider it's not applying the dark background.

lidord-wix commented 1 year ago

@MrX1068 can you share your project (or any example project) that I can run to reproduce?

josegiufrida commented 1 year ago

@MrX1068, @josegiufrida Did you try the solution from this comment?

Yes, Im implementing that.

I think my problem it's related to this comment. I assumed that the changes would be applied without a restart.

@sallar for now, after a scheme change you'll need to restart the app. after the restart, the Text color should be in the right color. for the background issue, where do you call this loadSchemes(themes)?

When I reload the app, all works nice. It would be nice if this information is added to docs.

mfrfinbox commented 1 year ago

Struggled through the documentation, simply adding the require to set the scheme to default did not work in a new bare Expo application, and since import statements are evaluated before requires, the setConfig() function does not work. The trick was to move the require into a new file, and import that file before anything else.

The following did work:

  1. create a file called setup.js besides the App.js file
  2. import the ./setup file before all the other imports in the App.js file.

setup.js

require('react-native-ui-lib/config').setConfig({appScheme: 'default'});

App.js line 1

import './setup';

This worked for me, I am using the latest version as of today (7.5.1) and using expo + expo router.

I went and put the require('react-native-ui-lib/config').setConfig({appScheme: 'default'}); directly into my index.js, and now it looks like this:

// index.js
require('react-native-ui-lib/config').setConfig({appScheme: 'default'});
import "expo-router/entry";

Thanks @uyasarkocal for making me realise that I indeed needed to do serInterfaceStyle": "automatic"and of course @mr-menno for the well explained solution.

awalmubarak commented 1 year ago

Does anyone have a work around for having to restart the app anytime you change themes? It's easier to change themes on IOS by just sliding down and pressing on the theme icon. Users will not know they have to restart the app to see the new theme and this is a little troubling.

I'd be glad if anyone has a way around this!

lidord-wix commented 1 year ago

Hi @awalmubarak! In the future, we'll use platformColor, which should solve this issue. While we tried to do it in the past we had some issues on Android so we're waiting for a fix on React Native side. Until that, you can use a UX solution for that - once the user changes his appearance on the device, you can show him a banner/alert saying that he needs to restart the app to see the changes.

awalmubarak commented 1 year ago

@lidord-wix thanks for the response. I'll go with the UX solution for now. Is the future solution something that's already in progress. If not, is there a way I can contribute to help speedup this solution. I think this will be a big win

lidord-wix commented 1 year ago

Thank you @awalmubarak! We actually need to migrate an internal project we have to >= RN70 before we can do this step. It has some bugs in older versions of react native.

jake-ruth commented 12 months ago

For anyone still struggling with this: my solution for now is to do the theme switch in rnui, save it to local storage, then use the react-native-restart package to reload the app programmatically:

https://www.npmjs.com/package/react-native-restart

Would be nice in the future to dynamically change the theme though. So hopefully that comes soon.

jdmg94 commented 11 months ago

After reading this thread and trying most solutions proposed here, nothing has worked on my detached expo project, so I think its time for me to abandon this library. The components look great but the documentation is not great (and it also lacks dark mode!) and to make things worse the APIs are not intuitive.

I don't see why this couldn't be abstracted into a single theme builder function with a more traditional context provider type of solution

// App.tsx
const theme = createTheme({
  mode: 'light', // or 'dark'
  lightColors: {
    tertiary: '#124789',
    accent: '#f98652',
    surface: '#0990763',
  },
  darkColors: {
    tertiary: '#124789',
    accent: '#908652',
    surface: '#0990763',
  },
  components:{
    Button:(props,theme)=>({
      containerStyle:{
        backgroundColor:theme.colors.tertiary
      }
    })
  }
});

// Wrap with ThemeProvider
const App = () => {
  return (
    <ThemeProvider theme={theme}>
      <Component />
    </ThemeProvider>
  );
};
ChrisPam commented 10 months ago

still waiting for any working solution? I tried everything above, but nothing works

bdotsamir commented 5 months ago

I'm in the same boat. I have tried every solution in this thread and still nothing is working for me. I switched to this component library from react-native-elements because it generally looked better, but the documentation is sorely lacking. In addition to this, I share some of the same sentiments that others have mentioned. It truly should not be this difficult to enable dark mode.

I think it's time for me to switch again. I've been meaning to, this is kind of what pushed me over the edge. Sorry folks

erikbwu commented 2 months ago

@sallar How did you get your text to work with dark mode?

I have tried using setup.js with the require function as the first import, but even when using <Text textColor>asdfasdf</Text> and reloading the app, the text is somewhat dark (in Dev Build): grafik

setup.js: require("react-native-ui-lib/config").setConfig({ appScheme: "dark" });

and userInterfaceStyle: "automatic", is set in app.config.js /app.json. I have not designed any custom themes.

Also, is there an easy way to check, if dark mode is enabled in rnuilib?