diff options
Diffstat (limited to 'src/view/lib')
-rw-r--r-- | src/view/lib/ThemeContext.tsx | 70 | ||||
-rw-r--r-- | src/view/lib/hooks/useAnimatedValue.ts (renamed from src/view/lib/useAnimatedValue.ts) | 0 | ||||
-rw-r--r-- | src/view/lib/hooks/useOnMainScroll.ts (renamed from src/view/lib/useOnMainScroll.ts) | 2 | ||||
-rw-r--r-- | src/view/lib/hooks/usePalette.ts | 41 | ||||
-rw-r--r-- | src/view/lib/themes.ts | 163 | ||||
-rw-r--r-- | src/view/lib/z-index.ts | 2 |
6 files changed, 275 insertions, 3 deletions
diff --git a/src/view/lib/ThemeContext.tsx b/src/view/lib/ThemeContext.tsx new file mode 100644 index 000000000..57f758c53 --- /dev/null +++ b/src/view/lib/ThemeContext.tsx @@ -0,0 +1,70 @@ +import React, {createContext, useContext, useMemo} from 'react' +import {TextStyle, useColorScheme, ViewStyle} from 'react-native' +import {darkTheme, defaultTheme} from './themes' + +export type ColorScheme = 'light' | 'dark' + +export type PaletteColorName = + | 'default' + | 'primary' + | 'secondary' + | 'inverted' + | 'error' +export type PaletteColor = { + isLowContrast: boolean + background: string + backgroundLight: string + text: string + textLight: string + textInverted: string + link: string + border: string + icon: string +} +export type Palette = Record<PaletteColorName, PaletteColor> + +export type ShapeName = 'button' | 'bigButton' | 'smallButton' +export type Shapes = Record<ShapeName, ViewStyle> + +export type TypographyVariant = + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'subtitle1' + | 'subtitle2' + | 'body1' + | 'body2' + | 'button' + | 'caption' + | 'overline' +export type Typography = Record<TypographyVariant, TextStyle> + +export interface Theme { + colorScheme: ColorScheme + palette: Palette + shapes: Shapes + typography: Typography +} + +export interface ThemeProviderProps { + theme?: ColorScheme +} + +export const ThemeContext = createContext<Theme>(defaultTheme) + +export const useTheme = () => useContext(ThemeContext) + +export const ThemeProvider: React.FC<ThemeProviderProps> = ({ + theme, + children, +}) => { + const colorScheme = useColorScheme() + + const value = useMemo( + () => ((theme || colorScheme) === 'dark' ? darkTheme : defaultTheme), + [colorScheme, theme], + ) + + return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider> +} diff --git a/src/view/lib/useAnimatedValue.ts b/src/view/lib/hooks/useAnimatedValue.ts index 1307ef952..1307ef952 100644 --- a/src/view/lib/useAnimatedValue.ts +++ b/src/view/lib/hooks/useAnimatedValue.ts diff --git a/src/view/lib/useOnMainScroll.ts b/src/view/lib/hooks/useOnMainScroll.ts index ee0081226..c3c16ff83 100644 --- a/src/view/lib/useOnMainScroll.ts +++ b/src/view/lib/hooks/useOnMainScroll.ts @@ -1,6 +1,6 @@ import {useState} from 'react' import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native' -import {RootStoreModel} from '../../state' +import {RootStoreModel} from '../../../state' export type OnScrollCb = ( event: NativeSyntheticEvent<NativeScrollEvent>, diff --git a/src/view/lib/hooks/usePalette.ts b/src/view/lib/hooks/usePalette.ts new file mode 100644 index 000000000..e9af4ae16 --- /dev/null +++ b/src/view/lib/hooks/usePalette.ts @@ -0,0 +1,41 @@ +import {TextStyle, ViewStyle} from 'react-native' +import {useTheme, PaletteColorName, PaletteColor} from '../ThemeContext' + +export interface UsePaletteValue { + colors: PaletteColor + view: ViewStyle + border: ViewStyle + text: TextStyle + textLight: TextStyle + textInverted: TextStyle + link: TextStyle +} +export function usePalette(color: PaletteColorName): UsePaletteValue { + const palette = useTheme().palette[color] + return { + colors: palette, + view: { + backgroundColor: palette.background, + }, + border: { + borderWidth: 1, + borderColor: palette.border, + }, + text: { + color: palette.text, + fontWeight: palette.isLowContrast ? '500' : undefined, + }, + textLight: { + color: palette.textLight, + fontWeight: palette.isLowContrast ? '500' : undefined, + }, + textInverted: { + color: palette.textInverted, + fontWeight: palette.isLowContrast ? '500' : undefined, + }, + link: { + color: palette.link, + fontWeight: palette.isLowContrast ? '500' : undefined, + }, + } +} diff --git a/src/view/lib/themes.ts b/src/view/lib/themes.ts new file mode 100644 index 000000000..3851ee9d0 --- /dev/null +++ b/src/view/lib/themes.ts @@ -0,0 +1,163 @@ +import type {Theme} from './ThemeContext' +import {colors} from './styles' + +export const defaultTheme: Theme = { + colorScheme: 'light', + palette: { + default: { + isLowContrast: false, + background: colors.white, + backgroundLight: colors.gray2, + text: colors.black, + textLight: colors.gray5, + textInverted: colors.white, + link: colors.blue3, + border: colors.gray3, + icon: colors.gray2, + }, + primary: { + isLowContrast: true, + background: colors.blue3, + backgroundLight: colors.blue2, + text: colors.white, + textLight: colors.blue0, + textInverted: colors.blue3, + link: colors.blue0, + border: colors.blue4, + icon: colors.blue4, + }, + secondary: { + isLowContrast: true, + background: colors.green3, + backgroundLight: colors.green2, + text: colors.white, + textLight: colors.green1, + textInverted: colors.green4, + link: colors.green1, + border: colors.green4, + icon: colors.green4, + }, + inverted: { + isLowContrast: true, + background: colors.black, + backgroundLight: colors.gray6, + text: colors.white, + textLight: colors.gray3, + textInverted: colors.black, + link: colors.blue2, + border: colors.gray3, + icon: colors.gray5, + }, + error: { + isLowContrast: true, + background: colors.red3, + backgroundLight: colors.red2, + text: colors.white, + textLight: colors.red1, + textInverted: colors.red3, + link: colors.red1, + border: colors.red4, + icon: colors.red4, + }, + }, + shapes: { + button: { + // TODO + }, + bigButton: { + // TODO + }, + smallButton: { + // TODO + }, + }, + typography: { + h1: { + fontSize: 48, + fontWeight: '500', + }, + h2: { + fontSize: 34, + letterSpacing: 0.25, + fontWeight: '500', + }, + h3: { + fontSize: 24, + fontWeight: '500', + }, + h4: { + fontWeight: '500', + fontSize: 20, + letterSpacing: 0.15, + }, + subtitle1: { + fontSize: 16, + letterSpacing: 0.15, + }, + subtitle2: { + fontWeight: '500', + fontSize: 14, + letterSpacing: 0.1, + }, + body1: { + fontSize: 16, + letterSpacing: 0.5, + }, + body2: { + fontSize: 14, + letterSpacing: 0.25, + }, + button: { + fontWeight: '500', + fontSize: 14, + letterSpacing: 0.5, + }, + caption: { + fontSize: 12, + letterSpacing: 0.4, + }, + overline: { + fontSize: 10, + letterSpacing: 1.5, + textTransform: 'uppercase', + }, + }, +} + +export const darkTheme: Theme = { + ...defaultTheme, + colorScheme: 'dark', + palette: { + ...defaultTheme.palette, + default: { + isLowContrast: true, + background: colors.black, + backgroundLight: colors.gray6, + text: colors.white, + textLight: colors.gray3, + textInverted: colors.black, + link: colors.blue2, + border: colors.gray3, + icon: colors.gray5, + }, + primary: { + ...defaultTheme.palette.primary, + textInverted: colors.blue2, + }, + secondary: { + ...defaultTheme.palette.secondary, + textInverted: colors.green2, + }, + inverted: { + isLowContrast: false, + background: colors.white, + backgroundLight: colors.gray2, + text: colors.black, + textLight: colors.gray5, + textInverted: colors.white, + link: colors.blue3, + border: colors.gray3, + icon: colors.gray1, + }, + }, +} diff --git a/src/view/lib/z-index.ts b/src/view/lib/z-index.ts deleted file mode 100644 index 872027d3f..000000000 --- a/src/view/lib/z-index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const FAB = 1 -export const BASE = 0 |