diff --git a/native/themes/colors.js b/native/themes/colors.js index 8600c1967..a7793fefc 100644 --- a/native/themes/colors.js +++ b/native/themes/colors.js @@ -1,323 +1,363 @@ // @flow import * as React from 'react'; import { StyleSheet } from 'react-native'; import { createSelector } from 'reselect'; import { selectBackgroundIsDark } from '../navigation/nav-selectors.js'; import { NavContext } from '../navigation/navigation-context.js'; import { useSelector } from '../redux/redux-utils.js'; import type { AppState } from '../redux/state-types.js'; import type { GlobalTheme } from '../types/themes.js'; +const designSystemColors = Object.freeze({ + shadesWhite100: '#ffffff', + shadesWhite90: '#f5f5f5', + shadesWhite80: '#ebebeb', + shadesWhite70: '#e0e0e0', + shadesWhite60: '#cccccc', + + shadesBlack100: '#0a0a0a', + shadesBlack90: '#1f1f1f', + shadesBlack80: '#404040', + shadesBlack70: '#666666', + shadesBlack60: '#808080', + + violetDark100: '#7e57c2', + violetDark80: '#6d49ab', + violetDark60: '#563894', + violetDark40: '#44297a', + violetDark20: '#331f5c', + + violetLight100: '#ae94db', + violetLight80: '#b9a4df', + violetLight60: '#d3c6ec', + violetLight40: '#e8e0f5', + violetLight20: '#f3f0fa', + + successLight10: '#d5f6e3', + successLight50: '#6cdf9c', + successPrimary: '#00c853', + successDark50: '#029841', + successDark90: '#034920', + + errorLight10: '#feebe6', + errorLight50: '#f9947b', + errorPrimary: '#f53100', + errorDark50: '#b62602', + errorDark90: '#4f1203', + + spoilerColor: '#33332c', +}); + const light = Object.freeze({ - blockQuoteBackground: '#E0E0E0', - blockQuoteBorder: '#CCCCCC', - codeBackground: '#E0E0E0', - disabledButton: '#E0E0E0', - disabledButtonText: '#808080', - disconnectedBarBackground: '#F5F5F5', + blockQuoteBackground: designSystemColors.shadesWhite70, + blockQuoteBorder: designSystemColors.shadesWhite60, + codeBackground: designSystemColors.shadesWhite70, + disabledButton: designSystemColors.shadesWhite70, + disabledButtonText: designSystemColors.shadesBlack60, + disconnectedBarBackground: designSystemColors.shadesWhite90, editButton: '#A4A4A2', floatingButtonBackground: '#999999', - floatingButtonLabel: '#EBEBEB', - headerChevron: '#0A0A0A', - inlineEngagementBackground: '#E0E0E0', - inlineEngagementLabel: '#0A0A0A', - link: '#7E57C2', - listBackground: '#FFFFFF', - listBackgroundLabel: '#0A0A0A', + floatingButtonLabel: designSystemColors.shadesWhite80, + headerChevron: designSystemColors.shadesBlack100, + inlineEngagementBackground: designSystemColors.shadesWhite70, + inlineEngagementLabel: designSystemColors.shadesBlack100, + link: designSystemColors.violetDark100, + listBackground: designSystemColors.shadesWhite100, + listBackgroundLabel: designSystemColors.shadesBlack100, listBackgroundSecondaryLabel: '#444444', listBackgroundTernaryLabel: '#999999', listChatBubble: '#F1F0F5', - listForegroundLabel: '#0A0A0A', + listForegroundLabel: designSystemColors.shadesBlack100, listForegroundSecondaryLabel: '#333333', - listForegroundTertiaryLabel: '#666666', - listInputBackground: '#F5F5F5', + listForegroundTertiaryLabel: designSystemColors.shadesBlack70, + listInputBackground: designSystemColors.shadesWhite90, listInputBar: '#E2E2E2', listInputButton: '#8E8D92', listIosHighlightUnderlay: '#DDDDDDDD', - listSearchBackground: '#F5F5F5', + listSearchBackground: designSystemColors.shadesWhite90, listSearchIcon: '#8E8D92', - listSeparatorLabel: '#666666', - modalBackground: '#EBEBEB', + listSeparatorLabel: designSystemColors.shadesBlack70, + modalBackground: designSystemColors.shadesWhite80, modalBackgroundLabel: '#333333', modalBackgroundSecondaryLabel: '#AAAAAA', modalButton: '#BBBBBB', - modalButtonLabel: '#0A0A0A', - modalContrastBackground: '#0A0A0A', - modalContrastForegroundLabel: '#FFFFFF', + modalButtonLabel: designSystemColors.shadesBlack100, + modalContrastBackground: designSystemColors.shadesBlack100, + modalContrastForegroundLabel: designSystemColors.shadesWhite100, modalContrastOpacity: 0.7, - modalForeground: '#FFFFFF', - modalForegroundBorder: '#CCCCCC', - modalForegroundLabel: '#0A0A0A', + modalForeground: designSystemColors.shadesWhite100, + modalForegroundBorder: designSystemColors.shadesWhite60, + modalForegroundLabel: designSystemColors.shadesBlack100, modalForegroundSecondaryLabel: '#888888', modalForegroundTertiaryLabel: '#AAAAAA', modalIosHighlightUnderlay: '#CCCCCCDD', - modalSubtext: '#CCCCCC', - modalSubtextLabel: '#666666', - navigationCard: '#FFFFFF', - navigationChevron: '#CCCCCC', - panelBackground: '#F5F5F5', + modalSubtext: designSystemColors.shadesWhite60, + modalSubtextLabel: designSystemColors.shadesBlack70, + navigationCard: designSystemColors.shadesWhite100, + navigationChevron: designSystemColors.shadesWhite60, + panelBackground: designSystemColors.shadesWhite90, panelBackgroundLabel: '#888888', - panelForeground: '#FFFFFF', - panelForegroundBorder: '#CCCCCC', - panelForegroundLabel: '#0A0A0A', + panelForeground: designSystemColors.shadesWhite100, + panelForegroundBorder: designSystemColors.shadesWhite60, + panelForegroundLabel: designSystemColors.shadesBlack100, panelForegroundSecondaryLabel: '#333333', panelForegroundTertiaryLabel: '#888888', panelIosHighlightUnderlay: '#EBEBEBDD', - panelSecondaryForeground: '#F5F5F5', - panelSecondaryForegroundBorder: '#CCCCCC', - purpleLink: '#7E57C2', - purpleButton: '#7E57C2', - reactionSelectionPopoverItemBackground: '#404040', - redText: '#F53100', - spoiler: '#33332C', - tabBarAccent: '#7E57C2', - tabBarBackground: '#F5F5F5', - tabBarActiveTintColor: '#7E57C2', - vibrantGreenButton: '#00C853', - vibrantRedButton: '#F53100', - whiteText: '#FFFFFF', - tooltipBackground: '#E0E0E0', + panelSecondaryForeground: designSystemColors.shadesWhite90, + panelSecondaryForegroundBorder: designSystemColors.shadesWhite60, + purpleLink: designSystemColors.violetDark100, + purpleButton: designSystemColors.violetDark100, + reactionSelectionPopoverItemBackground: designSystemColors.shadesBlack80, + redText: designSystemColors.errorPrimary, + spoiler: designSystemColors.spoilerColor, + tabBarAccent: designSystemColors.violetDark100, + tabBarBackground: designSystemColors.shadesWhite90, + tabBarActiveTintColor: designSystemColors.violetDark100, + vibrantGreenButton: designSystemColors.successPrimary, + vibrantRedButton: designSystemColors.errorPrimary, + whiteText: designSystemColors.shadesWhite100, + tooltipBackground: designSystemColors.shadesWhite70, logInSpacer: '#FFFFFF33', - siweButton: '#FFFFFF', - siweButtonText: '#1F1F1F', - drawerExpandButton: '#808080', - drawerExpandButtonDisabled: '#CCCCCC', - drawerItemLabelLevel0: '#0A0A0A', - drawerItemLabelLevel1: '#0A0A0A', - drawerItemLabelLevel2: '#1F1F1F', - drawerOpenCommunityBackground: '#F5F5F5', - drawerBackground: '#FFFFFF', - subthreadsModalClose: '#808080', - subthreadsModalBackground: '#EBEBEB', + siweButton: designSystemColors.shadesWhite100, + siweButtonText: designSystemColors.shadesBlack90, + drawerExpandButton: designSystemColors.shadesBlack60, + drawerExpandButtonDisabled: designSystemColors.shadesWhite60, + drawerItemLabelLevel0: designSystemColors.shadesBlack100, + drawerItemLabelLevel1: designSystemColors.shadesBlack100, + drawerItemLabelLevel2: designSystemColors.shadesBlack90, + drawerOpenCommunityBackground: designSystemColors.shadesWhite90, + drawerBackground: designSystemColors.shadesWhite100, + subthreadsModalClose: designSystemColors.shadesBlack60, + subthreadsModalBackground: designSystemColors.shadesWhite80, subthreadsModalSearch: '#00000008', - messageLabel: '#0A0A0A', - modalSeparator: '#CCCCCC', - secondaryButtonBorder: '#FFFFFF', + messageLabel: designSystemColors.shadesBlack100, + modalSeparator: designSystemColors.shadesWhite60, + secondaryButtonBorder: designSystemColors.shadesWhite100, }); export type Colors = $Exact; const dark: Colors = Object.freeze({ blockQuoteBackground: '#A9A9A9', - blockQuoteBorder: '#808080', - codeBackground: '#0A0A0A', - disabledButton: '#404040', - disabledButtonText: '#808080', - disconnectedBarBackground: '#1F1F1F', - editButton: '#666666', - floatingButtonBackground: '#666666', - floatingButtonLabel: '#FFFFFF', - headerChevron: '#FFFFFF', - inlineEngagementBackground: '#666666', - inlineEngagementLabel: '#FFFFFF', - link: '#AE94DB', - listBackground: '#0A0A0A', - listBackgroundLabel: '#CCCCCC', + blockQuoteBorder: designSystemColors.shadesBlack60, + codeBackground: designSystemColors.shadesBlack100, + disabledButton: designSystemColors.shadesBlack80, + disabledButtonText: designSystemColors.shadesBlack60, + disconnectedBarBackground: designSystemColors.shadesBlack90, + editButton: designSystemColors.shadesBlack70, + floatingButtonBackground: designSystemColors.shadesBlack70, + floatingButtonLabel: designSystemColors.shadesWhite100, + headerChevron: designSystemColors.shadesWhite100, + inlineEngagementBackground: designSystemColors.shadesBlack70, + inlineEngagementLabel: designSystemColors.shadesWhite100, + link: designSystemColors.violetLight100, + listBackground: designSystemColors.shadesBlack100, + listBackgroundLabel: designSystemColors.shadesWhite60, listBackgroundSecondaryLabel: '#BBBBBB', - listBackgroundTernaryLabel: '#808080', + listBackgroundTernaryLabel: designSystemColors.shadesBlack60, listChatBubble: '#26252A', - listForegroundLabel: '#FFFFFF', - listForegroundSecondaryLabel: '#CCCCCC', - listForegroundTertiaryLabel: '#808080', - listInputBackground: '#1F1F1F', - listInputBar: '#666666', - listInputButton: '#CCCCCC', + listForegroundLabel: designSystemColors.shadesWhite100, + listForegroundSecondaryLabel: designSystemColors.shadesWhite60, + listForegroundTertiaryLabel: designSystemColors.shadesBlack60, + listInputBackground: designSystemColors.shadesBlack90, + listInputBar: designSystemColors.shadesBlack70, + listInputButton: designSystemColors.shadesWhite60, listIosHighlightUnderlay: '#BBBBBB88', - listSearchBackground: '#1F1F1F', - listSearchIcon: '#CCCCCC', - listSeparatorLabel: '#EBEBEB', - modalBackground: '#0A0A0A', - modalBackgroundLabel: '#CCCCCC', - modalBackgroundSecondaryLabel: '#666666', - modalButton: '#666666', - modalButtonLabel: '#FFFFFF', - modalContrastBackground: '#FFFFFF', - modalContrastForegroundLabel: '#0A0A0A', + listSearchBackground: designSystemColors.shadesBlack90, + listSearchIcon: designSystemColors.shadesWhite60, + listSeparatorLabel: designSystemColors.shadesWhite80, + modalBackground: designSystemColors.shadesBlack100, + modalBackgroundLabel: designSystemColors.shadesWhite60, + modalBackgroundSecondaryLabel: designSystemColors.shadesBlack70, + modalButton: designSystemColors.shadesBlack70, + modalButtonLabel: designSystemColors.shadesWhite100, + modalContrastBackground: designSystemColors.shadesWhite100, + modalContrastForegroundLabel: designSystemColors.shadesBlack100, modalContrastOpacity: 0.85, - modalForeground: '#1F1F1F', - modalForegroundBorder: '#1F1F1F', - modalForegroundLabel: '#FFFFFF', + modalForeground: designSystemColors.shadesBlack90, + modalForegroundBorder: designSystemColors.shadesBlack90, + modalForegroundLabel: designSystemColors.shadesWhite100, modalForegroundSecondaryLabel: '#AAAAAA', - modalForegroundTertiaryLabel: '#666666', + modalForegroundTertiaryLabel: designSystemColors.shadesBlack70, modalIosHighlightUnderlay: '#AAAAAA88', - modalSubtext: '#404040', + modalSubtext: designSystemColors.shadesBlack80, modalSubtextLabel: '#AAAAAA', navigationCard: '#2A2A2A', - navigationChevron: '#666666', - panelBackground: '#0A0A0A', - panelBackgroundLabel: '#CCCCCC', - panelForeground: '#1F1F1F', + navigationChevron: designSystemColors.shadesBlack70, + panelBackground: designSystemColors.shadesBlack100, + panelBackgroundLabel: designSystemColors.shadesWhite60, + panelForeground: designSystemColors.shadesBlack90, panelForegroundBorder: '#2C2C2E', - panelForegroundLabel: '#FFFFFF', - panelForegroundSecondaryLabel: '#CCCCCC', + panelForegroundLabel: designSystemColors.shadesWhite100, + panelForegroundSecondaryLabel: designSystemColors.shadesWhite60, panelForegroundTertiaryLabel: '#AAAAAA', panelIosHighlightUnderlay: '#313035', panelSecondaryForeground: '#333333', - panelSecondaryForegroundBorder: '#666666', - purpleLink: '#AE94DB', - purpleButton: '#7E57C2', - reactionSelectionPopoverItemBackground: '#404040', - redText: '#F53100', - spoiler: '#33332C', - tabBarAccent: '#AE94DB', - tabBarBackground: '#0A0A0A', - tabBarActiveTintColor: '#AE94DB', - vibrantGreenButton: '#00C853', - vibrantRedButton: '#F53100', - whiteText: '#FFFFFF', - tooltipBackground: '#1F1F1F', + panelSecondaryForegroundBorder: designSystemColors.shadesBlack70, + purpleLink: designSystemColors.violetLight100, + purpleButton: designSystemColors.violetDark100, + reactionSelectionPopoverItemBackground: designSystemColors.shadesBlack80, + redText: designSystemColors.errorPrimary, + spoiler: designSystemColors.spoilerColor, + tabBarAccent: designSystemColors.violetLight100, + tabBarBackground: designSystemColors.shadesBlack100, + tabBarActiveTintColor: designSystemColors.violetLight100, + vibrantGreenButton: designSystemColors.successPrimary, + vibrantRedButton: designSystemColors.errorPrimary, + whiteText: designSystemColors.shadesWhite100, + tooltipBackground: designSystemColors.shadesBlack90, logInSpacer: '#FFFFFF33', - siweButton: '#FFFFFF', - siweButtonText: '#1F1F1F', - drawerExpandButton: '#808080', - drawerExpandButtonDisabled: '#404040', - drawerItemLabelLevel0: '#CCCCCC', - drawerItemLabelLevel1: '#CCCCCC', - drawerItemLabelLevel2: '#F5F5F5', + siweButton: designSystemColors.shadesWhite100, + siweButtonText: designSystemColors.shadesBlack90, + drawerExpandButton: designSystemColors.shadesBlack60, + drawerExpandButtonDisabled: designSystemColors.shadesBlack80, + drawerItemLabelLevel0: designSystemColors.shadesWhite60, + drawerItemLabelLevel1: designSystemColors.shadesWhite60, + drawerItemLabelLevel2: designSystemColors.shadesWhite90, drawerOpenCommunityBackground: '#191919', - drawerBackground: '#1F1F1F', - subthreadsModalClose: '#808080', - subthreadsModalBackground: '#1F1F1F', + drawerBackground: designSystemColors.shadesBlack90, + subthreadsModalClose: designSystemColors.shadesBlack60, + subthreadsModalBackground: designSystemColors.shadesBlack90, subthreadsModalSearch: '#FFFFFF04', typeaheadTooltipBackground: '#1F1F1f', - typeaheadTooltipBorder: '#404040', + typeaheadTooltipBorder: designSystemColors.shadesBlack80, typeaheadTooltipText: 'white', - messageLabel: '#CCCCCC', - modalSeparator: '#404040', - secondaryButtonBorder: '#FFFFFF', + messageLabel: designSystemColors.shadesWhite60, + modalSeparator: designSystemColors.shadesBlack80, + secondaryButtonBorder: designSystemColors.shadesWhite100, }); const colors = { light, dark }; const colorsSelector: (state: AppState) => Colors = createSelector( (state: AppState) => state.globalThemeInfo.activeTheme, (theme: ?GlobalTheme) => { const explicitTheme = theme ? theme : 'light'; return colors[explicitTheme]; }, ); const magicStrings = new Set(); for (const theme in colors) { for (const magicString in colors[theme]) { magicStrings.add(magicString); } } type Styles = { [name: string]: { [field: string]: mixed } }; type ReplaceField = (input: any) => any; export type StyleSheetOf = $ObjMap; function stylesFromColors( obj: IS, themeColors: Colors, ): StyleSheetOf { const result = {}; for (const key in obj) { const style = obj[key]; const filledInStyle = { ...style }; for (const styleKey in style) { const styleValue = style[styleKey]; if (typeof styleValue !== 'string') { continue; } if (magicStrings.has(styleValue)) { const mapped = themeColors[styleValue]; if (mapped) { filledInStyle[styleKey] = mapped; } } } result[key] = filledInStyle; } return StyleSheet.create(result); } function styleSelector( obj: IS, ): (state: AppState) => StyleSheetOf { return createSelector(colorsSelector, (themeColors: Colors) => stylesFromColors(obj, themeColors), ); } function useStyles(obj: IS): StyleSheetOf { const ourColors = useColors(); return React.useMemo( () => stylesFromColors(obj, ourColors), [obj, ourColors], ); } function useOverlayStyles(obj: IS): StyleSheetOf { const navContext = React.useContext(NavContext); const navigationState = navContext && navContext.state; const theme = useSelector( (state: AppState) => state.globalThemeInfo.activeTheme, ); const backgroundIsDark = React.useMemo( () => selectBackgroundIsDark(navigationState, theme), [navigationState, theme], ); const syntheticTheme = backgroundIsDark ? 'dark' : 'light'; return React.useMemo( () => stylesFromColors(obj, colors[syntheticTheme]), [obj, syntheticTheme], ); } function useColors(): Colors { return useSelector(colorsSelector); } function getStylesForTheme( obj: IS, theme: GlobalTheme, ): StyleSheetOf { return stylesFromColors(obj, colors[theme]); } export type IndicatorStyle = 'white' | 'black'; function useIndicatorStyle(): IndicatorStyle { const theme = useSelector( (state: AppState) => state.globalThemeInfo.activeTheme, ); return theme && theme === 'dark' ? 'white' : 'black'; } const indicatorStyleSelector: (state: AppState) => IndicatorStyle = createSelector( (state: AppState) => state.globalThemeInfo.activeTheme, (theme: ?GlobalTheme) => { return theme && theme === 'dark' ? 'white' : 'black'; }, ); export type KeyboardAppearance = 'default' | 'light' | 'dark'; const keyboardAppearanceSelector: (state: AppState) => KeyboardAppearance = createSelector( (state: AppState) => state.globalThemeInfo.activeTheme, (theme: ?GlobalTheme) => { return theme && theme === 'dark' ? 'dark' : 'light'; }, ); function useKeyboardAppearance(): KeyboardAppearance { return useSelector(keyboardAppearanceSelector); } export { colors, colorsSelector, styleSelector, useStyles, useOverlayStyles, useColors, getStylesForTheme, useIndicatorStyle, indicatorStyleSelector, useKeyboardAppearance, };