diff --git a/frontend/src/components/navigator.tsx b/frontend/src/components/navigator.tsx
index 9ffa117..5847649 100644
--- a/frontend/src/components/navigator.tsx
+++ b/frontend/src/components/navigator.tsx
@@ -10,6 +10,7 @@ import {
} from "react-icons/md";
import { useTranslation } from "react-i18next";
import UploadingSideBar from "./uploading_side_bar.tsx";
+import { ThemeSwitcher } from "./theme_switcher.tsx";
import { IoLogoGithub } from "react-icons/io";
import { useAppContext } from "./AppContext.tsx";
@@ -140,6 +141,7 @@ export default function Navigator() {
+
{app.isLoggedIn() && (
)}
-
+
+
{app.isLoggedIn() ? (
) : (
diff --git a/frontend/src/components/theme_switcher.tsx b/frontend/src/components/theme_switcher.tsx
new file mode 100644
index 0000000..657e218
--- /dev/null
+++ b/frontend/src/components/theme_switcher.tsx
@@ -0,0 +1,93 @@
+import { useEffect, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { MdPalette } from "react-icons/md";
+
+interface ThemeOption {
+ name: string;
+ displayName: string;
+ displayColor: string;
+}
+
+const themeOptions: ThemeOption[] = [
+ {
+ name: "pink",
+ displayName: "Nyne Pink",
+ displayColor: "oklch(65% 0.241 354.308)",
+ },
+ {
+ name: "ocean",
+ displayName: "Ocean Breeze",
+ displayColor: "oklch(70% 0.18 220)",
+ },
+ {
+ name: "mint",
+ displayName: "Mint Leaf",
+ displayColor: "oklch(65% 0.16 160)",
+ },
+ {
+ name: "glow",
+ displayName: "Golden Glow",
+ displayColor: "oklch(70% 0.16 70)",
+ },
+];
+
+export function ThemeSwitcher() {
+ const [currentTheme, setCurrentTheme] = useState("pink");
+
+ const { t } = useTranslation();
+
+ useEffect(() => {
+ const savedTheme = localStorage.getItem("theme") || "pink";
+ setCurrentTheme(savedTheme);
+ applyTheme(savedTheme);
+ }, []);
+
+ const applyTheme = (themeName: string) => {
+ const root = document.documentElement;
+ root.setAttribute("data-theme", themeName);
+ };
+
+ const handleThemeChange = (themeName: string) => {
+ setCurrentTheme(themeName);
+ applyTheme(themeName);
+ localStorage.setItem("theme", themeName);
+ const activeElement = document.activeElement as HTMLElement;
+ if (activeElement) {
+ activeElement.blur();
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts
index d29119e..99be8c5 100644
--- a/frontend/src/i18n.ts
+++ b/frontend/src/i18n.ts
@@ -205,6 +205,12 @@ export const i18nData = {
"Show more": "Show more",
"Show less": "Show less",
"You need to log in to comment": "You need to log in to comment",
+
+ // Color Scheme Translation
+ "Nyne Pink": "Nyne Pink",
+ "Ocean Breeze": "Ocean Breeze",
+ "Mint Leaf": "Mint Leaf",
+ "Golden Glow": "Golden Glow",
},
},
"zh-CN": {
@@ -402,6 +408,12 @@ export const i18nData = {
"Show more": "显示更多",
"Show less": "显示更少",
"You need to log in to comment": "您需要登录才能评论",
+
+ // Color Scheme Translation
+ "Nyne Pink": "Nyne 粉",
+ "Ocean Breeze": "海蓝",
+ "Mint Leaf": "薄荷",
+ "Golden Glow": "微光",
},
},
"zh-TW": {
@@ -599,6 +611,12 @@ export const i18nData = {
"Show more": "顯示更多",
"Show less": "顯示更少",
"You need to log in to comment": "您需要登入才能評論",
+
+ // Color Scheme Translation
+ "Nyne Pink": "Nyne 粉",
+ "Ocean Breeze": "海藍",
+ "Mint Leaf": "薄荷",
+ "Golden Glow": "微光",
},
},
};
diff --git a/frontend/src/index.css b/frontend/src/index.css
index 2a77f8b..e910bd3 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,11 +1,12 @@
@import "tailwindcss";
@plugin "daisyui";
+/* Pink Theme */
@plugin "daisyui/theme" {
- name: "light";
+ name: "pink";
default: true;
prefersdark: false;
- color-scheme: "light";
+ color-scheme: "light dark";
--color-base-100: oklch(99% 0.014 343.198);
--color-base-200: oklch(97% 0.028 342.258);
--color-base-300: oklch(84% 0.061 343.231);
@@ -36,31 +37,57 @@
--noise: 0;
}
+@media (prefers-color-scheme: dark) {
+ [data-theme="pink"] {
+ --color-base-100: oklch(28% 0.022 277.508);
+ --color-base-200: oklch(24% 0.02 277.508);
+ --color-base-300: oklch(40% 0.153 2.432);
+ --color-base-content: oklch(97.747% 0.007 106.545);
+ --color-primary: oklch(75.461% 0.183 346.812);
+ --color-primary-content: oklch(15.092% 0.036 346.812);
+ --color-secondary: oklch(74.202% 0.148 301.883);
+ --color-secondary-content: oklch(14.84% 0.029 301.883);
+ --color-accent: oklch(83.392% 0.124 66.558);
+ --color-accent-content: oklch(16.678% 0.024 66.558);
+ --color-neutral: oklch(39.445% 0.032 275.524);
+ --color-neutral-content: oklch(87.889% 0.006 275.524);
+ --color-info: oklch(88.263% 0.093 212.846);
+ --color-info-content: oklch(17.652% 0.018 212.846);
+ --color-success: oklch(87.099% 0.219 148.024);
+ --color-success-content: oklch(17.419% 0.043 148.024);
+ --color-warning: oklch(95.533% 0.134 112.757);
+ --color-warning-content: oklch(19.106% 0.026 112.757);
+ --color-error: oklch(68.22% 0.206 24.43);
+ --color-error-content: oklch(13.644% 0.041 24.43);
+ }
+}
+
+/* Ocean Theme */
@plugin "daisyui/theme" {
- name: "dark";
+ name: "ocean";
default: false;
- prefersdark: true;
- color-scheme: "dark";
- --color-base-100: oklch(28% 0.022 277.508);
- --color-base-200: oklch(24% 0.02 277.508);
- --color-base-300: oklch(40% 0.153 2.432);
- --color-base-content: oklch(97.747% 0.007 106.545);
- --color-primary: oklch(75.461% 0.183 346.812);
- --color-primary-content: oklch(15.092% 0.036 346.812);
- --color-secondary: oklch(74.202% 0.148 301.883);
- --color-secondary-content: oklch(14.84% 0.029 301.883);
- --color-accent: oklch(83.392% 0.124 66.558);
- --color-accent-content: oklch(16.678% 0.024 66.558);
- --color-neutral: oklch(39.445% 0.032 275.524);
- --color-neutral-content: oklch(87.889% 0.006 275.524);
- --color-info: oklch(88.263% 0.093 212.846);
- --color-info-content: oklch(17.652% 0.018 212.846);
- --color-success: oklch(87.099% 0.219 148.024);
- --color-success-content: oklch(17.419% 0.043 148.024);
- --color-warning: oklch(95.533% 0.134 112.757);
- --color-warning-content: oklch(19.106% 0.026 112.757);
- --color-error: oklch(68.22% 0.206 24.43);
- --color-error-content: oklch(13.644% 0.041 24.43);
+ prefersdark: false;
+ color-scheme: "light dark";
+ --color-base-100: oklch(98% 0.005 240);
+ --color-base-200: oklch(96% 0.01 240);
+ --color-base-300: oklch(92% 0.015 240);
+ --color-base-content: oklch(20% 0.01 240);
+ --color-primary: oklch(50% 0.2 240);
+ --color-primary-content: oklch(98% 0.005 240);
+ --color-secondary: oklch(60% 0.15 210);
+ --color-secondary-content: oklch(98% 0.005 210);
+ --color-accent: oklch(70% 0.18 220);
+ --color-accent-content: oklch(98% 0.005 220);
+ --color-neutral: oklch(25% 0.02 240);
+ --color-neutral-content: oklch(98% 0.005 240);
+ --color-info: oklch(65% 0.15 231);
+ --color-info-content: oklch(98% 0.005 231);
+ --color-success: oklch(60% 0.13 145);
+ --color-success-content: oklch(98% 0.005 145);
+ --color-warning: oklch(80% 0.15 90);
+ --color-warning-content: oklch(20% 0.05 90);
+ --color-error: oklch(60% 0.19 27);
+ --color-error-content: oklch(98% 0.005 27);
--radius-selector: 1rem;
--radius-field: 1.5rem;
--radius-box: 1rem;
@@ -71,6 +98,153 @@
--noise: 0;
}
+@media (prefers-color-scheme: dark) {
+ [data-theme="ocean"] {
+ --color-base-100: oklch(15% 0.02 240);
+ --color-base-200: oklch(12% 0.015 240);
+ --color-base-300: oklch(25% 0.03 240);
+ --color-base-content: oklch(90% 0.01 240);
+ --color-primary: oklch(70% 0.18 240);
+ --color-primary-content: oklch(15% 0.02 240);
+ --color-secondary: oklch(75% 0.15 210);
+ --color-secondary-content: oklch(15% 0.015 210);
+ --color-accent: oklch(80% 0.16 220);
+ --color-accent-content: oklch(15% 0.02 220);
+ --color-neutral: oklch(20% 0.025 240);
+ --color-neutral-content: oklch(85% 0.01 240);
+ --color-info: oklch(75% 0.14 231);
+ --color-info-content: oklch(15% 0.015 231);
+ --color-success: oklch(70% 0.12 145);
+ --color-success-content: oklch(15% 0.015 145);
+ --color-warning: oklch(85% 0.14 90);
+ --color-warning-content: oklch(15% 0.02 90);
+ --color-error: oklch(70% 0.18 27);
+ --color-error-content: oklch(15% 0.015 27);
+ }
+}
+
+/* Mint Theme */
+@plugin "daisyui/theme" {
+ name: "mint";
+ default: false;
+ prefersdark: false;
+ color-scheme: "light dark";
+ --color-base-100: oklch(98% 0.005 140);
+ --color-base-200: oklch(96% 0.01 140);
+ --color-base-300: oklch(92% 0.015 140);
+ --color-base-content: oklch(20% 0.01 140);
+ --color-primary: oklch(45% 0.18 140);
+ --color-primary-content: oklch(98% 0.005 140);
+ --color-secondary: oklch(55% 0.15 120);
+ --color-secondary-content: oklch(98% 0.005 120);
+ --color-accent: oklch(65% 0.16 160);
+ --color-accent-content: oklch(98% 0.005 160);
+ --color-neutral: oklch(25% 0.02 140);
+ --color-neutral-content: oklch(98% 0.005 140);
+ --color-info: oklch(70% 0.131 231);
+ --color-info-content: oklch(98% 0.005 231);
+ --color-success: oklch(55% 0.15 145);
+ --color-success-content: oklch(98% 0.005 145);
+ --color-warning: oklch(80% 0.15 90);
+ --color-warning-content: oklch(20% 0.05 90);
+ --color-error: oklch(60% 0.19 27);
+ --color-error-content: oklch(98% 0.005 27);
+ --radius-selector: 1rem;
+ --radius-field: 1.5rem;
+ --radius-box: 1rem;
+ --size-selector: 0.25rem;
+ --size-field: 0.25rem;
+ --border: 1px;
+ --depth: 1;
+ --noise: 0;
+}
+
+@media (prefers-color-scheme: dark) {
+ [data-theme="mint"] {
+ --color-base-100: oklch(15% 0.02 140);
+ --color-base-200: oklch(12% 0.015 140);
+ --color-base-300: oklch(25% 0.03 140);
+ --color-base-content: oklch(90% 0.01 140);
+ --color-primary: oklch(65% 0.16 140);
+ --color-primary-content: oklch(15% 0.02 140);
+ --color-secondary: oklch(70% 0.14 120);
+ --color-secondary-content: oklch(15% 0.015 120);
+ --color-accent: oklch(75% 0.15 160);
+ --color-accent-content: oklch(15% 0.02 160);
+ --color-neutral: oklch(20% 0.025 140);
+ --color-neutral-content: oklch(85% 0.01 140);
+ --color-info: oklch(75% 0.12 231);
+ --color-info-content: oklch(15% 0.015 231);
+ --color-success: oklch(70% 0.14 145);
+ --color-success-content: oklch(15% 0.015 145);
+ --color-warning: oklch(85% 0.14 90);
+ --color-warning-content: oklch(15% 0.02 90);
+ --color-error: oklch(70% 0.18 27);
+ --color-error-content: oklch(15% 0.015 27);
+ }
+}
+
+/* Glow Theme */
+@plugin "daisyui/theme" {
+ name: "glow";
+ default: false;
+ prefersdark: false;
+ color-scheme: "light dark";
+ --color-base-100: oklch(98% 0.005 50);
+ --color-base-200: oklch(96% 0.01 50);
+ --color-base-300: oklch(92% 0.015 50);
+ --color-base-content: oklch(20% 0.01 50);
+ --color-primary: oklch(60% 0.18 50);
+ --color-primary-content: oklch(98% 0.005 50);
+ --color-secondary: oklch(65% 0.15 30);
+ --color-secondary-content: oklch(98% 0.005 30);
+ --color-accent: oklch(70% 0.16 70);
+ --color-accent-content: oklch(98% 0.005 70);
+ --color-neutral: oklch(25% 0.02 50);
+ --color-neutral-content: oklch(98% 0.005 50);
+ --color-info: oklch(70% 0.131 231);
+ --color-info-content: oklch(98% 0.005 231);
+ --color-success: oklch(60% 0.13 145);
+ --color-success-content: oklch(98% 0.005 145);
+ --color-warning: oklch(75% 0.16 60);
+ --color-warning-content: oklch(20% 0.05 60);
+ --color-error: oklch(60% 0.19 27);
+ --color-error-content: oklch(98% 0.005 27);
+ --radius-selector: 1rem;
+ --radius-field: 1.5rem;
+ --radius-box: 1rem;
+ --size-selector: 0.25rem;
+ --size-field: 0.25rem;
+ --border: 1px;
+ --depth: 1;
+ --noise: 0;
+}
+
+@media (prefers-color-scheme: dark) {
+ [data-theme="glow"] {
+ --color-base-100: oklch(15% 0.02 50);
+ --color-base-200: oklch(12% 0.015 50);
+ --color-base-300: oklch(25% 0.03 50);
+ --color-base-content: oklch(90% 0.01 50);
+ --color-primary: oklch(75% 0.16 50);
+ --color-primary-content: oklch(15% 0.02 50);
+ --color-secondary: oklch(80% 0.14 30);
+ --color-secondary-content: oklch(15% 0.015 30);
+ --color-accent: oklch(85% 0.15 70);
+ --color-accent-content: oklch(15% 0.02 70);
+ --color-neutral: oklch(20% 0.025 50);
+ --color-neutral-content: oklch(85% 0.01 50);
+ --color-info: oklch(75% 0.12 231);
+ --color-info-content: oklch(15% 0.015 231);
+ --color-success: oklch(70% 0.12 145);
+ --color-success-content: oklch(15% 0.015 145);
+ --color-warning: oklch(85% 0.15 60);
+ --color-warning-content: oklch(15% 0.02 60);
+ --color-error: oklch(70% 0.18 27);
+ --color-error-content: oklch(15% 0.015 27);
+ }
+}
+
html {
width: 100%;
height: 100%;