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

Integration with React Navigation #5

Open
josmithua opened this issue Oct 5, 2021 · 5 comments
Open

Integration with React Navigation #5

josmithua opened this issue Oct 5, 2021 · 5 comments
Labels
documentation Improvements or additions to documentation question Further information is requested

Comments

@josmithua
Copy link
Contributor

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.

@emraps
Copy link

emraps commented Oct 5, 2021

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... 🤞

@josmithua
Copy link
Contributor Author

josmithua commented Oct 6, 2021

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' };
}

@arabold
Copy link
Owner

arabold commented Oct 6, 2021

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 arabold added documentation Improvements or additions to documentation question Further information is requested labels Oct 6, 2021
@josmithua
Copy link
Contributor Author

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

@emraps
Copy link

emraps commented Oct 6, 2021

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,
  };
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants