From f71481b2e4072cf073fb6827a8ffa6d5f4bf3391 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Tue, 4 Jul 2023 11:37:26 +0530 Subject: [PATCH] chore: new theming structure --- .../components/core/custom-theme-selector.tsx | 101 ++----------- apps/app/components/core/theme-switch.tsx | 16 +- apps/app/helpers/theme.helper.ts | 137 +++++++++++++----- apps/app/pages/colors.tsx | 48 ++++++ apps/app/styles/globals.css | 49 ++++--- apps/app/tailwind.config.js | 21 ++- apps/app/types/users.d.ts | 17 +-- 7 files changed, 222 insertions(+), 167 deletions(-) create mode 100644 apps/app/pages/colors.tsx diff --git a/apps/app/components/core/custom-theme-selector.tsx b/apps/app/components/core/custom-theme-selector.tsx index c0995a36a..76883f864 100644 --- a/apps/app/components/core/custom-theme-selector.tsx +++ b/apps/app/components/core/custom-theme-selector.tsx @@ -13,22 +13,20 @@ import { ColorPickerInput } from "components/core"; import userService from "services/user.service"; // helper import { applyTheme } from "helpers/theme.helper"; -import { hexToRgb, rgbToHex } from "helpers/color.helper"; // types import { ICustomTheme } from "types"; type Props = { preLoadedData?: Partial | null; }; + const defaultValues = { - "accent-500": "#FE5050", - bgBase: "#FFF7F7", - bgSurface1: "#FFE0E0", - bgSurface2: "#FFF7F7", - border: "#FFC9C9", + accent: "#fe5050", + background: "#fff7f7", + border: "#ffc9c9", darkPalette: false, palette: "", - sidebar: "#FFFFFF", + sidebar: "#ffffff", textBase: "#430000", textSecondary: "#323232", }; @@ -43,62 +41,20 @@ export const CustomThemeSelector: React.FC = ({ preLoadedData }) => { watch, setValue, reset, - } = useForm({ + } = useForm({ defaultValues, }); const { setTheme } = useTheme(); 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.9; - else if (shade === 700) decimalValue = 0.8; - else if (shade === 800) decimalValue = 0.7; - else if (shade === 900) decimalValue = 0.6; - - 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 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), - }; - + const handleFormSubmit = async (formData: ICustomTheme) => { const payload: ICustomTheme = { - accent, - bgBase: formData.bgBase, - bgSurface1: formData.bgSurface1, - bgSurface2: formData.bgSurface2, + accent: formData.accent, + background: formData.background, border: formData.border, darkPalette: darkPalette, - 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}`, + palette: `${formData.background},${formData.border},${formData.sidebar},${formData.accent},${formData.textBase},${formData.textSecondary}`, sidebar: formData.sidebar, textBase: formData.textBase, textSecondary: formData.textSecondary, @@ -129,7 +85,6 @@ export const CustomThemeSelector: React.FC = ({ preLoadedData }) => { reset({ ...defaultValues, ...preLoadedData, - "accent-500": preLoadedData?.accent?.[500] || "#FE5050", }); }, [preLoadedData, reset]); @@ -141,37 +96,11 @@ export const CustomThemeSelector: React.FC = ({ preLoadedData }) => {

- Primary background color + Background color

-
- -
-

- Secondary background color -

- -
- -
-

- Tertiary background color -

