mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: store various shades of accent color
This commit is contained in:
parent
ed0106200e
commit
7983be5eff
@ -13,29 +13,29 @@ import { ColorPickerInput } from "components/core";
|
|||||||
import userService from "services/user.service";
|
import userService from "services/user.service";
|
||||||
// helper
|
// helper
|
||||||
import { applyTheme } from "helpers/theme.helper";
|
import { applyTheme } from "helpers/theme.helper";
|
||||||
|
import { hexToRgb, rgbToHex } from "helpers/color.helper";
|
||||||
// types
|
// types
|
||||||
import { ICustomTheme } from "types";
|
import { ICustomTheme } from "types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
preLoadedData?: Partial<ICustomTheme> | null;
|
preLoadedData?: Partial<ICustomTheme> | null;
|
||||||
};
|
};
|
||||||
|
const defaultValues = {
|
||||||
|
"accent-500": "#FE5050",
|
||||||
|
bgBase: "#FFF7F7",
|
||||||
|
bgSurface1: "#FFE0E0",
|
||||||
|
bgSurface2: "#FFF7F7",
|
||||||
|
border: "#FFC9C9",
|
||||||
|
darkPalette: false,
|
||||||
|
palette: "",
|
||||||
|
sidebar: "#FFFFFF",
|
||||||
|
textBase: "#430000",
|
||||||
|
textSecondary: "#323232",
|
||||||
|
};
|
||||||
|
|
||||||
export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
||||||
const [darkPalette, setDarkPalette] = useState(false);
|
const [darkPalette, setDarkPalette] = useState(false);
|
||||||
|
|
||||||
const defaultValues = {
|
|
||||||
accent: preLoadedData?.accent ?? "#FE5050",
|
|
||||||
bgBase: preLoadedData?.bgBase ?? "#FFF7F7",
|
|
||||||
bgSurface1: preLoadedData?.bgSurface1 ?? "#FFE0E0",
|
|
||||||
bgSurface2: preLoadedData?.bgSurface2 ?? "#FFF7F7",
|
|
||||||
border: preLoadedData?.border ?? "#FFC9C9",
|
|
||||||
darkPalette: preLoadedData?.darkPalette ?? false,
|
|
||||||
palette: preLoadedData?.palette ?? "",
|
|
||||||
sidebar: preLoadedData?.sidebar ?? "#FFFFFF",
|
|
||||||
textBase: preLoadedData?.textBase ?? "#430000",
|
|
||||||
textSecondary: preLoadedData?.textSecondary ?? "#323232",
|
|
||||||
};
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
formState: { errors, isSubmitting },
|
formState: { errors, isSubmitting },
|
||||||
@ -50,17 +50,66 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
|||||||
const { setTheme } = useTheme();
|
const { setTheme } = useTheme();
|
||||||
const { mutateUser } = useUser();
|
const { mutateUser } = useUser();
|
||||||
|
|
||||||
|
const calculateShade = (hexValue: string, shade: number): string => {
|
||||||
|
const { r, g, b } = hexToRgb(hexValue);
|
||||||
|
|
||||||
|
if (shade > 500) {
|
||||||
|
let decimalValue = 0.1;
|
||||||
|
|
||||||
|
if (shade === 600) decimalValue = 0.1;
|
||||||
|
else if (shade === 700) decimalValue = 0.2;
|
||||||
|
else if (shade === 800) decimalValue = 0.3;
|
||||||
|
else if (shade === 900) decimalValue = 0.4;
|
||||||
|
|
||||||
|
const newR = Math.ceil(r * decimalValue);
|
||||||
|
const newG = Math.ceil(g * decimalValue);
|
||||||
|
const newB = Math.ceil(b * decimalValue);
|
||||||
|
|
||||||
|
return rgbToHex({ r: newR, g: newG, b: newB });
|
||||||
|
} else {
|
||||||
|
const decimalValue = 1 - (shade * 2) / 1000;
|
||||||
|
|
||||||
|
const newR = Math.floor(r + (255 - r) * decimalValue);
|
||||||
|
const newG = Math.floor(g + (255 - g) * decimalValue);
|
||||||
|
const newB = Math.floor(b + (255 - b) * decimalValue);
|
||||||
|
|
||||||
|
return rgbToHex({ r: newR, g: newG, b: newB });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleFormSubmit = async (formData: any) => {
|
const handleFormSubmit = async (formData: any) => {
|
||||||
|
const accent = {
|
||||||
|
50: calculateShade(formData["accent-500"], 50),
|
||||||
|
100: calculateShade(formData["accent-500"], 100),
|
||||||
|
200: calculateShade(formData["accent-500"], 200),
|
||||||
|
300: calculateShade(formData["accent-500"], 300),
|
||||||
|
400: calculateShade(formData["accent-500"], 400),
|
||||||
|
500: formData["accent-500"],
|
||||||
|
600: calculateShade(formData["accent-500"], 600),
|
||||||
|
700: calculateShade(formData["accent-500"], 700),
|
||||||
|
800: calculateShade(formData["accent-500"], 800),
|
||||||
|
900: calculateShade(formData["accent-500"], 900),
|
||||||
|
};
|
||||||
|
|
||||||
await userService
|
await userService
|
||||||
.updateUser({
|
.updateUser({
|
||||||
theme: {
|
theme: {
|
||||||
accent: formData.accent,
|
"accent-50": accent[50],
|
||||||
|
"accent-100": accent[100],
|
||||||
|
"accent-200": accent[200],
|
||||||
|
"accent-300": accent[300],
|
||||||
|
"accent-400": accent[400],
|
||||||
|
"accent-500": accent[500],
|
||||||
|
"accent-600": accent[600],
|
||||||
|
"accent-700": accent[700],
|
||||||
|
"accent-800": accent[800],
|
||||||
|
"accent-900": accent[900],
|
||||||
bgBase: formData.bgBase,
|
bgBase: formData.bgBase,
|
||||||
bgSurface1: formData.bgSurface1,
|
bgSurface1: formData.bgSurface1,
|
||||||
bgSurface2: formData.bgSurface2,
|
bgSurface2: formData.bgSurface2,
|
||||||
border: formData.border,
|
border: formData.border,
|
||||||
darkPalette: darkPalette,
|
darkPalette: darkPalette,
|
||||||
palette: `${formData.bgBase},${formData.bgSurface1},${formData.bgSurface2},${formData.border},${formData.sidebar},${formData.accent},${formData.textBase},${formData.textSecondary}`,
|
palette: `${formData.bgBase},${formData.bgSurface1},${formData.bgSurface2},${formData.border},${formData.sidebar},${accent[50]},${accent[100]},${accent[200]},${accent[300]},${accent[400]},${accent[500]},${accent[600]},${accent[700]},${accent[800]},${accent[900]},${formData.textBase},${formData.textSecondary}`,
|
||||||
sidebar: formData.sidebar,
|
sidebar: formData.sidebar,
|
||||||
textBase: formData.textBase,
|
textBase: formData.textBase,
|
||||||
textSecondary: formData.textSecondary,
|
textSecondary: formData.textSecondary,
|
||||||
@ -69,8 +118,10 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
|||||||
.then((res) => {
|
.then((res) => {
|
||||||
mutateUser((prevData) => {
|
mutateUser((prevData) => {
|
||||||
if (!prevData) return prevData;
|
if (!prevData) return prevData;
|
||||||
return { ...prevData, user: res };
|
|
||||||
|
return { ...prevData, ...res };
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
applyTheme(formData.palette, darkPalette);
|
applyTheme(formData.palette, darkPalette);
|
||||||
setTheme("custom");
|
setTheme("custom");
|
||||||
})
|
})
|
||||||
@ -79,10 +130,6 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
|||||||
|
|
||||||
const handleUpdateTheme = async (formData: any) => {
|
const handleUpdateTheme = async (formData: any) => {
|
||||||
await handleFormSubmit({ ...formData, darkPalette });
|
await handleFormSubmit({ ...formData, darkPalette });
|
||||||
|
|
||||||
reset({
|
|
||||||
...defaultValues,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -156,8 +203,8 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
|||||||
<div className="flex flex-col items-start gap-2">
|
<div className="flex flex-col items-start gap-2">
|
||||||
<h3 className="text-left text-base text-brand-secondary">Accent</h3>
|
<h3 className="text-left text-base text-brand-secondary">Accent</h3>
|
||||||
<ColorPickerInput
|
<ColorPickerInput
|
||||||
name="accent"
|
name="accent-500"
|
||||||
error={errors.accent}
|
error={errors["accent-500"]}
|
||||||
watch={watch}
|
watch={watch}
|
||||||
setValue={setValue}
|
setValue={setValue}
|
||||||
register={register}
|
register={register}
|
||||||
|
@ -83,10 +83,20 @@ export const ThemeSwitch: React.FC<Props> = ({
|
|||||||
"--color-bg-base",
|
"--color-bg-base",
|
||||||
"--color-bg-surface-1",
|
"--color-bg-surface-1",
|
||||||
"--color-bg-surface-2",
|
"--color-bg-surface-2",
|
||||||
|
"--color-bg-sidebar",
|
||||||
|
|
||||||
"--color-border",
|
"--color-border",
|
||||||
"--color-bg-sidebar",
|
|
||||||
"--color-accent",
|
"--color-accent-50",
|
||||||
|
"--color-accent-100",
|
||||||
|
"--color-accent-200",
|
||||||
|
"--color-accent-300",
|
||||||
|
"--color-accent-400",
|
||||||
|
"--color-accent-500",
|
||||||
|
"--color-accent-600",
|
||||||
|
"--color-accent-700",
|
||||||
|
"--color-accent-800",
|
||||||
|
"--color-accent-900",
|
||||||
|
|
||||||
"--color-text-base",
|
"--color-text-base",
|
||||||
"--color-text-secondary",
|
"--color-text-secondary",
|
||||||
|
19
apps/app/helpers/color.helper.ts
Normal file
19
apps/app/helpers/color.helper.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
export type TRgb = { r: number; g: number; b: number };
|
||||||
|
|
||||||
|
export const hexToRgb = (hex: string): TRgb => {
|
||||||
|
const r = parseInt(hex.slice(1, 3), 16);
|
||||||
|
const g = parseInt(hex.slice(3, 5), 16);
|
||||||
|
const b = parseInt(hex.slice(5, 7), 16);
|
||||||
|
|
||||||
|
return { r, g, b };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rgbToHex = (rgb: TRgb): string => {
|
||||||
|
const { r, g, b } = rgb;
|
||||||
|
|
||||||
|
const hexR = r.toString(16).padStart(2, "0");
|
||||||
|
const hexG = g.toString(16).padStart(2, "0");
|
||||||
|
const hexB = b.toString(16).padStart(2, "0");
|
||||||
|
|
||||||
|
return `#${hexR}${hexG}${hexB}`;
|
||||||
|
};
|
@ -19,7 +19,16 @@ export const applyTheme = (palette: string, isDarkPalette: boolean) => {
|
|||||||
"--color-bg-surface-2",
|
"--color-bg-surface-2",
|
||||||
"--color-border",
|
"--color-border",
|
||||||
"--color-bg-sidebar",
|
"--color-bg-sidebar",
|
||||||
"--color-accent",
|
"--color-accent-50",
|
||||||
|
"--color-accent-100",
|
||||||
|
"--color-accent-200",
|
||||||
|
"--color-accent-300",
|
||||||
|
"--color-accent-400",
|
||||||
|
"--color-accent-500",
|
||||||
|
"--color-accent-600",
|
||||||
|
"--color-accent-700",
|
||||||
|
"--color-accent-800",
|
||||||
|
"--color-accent-900",
|
||||||
"--color-text-base",
|
"--color-text-base",
|
||||||
"--color-text-secondary",
|
"--color-text-secondary",
|
||||||
"color-scheme",
|
"color-scheme",
|
||||||
|
@ -23,7 +23,16 @@
|
|||||||
|
|
||||||
--color-border: 229, 231, 235;
|
--color-border: 229, 231, 235;
|
||||||
--color-bg-sidebar: 255, 255, 255;
|
--color-bg-sidebar: 255, 255, 255;
|
||||||
--color-accent: 63, 118, 255;
|
--color-accent-50: 63, 118, 255;
|
||||||
|
--color-accent-100: 63, 118, 255;
|
||||||
|
--color-accent-200: 63, 118, 255;
|
||||||
|
--color-accent-300: 63, 118, 255;
|
||||||
|
--color-accent-400: 63, 118, 255;
|
||||||
|
--color-accent-500: 63, 118, 255;
|
||||||
|
--color-accent-600: 63, 118, 255;
|
||||||
|
--color-accent-700: 63, 118, 255;
|
||||||
|
--color-accent-800: 63, 118, 255;
|
||||||
|
--color-accent-900: 63, 118, 255;
|
||||||
|
|
||||||
--color-text-base: 3, 7, 18;
|
--color-text-base: 3, 7, 18;
|
||||||
--color-text-secondary: 55, 65, 81;
|
--color-text-secondary: 55, 65, 81;
|
||||||
|
@ -6,9 +6,7 @@ function withOpacity(variableName) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToRGB(variableName) {
|
const convertToRGB = (variableName) => `rgb(var(${variableName}))`;
|
||||||
return `rgb(var(${variableName}))`;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
darkMode: "class",
|
darkMode: "class",
|
||||||
@ -17,7 +15,19 @@ module.exports = {
|
|||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
brand: {
|
brand: {
|
||||||
accent: withOpacity("--color-accent"),
|
accent: {
|
||||||
|
50: convertToRGB("--color-accent-50"),
|
||||||
|
100: convertToRGB("--color-accent-100"),
|
||||||
|
200: convertToRGB("--color-accent-200"),
|
||||||
|
300: convertToRGB("--color-accent-300"),
|
||||||
|
400: convertToRGB("--color-accent-400"),
|
||||||
|
500: convertToRGB("--color-accent-500"),
|
||||||
|
600: convertToRGB("--color-accent-600"),
|
||||||
|
700: convertToRGB("--color-accent-700"),
|
||||||
|
800: convertToRGB("--color-accent-800"),
|
||||||
|
900: convertToRGB("--color-accent-900"),
|
||||||
|
DEFAULT: convertToRGB("--color-accent-500"),
|
||||||
|
},
|
||||||
base: withOpacity("--color-bg-base"),
|
base: withOpacity("--color-bg-base"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
11
apps/app/types/users.d.ts
vendored
11
apps/app/types/users.d.ts
vendored
@ -29,7 +29,16 @@ export interface IUser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ICustomTheme {
|
export interface ICustomTheme {
|
||||||
accent: string;
|
"accent-50": string;
|
||||||
|
"accent-100": string;
|
||||||
|
"accent-200": string;
|
||||||
|
"accent-300": string;
|
||||||
|
"accent-400": string;
|
||||||
|
"accent-500": string;
|
||||||
|
"accent-600": string;
|
||||||
|
"accent-700": string;
|
||||||
|
"accent-800": string;
|
||||||
|
"accent-900": string;
|
||||||
bgBase: string;
|
bgBase: string;
|
||||||
bgSurface1: string;
|
bgSurface1: string;
|
||||||
bgSurface2: string;
|
bgSurface2: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user