summaryrefslogtreecommitdiff
path: root/front/src/styles/ThemeProvider.tsx
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-09-18 10:04:43 +0700
committerpolwex <polwex@sortug.com>2025-09-18 10:04:43 +0700
commite69afcff1c1f42436998ca0b070162d556dd577c (patch)
treeceaf1e3c7f654902eb3029483a4a2af37591c320 /front/src/styles/ThemeProvider.tsx
parent7bac4927e8895719a91011da9a2b997579238145 (diff)
Diffstat (limited to 'front/src/styles/ThemeProvider.tsx')
-rw-r--r--front/src/styles/ThemeProvider.tsx144
1 files changed, 144 insertions, 0 deletions
diff --git a/front/src/styles/ThemeProvider.tsx b/front/src/styles/ThemeProvider.tsx
index 2cc0ca6..08d2e64 100644
--- a/front/src/styles/ThemeProvider.tsx
+++ b/front/src/styles/ThemeProvider.tsx
@@ -19,6 +19,8 @@ export interface ThemeColors {
primary: string;
primaryHover: string;
secondary: string;
+ accent: string;
+ accentHover: string;
background: string;
surface: string;
surfaceHover: string;
@@ -37,11 +39,82 @@ export interface ThemeColors {
overlay: string;
}
+export interface ThemeTypography {
+ fontSizeXs: string;
+ fontSizeSm: string;
+ fontSizeMd: string;
+ fontSizeLg: string;
+ fontSizeXl: string;
+ fontWeightNormal: string;
+ fontWeightMedium: string;
+ fontWeightSemibold: string;
+ fontWeightBold: string;
+}
+
+export interface ThemeSpacing {
+ spacingXs: string;
+ spacingSm: string;
+ spacingMd: string;
+ spacingLg: string;
+ spacingXl: string;
+}
+
+export interface ThemeRadius {
+ radiusSm: string;
+ radiusMd: string;
+ radiusLg: string;
+ radiusFull: string;
+}
+
+export interface ThemeTransitions {
+ transitionFast: string;
+ transitionNormal: string;
+ transitionSlow: string;
+}
+
export interface Theme {
name: ThemeName;
colors: ThemeColors;
+ typography: ThemeTypography;
+ spacing: ThemeSpacing;
+ radius: ThemeRadius;
+ transitions: ThemeTransitions;
}
+// Common theme properties
+const commonTypography: ThemeTypography = {
+ fontSizeXs: "0.75rem",
+ fontSizeSm: "0.875rem",
+ fontSizeMd: "1rem",
+ fontSizeLg: "1.125rem",
+ fontSizeXl: "1.25rem",
+ fontWeightNormal: "400",
+ fontWeightMedium: "500",
+ fontWeightSemibold: "600",
+ fontWeightBold: "700",
+};
+
+const commonSpacing: ThemeSpacing = {
+ spacingXs: "0.25rem",
+ spacingSm: "0.5rem",
+ spacingMd: "1rem",
+ spacingLg: "1.5rem",
+ spacingXl: "2rem",
+};
+
+const commonRadius: ThemeRadius = {
+ radiusSm: "0.25rem",
+ radiusMd: "0.5rem",
+ radiusLg: "0.75rem",
+ radiusFull: "9999px",
+};
+
+const commonTransitions: ThemeTransitions = {
+ transitionFast: "150ms ease",
+ transitionNormal: "250ms ease",
+ transitionSlow: "350ms ease",
+};
+
const themes: Record<ThemeName, Theme> = {
light: {
name: "light",
@@ -49,6 +122,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#543fd7",
primaryHover: "#4532b8",
secondary: "#f39c12",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#ffffff",
surface: "#f8f9fa",
surfaceHover: "#e9ecef",
@@ -66,6 +141,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(0, 0, 0, 0.1)",
overlay: "rgba(0, 0, 0, 0.5)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
dark: {
name: "dark",
@@ -73,6 +152,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#7c6ef7",
primaryHover: "#9085f9",
secondary: "#f39c12",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#0d1117",
surface: "#161b22",
surfaceHover: "#21262d",
@@ -90,6 +171,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(0, 0, 0, 0.3)",
overlay: "rgba(0, 0, 0, 0.7)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
sepia: {
name: "sepia",
@@ -97,6 +182,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#8b4513",
primaryHover: "#6b3410",
secondary: "#d2691e",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#f4e8d0",
surface: "#ede0c8",
surfaceHover: "#e6d9c0",
@@ -114,6 +201,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(62, 39, 35, 0.1)",
overlay: "rgba(62, 39, 35, 0.5)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
noir: {
name: "noir",
@@ -121,6 +212,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#ffffff",
primaryHover: "#e0e0e0",
secondary: "#808080",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#000000",
surface: "#0a0a0a",
surfaceHover: "#1a1a1a",
@@ -138,6 +231,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(255, 255, 255, 0.1)",
overlay: "rgba(0, 0, 0, 0.9)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
ocean: {
name: "ocean",
@@ -145,6 +242,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#006994",
primaryHover: "#005577",
secondary: "#00acc1",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#e1f5fe",
surface: "#b3e5fc",
surfaceHover: "#81d4fa",
@@ -162,6 +261,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(1, 87, 155, 0.1)",
overlay: "rgba(1, 87, 155, 0.5)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
forest: {
name: "forest",
@@ -169,6 +272,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#2e7d32",
primaryHover: "#1b5e20",
secondary: "#689f38",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#f1f8e9",
surface: "#dcedc8",
surfaceHover: "#c5e1a5",
@@ -186,6 +291,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(27, 94, 32, 0.1)",
overlay: "rgba(27, 94, 32, 0.5)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
gruvbox: {
name: "gruvbox",
@@ -193,6 +302,8 @@ const themes: Record<ThemeName, Theme> = {
primary: "#fe8019",
primaryHover: "#d65d0e",
secondary: "#fabd2f",
+ accent: "#2a9d8f",
+ accentHover: "#238b7f",
background: "#282828",
surface: "#3c3836",
surfaceHover: "#504945",
@@ -210,6 +321,10 @@ const themes: Record<ThemeName, Theme> = {
shadow: "rgba(0, 0, 0, 0.3)",
overlay: "rgba(40, 40, 40, 0.8)",
},
+ typography: commonTypography,
+ spacing: commonSpacing,
+ radius: commonRadius,
+ transitions: commonTransitions,
},
};
@@ -254,11 +369,40 @@ export const ThemeProvider: React.FC<ThemeProviderProps> = ({
root.setAttribute("data-theme", themeName);
+ // Set color variables
Object.entries(theme.colors).forEach(([key, value]) => {
const cssVarName = `--color-${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
root.style.setProperty(cssVarName, value);
});
+ // Set typography variables
+ Object.entries(theme.typography).forEach(([key, value]) => {
+ const cssVarName = `--${key.replace(/([A-Z])/g, "-$1").toLowerCase().replace("font-", "font-").replace("size", "").replace("weight", "")}`;
+ root.style.setProperty(cssVarName, value);
+ });
+
+ // Set spacing variables
+ Object.entries(theme.spacing).forEach(([key, value]) => {
+ const cssVarName = `--${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
+ root.style.setProperty(cssVarName, value);
+ });
+
+ // Set radius variables
+ Object.entries(theme.radius).forEach(([key, value]) => {
+ const cssVarName = `--${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
+ root.style.setProperty(cssVarName, value);
+ });
+
+ // Set transition variables
+ Object.entries(theme.transitions).forEach(([key, value]) => {
+ const cssVarName = `--${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
+ root.style.setProperty(cssVarName, value);
+ });
+
+ // Legacy variables for backward compatibility
+ root.style.setProperty('--text-color', theme.colors.text);
+ root.style.setProperty('--background-color', theme.colors.background);
+
localStorage.setItem("theme", themeName);
}, [themeName, theme]);