- = ({ preLoadedData }) => {

Accent color

= ({ } else { if (customThemeSelectorOptions) setCustomThemeSelectorOptions(false); const cssVars = [ - "--color-bg-base", - "--color-bg-surface-1", - "--color-bg-surface-2", + "--color-bg-50", + "--color-bg-100", + "--color-bg-200", + "--color-bg-300", + "--color-bg-400", + "--color-bg-500", + "--color-bg-600", + "--color-bg-700", + "--color-bg-800", + "--color-bg-900", + "--color-bg-sidebar", "--color-border", diff --git a/apps/app/helpers/theme.helper.ts b/apps/app/helpers/theme.helper.ts index 315679719..7edf56488 100644 --- a/apps/app/helpers/theme.helper.ts +++ b/apps/app/helpers/theme.helper.ts @@ -1,44 +1,107 @@ -export const hexToRgb = (hex: string) => { - hex = hex.toLowerCase(); - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result - ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)].join(",") - : null; -}; +import { TRgb, hexToRgb } from "helpers/color.helper"; export const applyTheme = (palette: string, isDarkPalette: boolean) => { - const values: string[] = []; - palette.split(",").map((color: string) => { - const cssVarColor = hexToRgb(color); - if (cssVarColor) values.push(cssVarColor); - }); - - const cssVars = [ - "--color-bg-base", - "--color-bg-surface-1", - "--color-bg-surface-2", - "--color-border", - "--color-bg-sidebar", - "--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-secondary", - "color-scheme", - ]; - + // palette: [bg, border, sidebarBg, accent, textBase, textSecondary, scheme] + const values: string[] = palette.split(","); values.push(isDarkPalette ? "dark" : "light"); - cssVars.forEach((cssVar, i) => + for (let i = 0; i < 10; i++) { + const bgShades = calculateShades(values[0]); + const accentShades = calculateShades(values[3]); + + const shade = (i === 0 ? 50 : i * 100) as keyof TShades; + + const bgRgbValues = `${bgShades[shade].r}, ${bgShades[shade].g}, ${bgShades[shade].b}`; + const accentRgbValues = `${accentShades[shade].r}, ${accentShades[shade].g}, ${accentShades[shade].b}`; + document .querySelector("[data-theme='custom']") - ?.style.setProperty(cssVar, values[i]) - ); + ?.style.setProperty(`--color-bg-${shade}`, bgRgbValues); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty(`--color-accent-${shade}`, accentRgbValues); + } + + const border = hexToRgb(values[1]); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty("--color-border", `${border.r}, ${border.g}, ${border.b}`); + + const sidebarBg = hexToRgb(values[2]); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty("--color-bg-sidebar", `${sidebarBg.r}, ${sidebarBg.g}, ${sidebarBg.b}`); + + const textBase = hexToRgb(values[4]); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty("--color-text-base", `${textBase.r}, ${textBase.g}, ${textBase.b}`); + + const textSecondary = hexToRgb(values[5]); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty( + "--color-text-secondary", + `${textSecondary.r}, ${textSecondary.g}, ${textSecondary.b}` + ); + document + .querySelector("[data-theme='custom']") + ?.style.setProperty("--color-scheme", values[6]); +}; + +type TShades = { + 50: TRgb; + 100: TRgb; + 200: TRgb; + 300: TRgb; + 400: TRgb; + 500: TRgb; + 600: TRgb; + 700: TRgb; + 800: TRgb; + 900: TRgb; +}; + +const calculateShades = (hexValue: string): TShades => { + const shades: Partial = {}; + + const convertHexToSpecificShade = (shade: number): TRgb => { + const { r, g, b } = hexToRgb(hexValue); + + if (shade > 500) { + let decimalValue = 0.1; + + if (shade === 600) decimalValue = 0.9; + else if (shade === 700) decimalValue = 0.8; + else if (shade === 800) decimalValue = 0.7; + else if (shade === 900) decimalValue = 0.6; + + const newR = Math.ceil(r * decimalValue); + const newG = Math.ceil(g * decimalValue); + const newB = Math.ceil(b * decimalValue); + + return { + 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 { + r: newR, + g: newG, + b: newB, + }; + } + }; + + shades[50] = convertHexToSpecificShade(50); + for (let i = 100; i <= 900; i += 100) shades[i as keyof TShades] = convertHexToSpecificShade(i); + + return shades as TShades; }; diff --git a/apps/app/pages/colors.tsx b/apps/app/pages/colors.tsx new file mode 100644 index 000000000..e26d26145 --- /dev/null +++ b/apps/app/pages/colors.tsx @@ -0,0 +1,48 @@ +import React from "react"; + +// layouts +import DefaultLayout from "layouts/default-layout"; +import { UserAuthorizationLayout } from "layouts/auth-layout/user-authorization-wrapper"; +// types +import type { NextPage } from "next"; + +const Colors: NextPage = () => ( + + +
+
+ Accent: +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Background: +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +); + +export default Colors; diff --git a/apps/app/styles/globals.css b/apps/app/styles/globals.css index 4b9428f2b..da7f512b9 100644 --- a/apps/app/styles/globals.css +++ b/apps/app/styles/globals.css @@ -23,42 +23,51 @@ --color-border: 229, 231, 235; --color-bg-sidebar: 255, 255, 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-50: 236, 241, 255; + --color-accent-100: 217, 228, 255; + --color-accent-200: 178, 200, 255; + --color-accent-300: 140, 173, 255; + --color-accent-400: 101, 145, 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-accent-600: 57, 106, 230; + --color-accent-700: 50, 94, 204; + --color-accent-800: 44, 83, 179; + --color-accent-900: 38, 71, 153; --color-text-base: 3, 7, 18; --color-text-secondary: 55, 65, 81; } [data-theme="light"] { - --color-bg-base: 255, 255, 255; - --color-bg-surface-1: 249, 250, 251; - --color-bg-surface-2: 243, 244, 246; + --color-bg-50: 250, 250, 250; + --color-bg-100: 250, 250, 250; + --color-bg-200: 250, 250, 250; + --color-bg-300: 250, 250, 250; + --color-bg-400: 250, 250, 250; + --color-bg-500: 250, 250, 250; + --color-bg-600: 250, 250, 250; + --color-bg-700: 250, 250, 250; + --color-bg-800: 250, 250, 250; + --color-bg-900: 250, 250, 250; --color-border: 229, 231, 235; --color-bg-sidebar: 255, 255, 255; - --color-accent: 63, 118, 255; - - --color-text-base: 3, 7, 18; - --color-text-secondary: 55, 65, 81; } [data-theme="dark"] { - --color-bg-base: 25, 27, 27; - --color-bg-surface-1: 29, 30, 32; - --color-bg-surface-2: 39, 42, 45; + --color-bg-50: 250, 250, 250; + --color-bg-100: 245, 245, 245; + --color-bg-200: 229, 229, 229; + --color-bg-300: 212, 212, 212; + --color-bg-400: 163, 163, 163; + --color-bg-500: 115, 115, 115; + --color-bg-600: 82, 82, 82; + --color-bg-700: 64, 64, 64; + --color-bg-800: 38, 38, 38; + --color-bg-900: 23, 23, 23; --color-border: 46, 50, 52; --color-bg-sidebar: 19, 20, 22; - --color-accent: 60, 133, 217; --color-text-base: 233, 244, 252; --color-text-secondary: 142, 148, 146; diff --git a/apps/app/tailwind.config.js b/apps/app/tailwind.config.js index bfa537413..c132bd669 100644 --- a/apps/app/tailwind.config.js +++ b/apps/app/tailwind.config.js @@ -28,21 +28,34 @@ module.exports = { 900: convertToRGB("--color-accent-900"), DEFAULT: convertToRGB("--color-accent-500"), }, + bg: { + 50: convertToRGB("--color-bg-50"), + 100: convertToRGB("--color-bg-100"), + 200: convertToRGB("--color-bg-200"), + 300: convertToRGB("--color-bg-300"), + 400: convertToRGB("--color-bg-400"), + 500: convertToRGB("--color-bg-500"), + 600: convertToRGB("--color-bg-600"), + 700: convertToRGB("--color-bg-700"), + 800: convertToRGB("--color-bg-800"), + 900: convertToRGB("--color-bg-900"), + DEFAULT: convertToRGB("--color-bg-500"), + }, base: withOpacity("--color-bg-base"), }, }, borderColor: { brand: { - base: withOpacity("--color-border"), + base: withOpacity("--color-bg-400"), "surface-1": withOpacity("--color-bg-surface-1"), "surface-2": withOpacity("--color-bg-surface-2"), }, }, backgroundColor: { brand: { - base: withOpacity("--color-bg-base"), - "surface-1": withOpacity("--color-bg-surface-1"), - "surface-2": withOpacity("--color-bg-surface-2"), + base: withOpacity("--color-bg-500"), + "surface-1": withOpacity("--color-bg-700"), + "surface-2": withOpacity("--color-bg-900"), sidebar: withOpacity("--color-bg-sidebar"), backdrop: "#131313", }, diff --git a/apps/app/types/users.d.ts b/apps/app/types/users.d.ts index 5b108ac0c..bc9984c64 100644 --- a/apps/app/types/users.d.ts +++ b/apps/app/types/users.d.ts @@ -29,21 +29,8 @@ export interface IUser { } export interface ICustomTheme { - accent: { - 50: string; - 100: string; - 200: string; - 300: string; - 400: string; - 500: string; - 600: string; - 700: string; - 800: string; - 900: string; - }; - bgBase: string; - bgSurface1: string; - bgSurface2: string; + accent: string; + background: string; border: string; darkPalette: boolean; palette: string;