react-native-whirlwind icon indicating copy to clipboard operation
react-native-whirlwind copied to clipboard

Integration with React Navigation

Open josmithua opened this issue 4 years ago • 5 comments

What is the recommended approach to integrating whirlwind with react navigation?

React navigation supplies its own theming solution:

<NavigationContainer
  theme={colorScheme === 'dark' ? darkTheme : lightTheme}
>
  {children}
</NavigationContainer>

and a useTheme hook.

josmithua avatar Oct 05 '21 18:10 josmithua

If you're using Typescript, this would error out.

NavigationContainer theme prop type is:

export declare type Theme = {
    dark: boolean;
    colors: {
        primary: string;
        background: string;
        card: string;
        text: string;
        border: string;
        notification: string;
    };
};

I have a lightColours object and a darkColours object so I'm going to try picking colours into a new navTheme object and passing it to NavigationContainer... 🤞

emraps avatar Oct 05 '21 22:10 emraps

This is what I have so far. Kinda ugly but works good enough.

import { DarkTheme, DefaultTheme, Theme } from '@react-navigation/native';
import { createTheme } from 'react-native-whirlwind';
import { StyleSheet, TextStyle } from 'react-native';
import useColorScheme from './useColorScheme';

const primary = '#61DAFB'; // reactnative.dev primary color

const customClasses = {
  borderYHairline: {
    borderTopWidth: StyleSheet.hairlineWidth,
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
  hHairline: {
    height: StyleSheet.hairlineWidth,
  },
} as const;

const light = StyleSheet.create({
  ...createTheme({
    colors: {
      primary,
      primaryContrast: 'rgb(28, 28, 30)',
      paper: 'rgb(255, 255, 255)',
    },
  }),
  ...customClasses,
});

const dark = StyleSheet.create({
  ...createTheme({
    colors: {
      primary,
      primaryContrast: 'rgb(229, 229, 231)',
      paper: 'rgb(18, 18, 18)',
    },
  }),
  ...customClasses,
});

export const navThemeLight: Theme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    primary,
    background: light.bgGray300.backgroundColor!.toString(),
    border: light.borderGray500.borderColor!.toString(),
    card: light.bgPaper.backgroundColor!.toString(),
    text: (light.textPrimaryContrast as TextStyle).color!.toString(),
  },
};

export const navThemeDark: Theme = {
  ...DarkTheme,
  colors: {
    ...DarkTheme.colors,
    primary,
    background: dark.bgBlack.backgroundColor!.toString(),
    border: dark.borderGray700.borderColor!.toString(),
    card: dark.bgPaper.backgroundColor!.toString(),
    text: (dark.textPrimaryContrast as TextStyle).color!.toString(),
  },
};

export function useWhirlwind() {
  const colorScheme = useColorScheme();
  const theme = colorScheme === 'dark' ? dark : light;
  return { w: theme, isDark: colorScheme === 'dark' };
}

josmithua avatar Oct 06 '21 02:10 josmithua

I agree, this isn't pretty 😞 Would be nice if the Whirlwind API wouldn't require casting or this ugly .toString() for cases like this... 🤔

arabold avatar Oct 06 '21 13:10 arabold

Can't we just type the classes to what they are, and not the very wide types that createStyles types them as?

For example, the bg{color} classes can be just typed as:

type Background = { backgroundColor: string };

I'll play around with this soon

josmithua avatar Oct 06 '21 19:10 josmithua

What I did, which works but also not the prettiest....

const lightColors = {
  primary: '#0954BB',
  primaryDark: '#033B61',
  primaryLight: '#29A8FF',
  // ...etc
};

export const light = StyleSheet.create({
  ...createTheme({
    colors: lightColors,
    // ... etc
  }),
});

export const dark = StyleSheet.create({
  ...createTheme({
     colors: darkColors,
     // ...etc
   }),
});

export const useTheme = () => {
  const colorScheme = useColorScheme();
  const isDark = colorScheme === 'dark';
  const t = isDark ? dark : light;
  const navTheme = {
    dark: isDark,
    colors: {
      primary: isDark ? lightColors.paper : lightColors.primary,
      background: isDark ? lightColors.selected : lightColors.paper,
      text: isDark ? lightColors.paper : '#43526D',
      card: isDark ? lightColors.primaryDark : lightColors.primaryContrast,
      border: lightColors.gray100,
      notification: lightColors.warning,
    },
  };
  return {
    t,
    navTheme,
  };
};

emraps avatar Oct 06 '21 21:10 emraps