Skip to content

Instantly share code, notes, and snippets.

@gilsonviana
Created May 3, 2021 00:22
Show Gist options
  • Save gilsonviana/30b9c9f60970424f7fb05a5d793f4737 to your computer and use it in GitHub Desktop.
Save gilsonviana/30b9c9f60970424f7fb05a5d793f4737 to your computer and use it in GitHub Desktop.
React Native Custom Themes
export const colorTokens = {
black: '#000',
dark: '#383838',
dark50: '#707070',
muted: '#cdcdcd',
light: '#e6e6e6',
offWhite: '#f5f5f5',
white: '#ffffff',
accent1: '#f72585',
accent1_50: '#fb91c2',
accent2: '#3f37c9',
accent2_50: '#9e9ae4',
danger: '#F44D4D'
}
import React, { createContext, useContext, useState } from 'react'
import { useColorScheme } from 'react-native'
import { Theme, lightTheme, darkTheme } from '@main/theme'
import { IThemeContext } from './types'
export const ThemeContext = createContext<IThemeContext>({} as IThemeContext)
export const ThemeProvider: React.FC<React.ReactNode> = ({ children }) => {
const colorScheme = useColorScheme()
const setThemeScheme = (scheme: 'light' | 'dark' = 'light'): void => {
setTheme(() => {
return scheme === 'dark' ? darkTheme : lightTheme
})
}
const toggleTheme = (): void => {
const currentTheme = theme.variant
setTheme(() => {
return currentTheme === 'dark' ? lightTheme : darkTheme
})
}
const [theme, setTheme] = useState<Theme>(() =>
colorScheme === 'dark' ? darkTheme : lightTheme
)
return (
<ThemeContext.Provider
value={{
theme,
setThemeScheme,
toggleTheme
}}
>
{children}
</ThemeContext.Provider>
)
}
export const useThemeContext = () => useContext(ThemeContext)
import { Dimensions } from 'react-native'
import { colorTokens } from './colors'
const { width } = Dimensions.get('screen')
const getPercentage = (percentage: number) => width * (percentage / 100)
type ThemeVariant = 'light' | 'dark';
export type Theme = {
variant: ThemeVariant;
neutral: ColorShades<Shades>;
primary: ColorShades<Record<500 | 400, Shades>>;
secondary: ColorShades<Record<500 | 400, Shades>>;
danger: string;
font: {
primary: ThemeFont;
secondary?: ThemeFont;
};
layout: {
horizontal: number;
top: number;
};
};
type ThemeFont = {
regular: string;
bold: string;
};
type Shades = {
0: string;
10: string;
100: string;
200: string;
300: string;
400: string;
500: string;
};
type ColorShades<T> = {
[key in keyof T]: string;
};
const font = {
primary: {
regular: 'Archivo-Medium',
bold: 'Archivo-Bold'
}
}
const layout = {
horizontal: getPercentage(3.5),
top: getPercentage(15)
}
export const lightTheme: Theme = {
variant: 'light',
neutral: {
0: 'transparent',
10: colorTokens.white,
100: colorTokens.offWhite,
200: colorTokens.light,
300: colorTokens.muted,
400: colorTokens.dark50,
500: colorTokens.dark
},
primary: {
500: colorTokens.accent1,
400: colorTokens.accent1_50
},
secondary: {
500: colorTokens.accent2,
400: colorTokens.accent2_50
},
danger: colorTokens.danger,
font,
layout
}
export const darkTheme: Theme = {
variant: 'dark',
neutral: {
0: 'transparent',
10: colorTokens.black,
100: colorTokens.dark,
200: colorTokens.dark50,
300: colorTokens.muted,
400: colorTokens.light,
500: colorTokens.offWhite
},
primary: {
500: colorTokens.accent1,
400: colorTokens.accent1_50
},
secondary: {
500: colorTokens.accent2,
400: colorTokens.accent2_50
},
danger: colorTokens.danger,
font,
layout
}
import { Theme } from '@main/theme'
export interface IThemeContext {
theme: Theme;
setThemeScheme: (scheme: 'light' | 'dark') => void;
toggleTheme: () => void;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment