Skip to content

Commit

Permalink
Support theme (light and dark) colors in the JS code
Browse files Browse the repository at this point in the history
  • Loading branch information
roienatan committed Nov 22, 2023
1 parent b7ce3c3 commit 8e19370
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 111 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React from "react";
import { useSelector } from "react-redux";
import Select, { components, DropdownIndicatorProps } from "react-select";
import { useFormikContext } from "formik";
import { ProposalsTypes } from "@/shared/constants";
import { Theme } from "@/shared/constants";
import { RightArrowThinIcon } from "@/shared/icons";
import { NewProposalCreationFormValues } from "@/shared/interfaces";
import { selectTheme } from "@/shared/store/selectors";
import { selectorStyles } from "./selectorStyles";
import styles from "./ProposalTypeSelect.module.scss";

Expand Down Expand Up @@ -42,7 +39,6 @@ const ProposalTypeSelect = ({ commonBalance }: ProposalTypeSelectProps) => {
const { values, setFieldValue, handleBlur, touched, errors } =
useFormikContext<NewProposalCreationFormValues>();
const hasError = Boolean(touched.proposalType && errors.proposalType);
const theme = useSelector(selectTheme);

return (
<div className={styles.container}>
Expand All @@ -56,7 +52,7 @@ const ProposalTypeSelect = ({ commonBalance }: ProposalTypeSelectProps) => {
}}
onBlur={handleBlur("proposalType")}
hideSelectedOptions={false}
styles={selectorStyles(hasError, theme === Theme.Dark)}
styles={selectorStyles(hasError)}
components={{
DropdownIndicator,
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
import { Colors } from "@/shared/constants";
import { ThemeColors } from "@/shared/constants";
import useThemeColor from "@/shared/hooks/useThemeColor";

export const selectorStyles = (hasError: boolean, isDarkMode: boolean) => ({
menu: (provided) => ({ ...provided, zIndex: 10000 }),
menuPortal: (provided) => ({ ...provided, zIndex: 10000 }),
menuList: (provided) => ({
...provided,
backgroundColor: isDarkMode ? "#131b23" : "#ffffff",
}),
control: (provided) => ({
...provided,
height: "3rem",
...(hasError && { borderColor: Colors.error }),
backgroundColor: isDarkMode ? "#2e3452" : "#f8f8f5",
color: isDarkMode ? "#ffffff" : "#001a36",
borderColor: "rgba(255, 255, 255, 0)",
boxShadow: "rgba(255, 255, 255, 0)",
"&:hover": {
export const selectorStyles = (hasError: boolean) => {
const { getThemeColor } = useThemeColor();

return {
menu: (provided) => ({ ...provided, zIndex: 10000 }),
menuPortal: (provided) => ({ ...provided, zIndex: 10000 }),
menuList: (provided) => ({
...provided,
backgroundColor: getThemeColor(ThemeColors.tertiaryFill),
}),
control: (provided) => ({
...provided,
height: "3rem",
...(hasError && { borderColor: getThemeColor(ThemeColors.warning) }),
backgroundColor: getThemeColor(ThemeColors.secondaryBackground),
color: getThemeColor(ThemeColors.primaryText),
borderColor: "rgba(255, 255, 255, 0)",
boxShadow: "rgba(255, 255, 255, 0)",
},
}),
option: (provided, data) => ({
...provided,
backgroundColor: data.isDisabled
? "transparent"
: isDarkMode
? "#131b23"
: "#ffffff",
color: isDarkMode ? "#ffffff" : "#001a36",
"&:hover": {
"&:hover": {
boxShadow: "rgba(255, 255, 255, 0)",
},
}),
option: (provided, data) => ({
...provided,
backgroundColor: data.isDisabled
? ""
: isDarkMode
? "#2e3452"
: "#fff9fd",
},
cursor: data.isDisabled ? "not-allowed" : "default",
}),
indicatorSeparator: () => ({ display: "none" }),
indicatorsContainer: (provided) => ({
...provided,
color: isDarkMode ? "#ffffff" : "#001a36",
}),
singleValue: (provided) => ({
...provided,
backgroundColor: isDarkMode ? "#2e3452" : "#f8f8f5",
color: isDarkMode ? "#ffffff" : "#001a36",
}),
});
? "transparent"
: getThemeColor(ThemeColors.tertiaryFill),
color: getThemeColor(ThemeColors.primaryText),
"&:hover": {
backgroundColor: data.isDisabled
? ""
: getThemeColor(ThemeColors.secondaryBackground),
},
cursor: data.isDisabled ? "not-allowed" : "default",
}),
indicatorSeparator: () => ({ display: "none" }),
indicatorsContainer: (provided) => ({
...provided,
color: getThemeColor(ThemeColors.primaryText),
}),
singleValue: (provided) => ({
...provided,
backgroundColor: getThemeColor(ThemeColors.secondaryBackground),
color: getThemeColor(ThemeColors.primaryText),
}),
};
};
6 changes: 1 addition & 5 deletions src/shared/components/Form/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import React, { FC } from "react";
import { useSelector } from "react-redux";
import Select, { components, DropdownIndicatorProps } from "react-select";
import classNames from "classnames";
import { useFormikContext } from "formik";
import { Theme } from "@/shared/constants/theme";
import { RightArrowThinIcon } from "@/shared/icons";
import { SelectOptionType } from "@/shared/interfaces/Select";
import { selectTheme } from "@/shared/store/selectors";
import { selectorStyles } from "./selectorStyles";
import styles from "./Select.module.scss";

Expand Down Expand Up @@ -42,7 +39,6 @@ const FormSelect: FC<FormSelectProps> = ({
const { values, setFieldValue, handleBlur, touched, errors } =
useFormikContext<Record<string, unknown>>();
const hasError = Boolean(touched[formName] && errors[formName]);
const theme = useSelector(selectTheme);

return (
<div className={classNames(styles.container, containerClassName)}>
Expand All @@ -58,7 +54,7 @@ const FormSelect: FC<FormSelectProps> = ({
}}
onBlur={handleBlur(formName)}
hideSelectedOptions={false}
styles={selectorStyles(hasError, theme === Theme.Dark)}
styles={selectorStyles(hasError)}
components={{
DropdownIndicator,
}}
Expand Down
93 changes: 47 additions & 46 deletions src/shared/components/Form/Select/selectorStyles.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
import { Colors } from "@/shared/constants";
import { ThemeColors } from "@/shared/constants";
import useThemeColor from "@/shared/hooks/useThemeColor";

export const selectorStyles = (hasError: boolean, isDarkMode: boolean) => ({
menu: (provided) => ({ ...provided, zIndex: 10000 }),
menuPortal: (provided) => ({ ...provided, zIndex: 10000 }),
menuList: (provided) => ({
...provided,
backgroundColor: isDarkMode ? "#131b23" : "#ffffff",
}),
control: (provided) => ({
...provided,
height: "3rem",
...(hasError && { borderColor: Colors.error }),
backgroundColor: isDarkMode ? "#2e3452" : "#f8f8f5",
color: isDarkMode ? "#ffffff" : "#001a36",
borderColor: "rgba(255, 255, 255, 0)",
boxShadow: "rgba(255, 255, 255, 0)",
"&:hover": {
export const selectorStyles = (hasError: boolean) => {
const { getThemeColor } = useThemeColor();

return {
menu: (provided) => ({ ...provided, zIndex: 10000 }),
menuPortal: (provided) => ({ ...provided, zIndex: 10000 }),
menuList: (provided) => ({
...provided,
backgroundColor: getThemeColor(ThemeColors.tertiaryFill),
}),
control: (provided) => ({
...provided,
height: "3rem",
...(hasError && { borderColor: getThemeColor(ThemeColors.warning) }),
backgroundColor: getThemeColor(ThemeColors.secondaryBackground),
color: getThemeColor(ThemeColors.primaryText),
borderColor: "rgba(255, 255, 255, 0)",
boxShadow: "rgba(255, 255, 255, 0)",
},
}),
indicatorSeparator: () => ({ display: "none" }),
indicatorsContainer: (provided) => ({
...provided,
color: isDarkMode ? "#ffffff" : "#001a36",
}),
option: (provided, data) => ({
...provided,
backgroundColor: data.isDisabled
? "transparent"
: isDarkMode
? "#131b23"
: "#ffffff",
color: isDarkMode ? "#ffffff" : "#001a36",
"&:hover": {
"&:hover": {
boxShadow: "rgba(255, 255, 255, 0)",
},
}),
indicatorSeparator: () => ({ display: "none" }),
indicatorsContainer: (provided) => ({
...provided,
color: getThemeColor(ThemeColors.primaryText),
}),
option: (provided, data) => ({
...provided,
backgroundColor: data.isDisabled
? ""
: isDarkMode
? "#2e3452"
: "#fff9fd",
},
cursor: data.isDisabled ? "not-allowed" : "default",
}),
singleValue: (provided) => ({
...provided,
backgroundColor: isDarkMode ? "#2e3452" : "#f8f8f5",
color: isDarkMode ? "#ffffff" : "#001a36",
}),
});
? "transparent"
: getThemeColor(ThemeColors.tertiaryFill),
color: getThemeColor(ThemeColors.primaryText),
"&:hover": {
backgroundColor: data.isDisabled
? ""
: getThemeColor(ThemeColors.secondaryBackground),
},
cursor: data.isDisabled ? "not-allowed" : "default",
}),
singleValue: (provided) => ({
...provided,
backgroundColor: getThemeColor(ThemeColors.secondaryBackground),
color: getThemeColor(ThemeColors.primaryText),
}),
};
};
49 changes: 49 additions & 0 deletions src/shared/constants/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,52 @@ export enum Theme {
Light = "light",
Dark = "dark",
}

export enum ThemeColors {
primaryBackground,
secondaryBackground,
hoverFill,
secondaryHoverFill,
primaryText,
secondaryText,
gentleStroke,
warning,
primaryFill,
secondaryFill,
tertiaryFill,
quaternaryFill,
dropShadow,
}

export const ThemeColorsValues = {
[Theme.Light]: {
[ThemeColors.primaryBackground]: "#ffffff",
[ThemeColors.secondaryBackground]: "#f8f8f5",
[ThemeColors.hoverFill]: "#fff9fd",
[ThemeColors.secondaryHoverFill]: "#fff9fd",
[ThemeColors.primaryText]: "#001a36",
[ThemeColors.secondaryText]: "#a75a93",
[ThemeColors.gentleStroke]: "#f4f5f5",
[ThemeColors.warning]: "#ff603e",
[ThemeColors.primaryFill]: "#c32ea3",
[ThemeColors.secondaryFill]: "#f3d4eb",
[ThemeColors.tertiaryFill]: "#ffffff",
[ThemeColors.quaternaryFill]: "#d5d5e4",
[ThemeColors.dropShadow]: "rgba(0, 0, 0, 0.15259)",
},
[Theme.Dark]: {
[ThemeColors.primaryBackground]: "#1f2535",
[ThemeColors.secondaryBackground]: "#2e3452",
[ThemeColors.hoverFill]: "#131b23",
[ThemeColors.secondaryHoverFill]: "#2e3452",
[ThemeColors.primaryText]: "#ffffff",
[ThemeColors.secondaryText]: "#a75a93",
[ThemeColors.gentleStroke]: "#2e3452",
[ThemeColors.warning]: "#ff603e",
[ThemeColors.primaryFill]: "#c32ea3",
[ThemeColors.secondaryFill]: "#743b65",
[ThemeColors.tertiaryFill]: "#131b23",
[ThemeColors.quaternaryFill]: "#525876",
[ThemeColors.dropShadow]: "rgba(0, 0, 0, 0.15259)",
},
};
23 changes: 23 additions & 0 deletions src/shared/hooks/useThemeColor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useCallback } from "react";
import { useSelector } from "react-redux";
import { ThemeColors, ThemeColorsValues } from "../constants";
import { selectTheme } from "../store/selectors";

interface Return {
getThemeColor: (color: ThemeColors) => string;
}

const useThemeColor = (): Return => {
const theme = useSelector(selectTheme);

const getThemeColor = useCallback(
(color: ThemeColors) => {
return ThemeColorsValues[theme][color];
},
[theme],
);

return { getThemeColor };
};

export default useThemeColor;
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import React, { FC } from "react";
import ContentLoader from "react-content-loader";
import { useSelector } from "react-redux";
import { Theme } from "@/shared/constants";
import { selectTheme } from "@/shared/store/selectors";
import { ThemeColors } from "@/shared/constants";
import useThemeColor from "@/shared/hooks/useThemeColor";
import { Separator } from "../Separator";
import styles from "./LoadingBreadcrumbsItem.module.scss";

const LoadingBreadcrumbsItem: FC = (props) => {
const theme = useSelector(selectTheme);

const backgroundColor = theme === Theme.Light ? "#f3f3f3" : "#1f2535";
const foregroundColor = theme === Theme.Light ? "#ecebeb" : "#2e3452";
const { getThemeColor } = useThemeColor();

return (
<li className={styles.container}>
Expand All @@ -19,8 +15,8 @@ const LoadingBreadcrumbsItem: FC = (props) => {
width={296}
height={22}
viewBox="0 0 296 22"
backgroundColor={backgroundColor}
foregroundColor={foregroundColor}
backgroundColor={getThemeColor(ThemeColors.primaryBackground)}
foregroundColor={getThemeColor(ThemeColors.secondaryBackground)}
{...props}
>
<rect x="0" y="0" rx="4" ry="4" width="120" height="22" />
Expand Down

0 comments on commit 8e19370

Please sign in to comment.