diff --git a/client/public/locales/en/common.json b/client/public/locales/en/common.json index de65926..41875a0 100644 --- a/client/public/locales/en/common.json +++ b/client/public/locales/en/common.json @@ -348,6 +348,14 @@ "round_prices": { "label": "Round prices", "tooltip": "Round prices to the nearest whole number." + }, + "theme_color": { + "label": "Theme Color", + "orange": "Orange", + "teal": "Teal", + "red": "Red", + "green": "Green", + "blue": "Blue" } }, "backup": { diff --git a/client/src/contexts/color-mode/index.tsx b/client/src/contexts/color-mode/index.tsx index 2a08ccd..f01ae72 100644 --- a/client/src/contexts/color-mode/index.tsx +++ b/client/src/contexts/color-mode/index.tsx @@ -1,24 +1,43 @@ import { ConfigProvider, theme } from "antd"; import { createContext, PropsWithChildren, useEffect, useState } from "react"; +// Theme color options +export const THEME_COLORS = { + orange: "#f97316", + teal: "#0891b2", + red: "#dc2626", + green: "#16a34a", + blue: "#2563eb", +} as const; + +export type ThemeColorKey = keyof typeof THEME_COLORS; + type ColorModeContextType = { mode: string; setMode: (mode: string) => void; + themeColor: ThemeColorKey; + setThemeColor: (color: ThemeColorKey) => void; }; export const ColorModeContext = createContext({} as ColorModeContextType); export const ColorModeContextProvider: React.FC = ({ children }) => { const colorModeFromLocalStorage = localStorage.getItem("colorMode"); + const themeColorFromLocalStorage = localStorage.getItem("themeColor") as ThemeColorKey | null; const isSystemPreferenceDark = window?.matchMedia("(prefers-color-scheme: dark)").matches; const systemPreference = isSystemPreferenceDark ? "dark" : "light"; const [mode, setMode] = useState(colorModeFromLocalStorage || systemPreference); + const [themeColor, setThemeColorState] = useState(themeColorFromLocalStorage || "teal"); useEffect(() => { window.localStorage.setItem("colorMode", mode); }, [mode]); + useEffect(() => { + window.localStorage.setItem("themeColor", themeColor); + }, [themeColor]); + const setColorMode = () => { if (mode === "light") { setMode("dark"); @@ -27,22 +46,28 @@ export const ColorModeContextProvider: React.FC = ({ children } }; + const setThemeColor = (color: ThemeColorKey) => { + setThemeColorState(color); + }; + const { darkAlgorithm, defaultAlgorithm } = theme; + const primaryColor = THEME_COLORS[themeColor]; return ( diff --git a/client/src/pages/home/index.tsx b/client/src/pages/home/index.tsx index b72ca1d..525e219 100644 --- a/client/src/pages/home/index.tsx +++ b/client/src/pages/home/index.tsx @@ -38,16 +38,21 @@ export const Home: React.FC = () => { + e.stopPropagation()}> , - + e.stopPropagation()}> , ]} > - + + + ); diff --git a/client/src/pages/settings/generalSettings.tsx b/client/src/pages/settings/generalSettings.tsx index 366cbfd..e5100e0 100644 --- a/client/src/pages/settings/generalSettings.tsx +++ b/client/src/pages/settings/generalSettings.tsx @@ -2,9 +2,10 @@ import { DownloadOutlined, UploadOutlined } from "@ant-design/icons"; import { useTranslate } from "@refinedev/core"; import { Button, Checkbox, Divider, Form, Input, message, Popconfirm, Space, Upload } from "antd"; import type { UploadFile } from "antd"; -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { getAPIURL } from "../../utils/url"; import { useGetSettings, useSetSetting } from "../../utils/querySettings"; +import { ColorModeContext, THEME_COLORS, ThemeColorKey } from "../../contexts/color-mode"; export function GeneralSettings() { const settings = useGetSettings(); @@ -14,6 +15,7 @@ export function GeneralSettings() { const [form] = Form.useForm(); const [messageApi, contextHolder] = message.useMessage(); const t = useTranslate(); + const { themeColor, setThemeColor } = useContext(ColorModeContext); // Set initial form values useEffect(() => { @@ -107,6 +109,25 @@ export function GeneralSettings() { + + + {(Object.keys(THEME_COLORS) as ThemeColorKey[]).map((colorKey) => ( + + ))} + + +