Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae6656e0ec | |||
| 7e9eae0ef2 | |||
| 6b28abc405 |
@@ -26,13 +26,13 @@ export default function Navbar() {
|
||||
const { width } = useWindowDimensions();
|
||||
|
||||
const handleToggle = () => {
|
||||
if (settings.theme === "dark") {
|
||||
updateSettings({ theme: "light" });
|
||||
} else {
|
||||
updateSettings({ theme: "dark" });
|
||||
}
|
||||
const [colorTheme, mode] = (settings.theme || "default-light").split('-');
|
||||
const newMode = mode === "dark" ? "light" : "dark";
|
||||
const newTheme = `${colorTheme}-${newMode}`;
|
||||
updateSettings({ theme: newTheme });
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setSidebar(false);
|
||||
}, [width]);
|
||||
@@ -143,7 +143,7 @@ export default function Navbar() {
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
>
|
||||
Switch to {settings.theme === "light" ? "Dark" : "Light"}
|
||||
Switch to {(settings.theme || "default-light").endsWith("-dark") ? "Light" : "Dark"}
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -6,32 +6,39 @@ type Props = {
|
||||
};
|
||||
|
||||
export default function ToggleDarkMode({ className }: Props) {
|
||||
const { settings, updateSettings } = useLocalSettingsStore();
|
||||
|
||||
const [theme, setTheme] = useState(localStorage.getItem("theme"));
|
||||
|
||||
const handleToggle = (e: any) => {
|
||||
setTheme(e.target.checked ? "dark" : "light");
|
||||
};
|
||||
const { updateSettings } = useLocalSettingsStore();
|
||||
const [theme, setTheme] = useState('default-light');
|
||||
|
||||
useEffect(() => {
|
||||
updateSettings({ theme: theme as string });
|
||||
}, [theme]);
|
||||
const storedTheme = localStorage.getItem("theme");
|
||||
if (storedTheme) {
|
||||
setTheme(storedTheme);
|
||||
} else {
|
||||
// Default theme if not set in localStorage
|
||||
localStorage.setItem("theme", "default-light");
|
||||
setTheme("default-light");
|
||||
}
|
||||
console.log("Initial theme from localStorage:", storedTheme || "default-light");
|
||||
}, []);
|
||||
|
||||
const handleToggle = () => {
|
||||
const [currentColorTheme, currentMode] = theme.split('-');
|
||||
const newMode = currentMode === 'light' ? 'dark' : 'light';
|
||||
const newTheme = `${currentColorTheme}-${newMode}`;
|
||||
|
||||
setTheme(newTheme);
|
||||
localStorage.setItem("theme", newTheme);
|
||||
document.documentElement.setAttribute('data-theme', newTheme);
|
||||
updateSettings({ theme: newTheme });
|
||||
console.log("New theme set:", newTheme);
|
||||
};
|
||||
|
||||
const isDarkMode = theme.endsWith('-dark');
|
||||
|
||||
return (
|
||||
<div
|
||||
className="tooltip tooltip-bottom"
|
||||
data-tip={`Switch to ${settings.theme === "light" ? "Dark" : "Light"}`}
|
||||
>
|
||||
<label
|
||||
className={`swap swap-rotate btn-square text-neutral btn btn-ghost btn-sm ${className}`}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
onChange={handleToggle}
|
||||
className="theme-controller"
|
||||
checked={localStorage.getItem("theme") === "light" ? false : true}
|
||||
/>
|
||||
<div className="tooltip tooltip-bottom" data-tip={`Switch to ${isDarkMode ? "Light" : "Dark"}`}>
|
||||
<label className={`swap swap-rotate btn-square text-neutral btn btn-ghost btn-sm ${className}`}>
|
||||
<input type="checkbox" onChange={handleToggle} className="theme-controller" checked={isDarkMode} />
|
||||
<i className="bi-sun-fill text-xl swap-on"></i>
|
||||
<i className="bi-moon-fill text-xl swap-off"></i>
|
||||
</label>
|
||||
|
||||
+13
-1
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import "@/styles/globals.css";
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
@@ -14,6 +14,18 @@ export default function App({
|
||||
}: AppProps<{
|
||||
session: Session;
|
||||
}>) {
|
||||
|
||||
useEffect(() => {
|
||||
let theme = localStorage.getItem("theme");
|
||||
if (!theme || !theme.includes("-")) {
|
||||
theme = "default-dark"; // Default theme
|
||||
localStorage.setItem("theme", theme);
|
||||
}
|
||||
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}, []);
|
||||
|
||||
|
||||
return (
|
||||
<SessionProvider
|
||||
session={pageProps.session}
|
||||
|
||||
@@ -104,8 +104,10 @@ export default function Index() {
|
||||
className="h-[60rem] p-5 flex gap-3 flex-col"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(${activeCollection?.color}20 10%, ${
|
||||
settings.theme === "dark" ? "#262626" : "#f3f4f6"
|
||||
} 13rem, ${settings.theme === "dark" ? "#171717" : "#ffffff"} 100%)`,
|
||||
(settings.theme || "default-light").endsWith("-dark") ? "#262626" : "#f3f4f6"
|
||||
} 13rem, ${
|
||||
(settings.theme || "default-light").endsWith("-dark") ? "#171717" : "#ffffff"
|
||||
} 100%)`,
|
||||
}}
|
||||
>
|
||||
{activeCollection && (
|
||||
|
||||
+2
-2
@@ -155,7 +155,7 @@ export default function Dashboard() {
|
||||
</div>
|
||||
<Link
|
||||
href="/links"
|
||||
className="flex items-center text-sm text-black/75 dark:text-white/75 gap-2 cursor-pointer"
|
||||
className="flex items-center text-sm text-neutral gap-2 cursor-pointer"
|
||||
>
|
||||
View All
|
||||
<i className="bi-chevron-right text-sm"></i>
|
||||
@@ -264,7 +264,7 @@ export default function Dashboard() {
|
||||
</div>
|
||||
<Link
|
||||
href="/links/pinned"
|
||||
className="flex items-center text-sm text-black/75 dark:text-white/75 gap-2 cursor-pointer"
|
||||
className="flex items-center text-sm text-neutral gap-2 cursor-pointer"
|
||||
>
|
||||
View All
|
||||
<i className="bi-chevron-right text-sm "></i>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
|
||||
import SettingsLayout from "@/layouts/SettingsLayout";
|
||||
import { useState, useEffect } from "react";
|
||||
import useAccountStore from "@/store/account";
|
||||
import { AccountSettings } from "@/types/global";
|
||||
import { toast } from "react-hot-toast";
|
||||
import React from "react";
|
||||
import useLocalSettingsStore from "@/store/localSettings";
|
||||
|
||||
export default function Appearance() {
|
||||
const { updateSettings } = useLocalSettingsStore();
|
||||
const { account, updateAccount } = useAccountStore();
|
||||
const submit = async () => {
|
||||
setSubmitLoader(true);
|
||||
|
||||
const load = toast.loading("Applying...");
|
||||
|
||||
const response = await updateAccount({
|
||||
@@ -18,17 +18,12 @@ export default function Appearance() {
|
||||
});
|
||||
|
||||
toast.dismiss(load);
|
||||
|
||||
if (response.ok) {
|
||||
toast.success("Settings Applied!");
|
||||
} else toast.error(response.data as string);
|
||||
setSubmitLoader(false);
|
||||
};
|
||||
|
||||
const [submitLoader, setSubmitLoader] = useState(false);
|
||||
|
||||
const { account, updateAccount } = useAccountStore();
|
||||
|
||||
const [user, setUser] = useState<AccountSettings>(
|
||||
!objectIsEmpty(account)
|
||||
? account
|
||||
@@ -48,6 +43,9 @@ export default function Appearance() {
|
||||
} as unknown as AccountSettings)
|
||||
);
|
||||
|
||||
// Combine colorTheme and mode into a single state
|
||||
const [theme, setTheme] = useState(localStorage.getItem("theme") || "default-dark");
|
||||
|
||||
function objectIsEmpty(obj: object) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
@@ -56,51 +54,72 @@ export default function Appearance() {
|
||||
if (!objectIsEmpty(account)) setUser({ ...account });
|
||||
}, [account]);
|
||||
|
||||
const handleThemeChange = (newThemePart: string, isColorTheme: boolean) => {
|
||||
const currentTheme = localStorage.getItem("theme") || "default-light";
|
||||
const [currentColorTheme, currentMode] = currentTheme.split('-');
|
||||
const newTheme = isColorTheme ? `${newThemePart}-${currentMode}` : `${currentColorTheme}-${newThemePart}`;
|
||||
|
||||
localStorage.setItem("theme", newTheme);
|
||||
document.documentElement.setAttribute('data-theme', newTheme);
|
||||
updateSettings({ theme: newTheme });
|
||||
|
||||
// Update the theme state
|
||||
setTheme(newTheme);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<SettingsLayout>
|
||||
<p className="capitalize text-3xl font-thin inline">Appearance</p>
|
||||
|
||||
<div className="divider my-3"></div>
|
||||
|
||||
<div className="flex flex-col gap-5">
|
||||
|
||||
<div>
|
||||
<p className="mb-3">Select Theme</p>
|
||||
<div className="flex gap-3 w-full">
|
||||
<div
|
||||
className={`w-full text-center outline-solid outline-neutral-content outline dark:outline-neutral-700 h-36 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-black ${
|
||||
localStorage.getItem("theme") === "dark"
|
||||
? "dark:outline-primary text-primary"
|
||||
: "text-white"
|
||||
}`}
|
||||
onClick={() => updateSettings({ theme: "dark" })}
|
||||
<p className="mb-3">Select Mode</p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{["light", "dark"].map((modeOption) => (
|
||||
<button
|
||||
key={modeOption}
|
||||
onClick={() => handleThemeChange(modeOption, false)}
|
||||
className={`w-full text-center h-36 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none ${theme.endsWith(modeOption) ? "ring-2 ring-primary" : "ring-2 ring-neutral"}`}
|
||||
>
|
||||
<i className="bi-moon-fill text-6xl"></i>
|
||||
<p className="ml-2 text-2xl">Dark</p>
|
||||
|
||||
{/* <hr className="my-3 outline-1 outline-neutral-content dark:outline-neutral-700" /> */}
|
||||
</div>
|
||||
<div
|
||||
className={`w-full text-center outline-solid outline-neutral-content outline dark:outline-neutral-700 h-36 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-white ${
|
||||
localStorage.getItem("theme") === "light"
|
||||
? "outline-primary text-primary"
|
||||
: "text-black"
|
||||
}`}
|
||||
onClick={() => updateSettings({ theme: "light" })}
|
||||
>
|
||||
<i className="bi-sun-fill text-6xl"></i>
|
||||
<p className="ml-2 text-2xl">Light</p>
|
||||
{/* <hr className="my-3 outline-1 outline-neutral-content dark:outline-neutral-700" /> */}
|
||||
</div>
|
||||
{modeOption === 'light' ?
|
||||
<i className={`bi-sun-fill text-6xl ${theme.endsWith(modeOption) ? "text-primary" : ""}`}></i> :
|
||||
<i className={`bi-moon-fill text-6xl ${theme.endsWith(modeOption) ? "text-primary" : ""}`}></i>}
|
||||
<p className="ml-2 text-2xl">{modeOption.charAt(0).toUpperCase() + modeOption.slice(1)}</p>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* <SubmitButton
|
||||
<div>
|
||||
<p className="mb-3">Select Color Theme</p>
|
||||
<div className="grid grid-cols-4 gap-3">
|
||||
{["default", "red", "green", "orange"].map((colorTheme) => (
|
||||
<button
|
||||
key={colorTheme}
|
||||
onClick={() => handleThemeChange(colorTheme, true)}
|
||||
className={`w-full text-center h-36 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none ${theme.startsWith(colorTheme) ? "ring-2 ring-primary" : "ring-2 ring-neutral"}`}
|
||||
>
|
||||
{colorTheme.charAt(0).toUpperCase() + colorTheme.slice(1)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={submit}
|
||||
loading={submitLoader}
|
||||
label="Save"
|
||||
className="mt-2 mx-auto lg:mx-0"
|
||||
/> */}
|
||||
disabled={submitLoader}
|
||||
className="mt-2 mx-auto lg:mx-0 bg-primary text-white rounded-md px-4 py-2"
|
||||
>
|
||||
{submitLoader ? "Saving..." : "Save"}
|
||||
</button>
|
||||
</div>
|
||||
</SettingsLayout>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+21
-16
@@ -18,34 +18,39 @@ const useLocalSettingsStore = create<LocalSettingsStore>((set) => ({
|
||||
viewMode: "",
|
||||
},
|
||||
updateSettings: async (newSettings) => {
|
||||
if (
|
||||
newSettings.theme &&
|
||||
newSettings.theme !== localStorage.getItem("theme")
|
||||
) {
|
||||
if (newSettings.theme) {
|
||||
localStorage.setItem("theme", newSettings.theme);
|
||||
document.documentElement.setAttribute('data-theme', newSettings.theme);
|
||||
|
||||
const localTheme = localStorage.getItem("theme") || "";
|
||||
|
||||
document.querySelector("html")?.setAttribute("data-theme", localTheme);
|
||||
if (newSettings.theme.endsWith("-dark")) {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
newSettings.viewMode &&
|
||||
newSettings.viewMode !== localStorage.getItem("viewMode")
|
||||
) {
|
||||
if (newSettings.viewMode) {
|
||||
localStorage.setItem("viewMode", newSettings.viewMode);
|
||||
|
||||
// const localTheme = localStorage.getItem("viewMode") || "";
|
||||
}
|
||||
|
||||
set((state) => ({ settings: { ...state.settings, ...newSettings } }));
|
||||
},
|
||||
setSettings: async () => {
|
||||
if (!localStorage.getItem("theme")) {
|
||||
localStorage.setItem("theme", "dark");
|
||||
let theme = localStorage.getItem("theme");
|
||||
if (!theme || !theme.includes("-")) {
|
||||
theme = "default-dark"; // Default theme
|
||||
localStorage.setItem("theme", theme);
|
||||
}
|
||||
|
||||
const localTheme = localStorage.getItem("theme") || "";
|
||||
const localTheme = theme;
|
||||
|
||||
document.documentElement.setAttribute('data-theme', localTheme);
|
||||
|
||||
if (localTheme.endsWith("-dark")) {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
|
||||
set((state) => ({
|
||||
settings: { ...state.settings, theme: localTheme },
|
||||
|
||||
+106
-3
@@ -5,7 +5,7 @@ module.exports = {
|
||||
daisyui: {
|
||||
themes: [
|
||||
{
|
||||
light: {
|
||||
"default-light": {
|
||||
primary: "#0369a1",
|
||||
secondary: "#0891b2",
|
||||
accent: "#6d28d9",
|
||||
@@ -21,7 +21,7 @@ module.exports = {
|
||||
},
|
||||
},
|
||||
{
|
||||
dark: {
|
||||
"default-dark": {
|
||||
primary: "#7dd3fc",
|
||||
secondary: "#22d3ee",
|
||||
accent: "#6d28d9",
|
||||
@@ -36,6 +36,108 @@ module.exports = {
|
||||
error: "#f1293c",
|
||||
},
|
||||
},
|
||||
// Red Light Theme
|
||||
{
|
||||
"red-light": {
|
||||
primary: "#ef4444",
|
||||
secondary: "#dc2626",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#6b7280",
|
||||
"neutral-content": "#d1d5db",
|
||||
"base-100": "#ffffff",
|
||||
"base-200": "#f3f4f6",
|
||||
"base-content": "#0a0a0a",
|
||||
info: "#a5f3fc",
|
||||
success: "#22c55e",
|
||||
warning: "#facc15",
|
||||
error: "#dc2626",
|
||||
},
|
||||
},
|
||||
// Red Dark Theme
|
||||
{
|
||||
"red-dark": {
|
||||
primary: "#ef4444",
|
||||
secondary: "#dc2626",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#9ca3af",
|
||||
"neutral-content": "#404040",
|
||||
"base-100": "#171717",
|
||||
"base-200": "#262626",
|
||||
"base-content": "#fafafa",
|
||||
info: "#009ee4",
|
||||
success: "#00b17d",
|
||||
warning: "#eac700",
|
||||
error: "#f1293c",
|
||||
},
|
||||
},
|
||||
// Green Light Theme
|
||||
{
|
||||
"green-light": {
|
||||
primary: "#22c55e",
|
||||
secondary: "#16a34a",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#6b7280",
|
||||
"neutral-content": "#d1d5db",
|
||||
"base-100": "#ffffff",
|
||||
"base-200": "#f3f4f6",
|
||||
"base-content": "#0a0a0a",
|
||||
info: "#a5f3fc",
|
||||
success: "#22c55e",
|
||||
warning: "#facc15",
|
||||
error: "#dc2626",
|
||||
},
|
||||
},
|
||||
// Green Dark Theme
|
||||
{
|
||||
"green-dark": {
|
||||
primary: "#22c55e",
|
||||
secondary: "#16a34a",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#9ca3af",
|
||||
"neutral-content": "#404040",
|
||||
"base-100": "#171717",
|
||||
"base-200": "#262626",
|
||||
"base-content": "#fafafa",
|
||||
info: "#009ee4",
|
||||
success: "#00b17d",
|
||||
warning: "#eac700",
|
||||
error: "#f1293c",
|
||||
},
|
||||
},
|
||||
// Orange Light Theme
|
||||
{
|
||||
"orange-light": {
|
||||
primary: "#f97316",
|
||||
secondary: "#ea580c",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#9ca3af",
|
||||
"neutral-content": "#404040",
|
||||
"base-100": "#171717",
|
||||
"base-200": "#262626",
|
||||
"base-content": "#fafafa",
|
||||
info: "#009ee4",
|
||||
success: "#00b17d",
|
||||
warning: "#eac700",
|
||||
error: "#f1293c",
|
||||
},
|
||||
},
|
||||
// Orange Dark Theme
|
||||
{
|
||||
"orange-dark": {
|
||||
primary: "#f97316",
|
||||
secondary: "#ea580c",
|
||||
accent: "#6d28d9",
|
||||
neutral: "#9ca3af",
|
||||
"neutral-content": "#404040",
|
||||
"base-100": "#171717",
|
||||
"base-200": "#262626",
|
||||
"base-content": "#fafafa",
|
||||
info: "#009ee4",
|
||||
success: "#00b17d",
|
||||
warning: "#eac700",
|
||||
error: "#f1293c",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
darkMode: ["class", '[data-theme="dark"]'],
|
||||
@@ -53,4 +155,5 @@ module.exports = {
|
||||
addVariant("dark", '&[data-theme="dark"]');
|
||||
}),
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user