Integration with React Navigation
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.
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... 🤞
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' };
}
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... 🤔
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
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,
};
};