used daisyUI for dark mode

This commit is contained in:
daniel31x13 2023-11-24 07:50:16 -05:00
parent b8b6fe24bc
commit 3afd5fef6e
14 changed files with 105 additions and 48 deletions

View File

@ -8,6 +8,7 @@ import ProfilePhoto from "./ProfilePhoto";
import { faCalendarDays } from "@fortawesome/free-regular-svg-icons"; import { faCalendarDays } from "@fortawesome/free-regular-svg-icons";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import usePermissions from "@/hooks/usePermissions"; import usePermissions from "@/hooks/usePermissions";
import useLocalSettingsStore from "@/store/localSettings";
type Props = { type Props = {
collection: CollectionIncludingMembersAndLinkCount; collection: CollectionIncludingMembersAndLinkCount;
@ -23,6 +24,7 @@ type DropdownTrigger =
export default function CollectionCard({ collection, className }: Props) { export default function CollectionCard({ collection, className }: Props) {
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const { settings } = useLocalSettingsStore();
const formattedDate = new Date(collection.createdAt as string).toLocaleString( const formattedDate = new Date(collection.createdAt as string).toLocaleString(
"en-US", "en-US",
@ -42,8 +44,8 @@ export default function CollectionCard({ collection, className }: Props) {
<div <div
style={{ style={{
backgroundImage: `linear-gradient(45deg, ${collection.color}30 10%, ${ backgroundImage: `linear-gradient(45deg, ${collection.color}30 10%, ${
"dark" ? "#262626" : "#f3f4f6" settings.theme === "dark" ? "#262626" : "#f3f4f6"
} 50%, ${"dark" ? "#262626" : "#f9fafb"} 100%)`, } 50%, ${settings.theme === "dark" ? "#262626" : "#f9fafb"} 100%)`,
}} }}
className={`border border-solid border-sky-100 dark:border-neutral-700 self-stretch min-h-[12rem] rounded-2xl shadow duration-100 hover:shadow-none hover:opacity-80 group relative ${ className={`border border-solid border-sky-100 dark:border-neutral-700 self-stretch min-h-[12rem] rounded-2xl shadow duration-100 hover:shadow-none hover:opacity-80 group relative ${
className || "" className || ""

View File

@ -12,10 +12,13 @@ import ProfilePhoto from "@/components/ProfilePhoto";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import useWindowDimensions from "@/hooks/useWindowDimensions"; import useWindowDimensions from "@/hooks/useWindowDimensions";
import ToggleDarkMode from "./ToggleDarkMode"; import ToggleDarkMode from "./ToggleDarkMode";
import useLocalSettingsStore from "@/store/localSettings";
export default function Navbar() { export default function Navbar() {
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const { settings, updateSettings } = useLocalSettingsStore();
const { account } = useAccountStore(); const { account } = useAccountStore();
const [profileDropdown, setProfileDropdown] = useState(false); const [profileDropdown, setProfileDropdown] = useState(false);
@ -26,6 +29,14 @@ export default function Navbar() {
const { width } = useWindowDimensions(); const { width } = useWindowDimensions();
const handleToggle = () => {
if (settings.theme === "dark") {
updateSettings({ theme: "light" });
} else {
updateSettings({ theme: "dark" });
}
};
useEffect(() => { useEffect(() => {
setSidebar(false); setSidebar(false);
}, [width]); }, [width]);
@ -95,9 +106,12 @@ export default function Navbar() {
href: "/settings/account", href: "/settings/account",
}, },
{ {
name: `Switch to ${"light" ? "Dark" : "Light"}`, name: `Switch to ${
settings.theme === "light" ? "Dark" : "Light"
}`,
onClick: () => { onClick: () => {
setProfileDropdown(!profileDropdown); setProfileDropdown(!profileDropdown);
handleToggle();
}, },
}, },
{ {

View File

@ -1,3 +1,4 @@
import useLocalSettingsStore from "@/store/localSettings";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
type Props = { type Props = {
@ -5,9 +6,9 @@ type Props = {
}; };
export default function ToggleDarkMode({ className }: Props) { export default function ToggleDarkMode({ className }: Props) {
const [theme, setTheme] = useState( const { updateSettings } = useLocalSettingsStore();
localStorage.getItem("theme") ? localStorage.getItem("theme") : "light"
); const [theme, setTheme] = useState(localStorage.getItem("theme"));
const handleToggle = (e: any) => { const handleToggle = (e: any) => {
if (e.target.checked) { if (e.target.checked) {
@ -18,11 +19,7 @@ export default function ToggleDarkMode({ className }: Props) {
}; };
useEffect(() => { useEffect(() => {
localStorage.setItem("theme", theme || ""); updateSettings({ theme: theme as string });
const localTheme = localStorage.getItem("theme");
document
.querySelector("html")
?.setAttribute("data-theme", localTheme || "");
}, [theme]); }, [theme]);
return ( return (
@ -31,7 +28,7 @@ export default function ToggleDarkMode({ className }: Props) {
type="checkbox" type="checkbox"
onChange={handleToggle} onChange={handleToggle}
className="theme-controller" className="theme-controller"
checked={theme === "light" ? false : true} checked={localStorage.getItem("theme") === "light" ? false : true}
/> />
{/* sun icon */} {/* sun icon */}

View File

@ -1,3 +1,4 @@
import useLocalSettingsStore from "@/store/localSettings";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
@ -8,19 +9,22 @@ interface Props {
} }
export default function CenteredForm({ text, children }: Props) { export default function CenteredForm({ text, children }: Props) {
const { settings } = useLocalSettingsStore();
return ( return (
<div className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center p-5"> <div className="absolute top-0 bottom-0 left-0 right-0 flex justify-center items-center p-5">
<div className="m-auto flex flex-col gap-2 w-full"> <div className="m-auto flex flex-col gap-2 w-full">
{true ? ( {true ? (
<Image <Image
src={`/linkwarden_${"dark" ? "dark" : "light"}.png`} src={`/linkwarden_${
settings.theme === "dark" ? "dark" : "light"
}.png`}
width={640} width={640}
height={136} height={136}
alt="Linkwarden" alt="Linkwarden"
className="h-12 w-fit mx-auto" className="h-12 w-fit mx-auto"
/> />
) : undefined} ) : undefined}
{/* {theme === "dark" ? ( {/* {settings.theme === "dark" ? (
<Image <Image
src="/linkwarden_dark.png" src="/linkwarden_dark.png"
width={640} width={640}

View File

@ -6,6 +6,7 @@ import Head from "next/head";
import AuthRedirect from "@/layouts/AuthRedirect"; import AuthRedirect from "@/layouts/AuthRedirect";
import { Toaster } from "react-hot-toast"; import { Toaster } from "react-hot-toast";
import { Session } from "next-auth"; import { Session } from "next-auth";
import useLocalSettingsStore from "@/store/localSettings";
export default function App({ export default function App({
Component, Component,
@ -13,20 +14,10 @@ export default function App({
}: AppProps<{ }: AppProps<{
session: Session; session: Session;
}>) { }>) {
const [theme, setTheme] = useState(""); const { setSettings } = useLocalSettingsStore();
useEffect(() => { useEffect(() => {
setTheme( setSettings();
localStorage.getItem("theme")
? (localStorage.getItem("theme") as string)
: "light"
);
if (theme) localStorage.setItem("theme", theme as string);
const localTheme = localStorage.getItem("theme");
document
.querySelector("html")
?.setAttribute("data-theme", localTheme || "");
}, []); }, []);
return ( return (

View File

@ -18,10 +18,13 @@ import useModalStore from "@/store/modals";
import useLinks from "@/hooks/useLinks"; import useLinks from "@/hooks/useLinks";
import usePermissions from "@/hooks/usePermissions"; import usePermissions from "@/hooks/usePermissions";
import NoLinksFound from "@/components/NoLinksFound"; import NoLinksFound from "@/components/NoLinksFound";
import useLocalSettingsStore from "@/store/localSettings";
export default function Index() { export default function Index() {
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const { settings } = useLocalSettingsStore();
const router = useRouter(); const router = useRouter();
const { links } = useLinkStore(); const { links } = useLinkStore();
@ -51,9 +54,9 @@ export default function Index() {
style={{ style={{
backgroundImage: `linear-gradient(-45deg, ${ backgroundImage: `linear-gradient(-45deg, ${
activeCollection?.color activeCollection?.color
}30 10%, ${"dark" ? "#262626" : "#f3f4f6"} 50%, ${ }30 10%, ${
"dark" ? "#262626" : "#f9fafb" settings.theme === "dark" ? "#262626" : "#f3f4f6"
} 100%)`, } 50%, ${settings.theme === "dark" ? "#262626" : "#f9fafb"} 100%)`,
}} }}
className="border border-solid border-sky-100 dark:border-neutral-700 rounded-2xl shadow min-h-[10rem] p-5 flex gap-5 flex-col justify-between" className="border border-solid border-sky-100 dark:border-neutral-700 rounded-2xl shadow min-h-[10rem] p-5 flex gap-5 flex-col justify-between"
> >

View File

@ -106,8 +106,6 @@ export default function Dashboard() {
return ( return (
<MainLayout> <MainLayout>
<button className="btn btn-primary">Primary</button>
<button className=" dark:bg-red-500">Primary</button>
<div style={{ flex: "1 1 auto" }} className="p-5 flex flex-col gap-5"> <div style={{ flex: "1 1 auto" }} className="p-5 flex flex-col gap-5">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<FontAwesomeIcon <FontAwesomeIcon

View File

@ -16,6 +16,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBoxesStacked, faFolder } from "@fortawesome/free-solid-svg-icons"; import { faBoxesStacked, faFolder } from "@fortawesome/free-solid-svg-icons";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import useLocalSettingsStore from "@/store/localSettings";
type LinkContent = { type LinkContent = {
title: string; title: string;
@ -33,6 +34,8 @@ export default function Index() {
const { links, getLink } = useLinkStore(); const { links, getLink } = useLinkStore();
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const { settings } = useLocalSettingsStore();
const session = useSession(); const session = useSession();
const userId = session.data?.user.id; const userId = session.data?.user.id;
@ -144,7 +147,7 @@ export default function Index() {
<LinkLayout> <LinkLayout>
<div <div
className={`flex flex-col max-w-screen-md h-full ${ className={`flex flex-col max-w-screen-md h-full ${
"dark" ? "banner-dark-mode" : "banner-light-mode" settings.theme === "dark" ? "banner-dark-mode" : "banner-light-mode"
}`} }`}
> >
<div <div

View File

@ -20,6 +20,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faFilter, faSort } from "@fortawesome/free-solid-svg-icons"; import { faFilter, faSort } from "@fortawesome/free-solid-svg-icons";
import FilterSearchDropdown from "@/components/FilterSearchDropdown"; import FilterSearchDropdown from "@/components/FilterSearchDropdown";
import SortDropdown from "@/components/SortDropdown"; import SortDropdown from "@/components/SortDropdown";
import useLocalSettingsStore from "@/store/localSettings";
const cardVariants: Variants = { const cardVariants: Variants = {
offscreen: { offscreen: {
@ -39,6 +40,8 @@ export default function PublicCollections() {
const { links } = useLinkStore(); const { links } = useLinkStore();
const { modal, setModal } = useModalStore(); const { modal, setModal } = useModalStore();
const { settings } = useLocalSettingsStore();
useEffect(() => { useEffect(() => {
modal modal
? (document.body.style.overflow = "hidden") ? (document.body.style.overflow = "hidden")
@ -103,8 +106,8 @@ export default function PublicCollections() {
className="h-screen" className="h-screen"
style={{ style={{
backgroundImage: `linear-gradient(${collection?.color}30 10%, ${ backgroundImage: `linear-gradient(${collection?.color}30 10%, ${
"dark" ? "#262626" : "#f3f4f6" settings.theme === "dark" ? "#262626" : "#f3f4f6"
} 50%, ${"dark" ? "#171717" : "#ffffff"} 100%)`, } 50%, ${settings.theme === "dark" ? "#171717" : "#ffffff"} 100%)`,
}} }}
> >
<ModalManagement /> <ModalManagement />

View File

@ -16,6 +16,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBoxesStacked, faFolder } from "@fortawesome/free-solid-svg-icons"; import { faBoxesStacked, faFolder } from "@fortawesome/free-solid-svg-icons";
import useModalStore from "@/store/modals"; import useModalStore from "@/store/modals";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import useLocalSettingsStore from "@/store/localSettings";
type LinkContent = { type LinkContent = {
title: string; title: string;
@ -33,6 +34,8 @@ export default function Index() {
const { links, getLink } = useLinkStore(); const { links, getLink } = useLinkStore();
const { setModal } = useModalStore(); const { setModal } = useModalStore();
const { settings } = useLocalSettingsStore();
const session = useSession(); const session = useSession();
const userId = session.data?.user.id; const userId = session.data?.user.id;
@ -144,7 +147,7 @@ export default function Index() {
<LinkLayout> <LinkLayout>
<div <div
className={`flex flex-col max-w-screen-md h-full ${ className={`flex flex-col max-w-screen-md h-full ${
"dark" ? "banner-dark-mode" : "banner-light-mode" settings.theme === "dark" ? "banner-dark-mode" : "banner-light-mode"
}`} }`}
> >
<div <div

View File

@ -13,8 +13,10 @@ import SubmitButton from "@/components/SubmitButton";
import React from "react"; import React from "react";
import Checkbox from "@/components/Checkbox"; import Checkbox from "@/components/Checkbox";
import LinkPreview from "@/components/LinkPreview"; import LinkPreview from "@/components/LinkPreview";
import useLocalSettingsStore from "@/store/localSettings";
export default function Appearance() { export default function Appearance() {
const { settings, updateSettings } = useLocalSettingsStore();
const submit = async () => { const submit = async () => {
setSubmitLoader(true); setSubmitLoader(true);
@ -75,8 +77,11 @@ export default function Appearance() {
<div className="flex gap-3 w-full"> <div className="flex gap-3 w-full">
<div <div
className={`w-full text-center outline-solid outline-sky-100 outline dark:outline-neutral-700 h-40 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-black ${ className={`w-full text-center outline-solid outline-sky-100 outline dark:outline-neutral-700 h-40 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-black ${
"dark" ? "dark:outline-sky-500 text-sky-500" : "text-white" localStorage.getItem("theme") === "dark"
? "dark:outline-sky-500 text-sky-500"
: "text-white"
}`} }`}
onClick={() => updateSettings({ theme: "dark" })}
> >
<FontAwesomeIcon icon={faMoon} className="w-1/2 h-1/2" /> <FontAwesomeIcon icon={faMoon} className="w-1/2 h-1/2" />
<p className="text-2xl">Dark Theme</p> <p className="text-2xl">Dark Theme</p>
@ -85,8 +90,11 @@ export default function Appearance() {
</div> </div>
<div <div
className={`w-full text-center outline-solid outline-sky-100 outline dark:outline-neutral-700 h-40 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-white ${ className={`w-full text-center outline-solid outline-sky-100 outline dark:outline-neutral-700 h-40 duration-100 rounded-md flex items-center justify-center cursor-pointer select-none bg-white ${
"light" ? "outline-sky-500 text-sky-500" : "text-black" localStorage.getItem("theme") === "light"
? "outline-sky-500 text-sky-500"
: "text-black"
}`} }`}
onClick={() => updateSettings({ theme: "light" })}
> >
<FontAwesomeIcon icon={faSun} className="w-1/2 h-1/2" /> <FontAwesomeIcon icon={faSun} className="w-1/2 h-1/2" />
<p className="text-2xl">Light Theme</p> <p className="text-2xl">Light Theme</p>

View File

@ -1,23 +1,45 @@
import { create } from "zustand"; import { create } from "zustand";
type LocalSettings = { type LocalSettings = {
darkMode: boolean; theme: string;
}; };
type LocalSettingsStore = { type LocalSettingsStore = {
settings: LocalSettings; settings: LocalSettings;
updateSettings: (settings: LocalSettings) => void; updateSettings: (settings: LocalSettings) => void;
setSettings: () => void;
}; };
const useLocalSettingsStore = create<LocalSettingsStore>((set) => ({ const useLocalSettingsStore = create<LocalSettingsStore>((set) => ({
settings: { settings: {
darkMode: false, theme: "",
}, },
updateSettings: async (newSettings) => { updateSettings: async (newSettings) => {
if (
newSettings.theme &&
newSettings.theme !== localStorage.getItem("theme")
) {
localStorage.setItem("theme", newSettings.theme);
const localTheme = localStorage.getItem("theme");
document
.querySelector("html")
?.setAttribute("data-theme", localTheme || "");
}
set((state) => ({ settings: { ...state.settings, ...newSettings } })); set((state) => ({ settings: { ...state.settings, ...newSettings } }));
}, },
setSettings: async () => {
if (!localStorage.getItem("theme")) {
localStorage.setItem("theme", "dark");
}
const localTheme = localStorage.getItem("theme");
document
.querySelector("html")
?.setAttribute("data-theme", localTheme || "");
},
})); }));
export default useLocalSettingsStore; export default useLocalSettingsStore;
// TODO: Add Dark mode.

View File

@ -2,8 +2,22 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
:root {
--my-color: #fff;
/* or any other variables/style */
}
[data-theme="dark"] {
--my-color: #000;
}
[data-theme="light"] {
--my-color: #ffabc8;
}
html, html,
body { body {
color-scheme: dark;
scroll-behavior: smooth; scroll-behavior: smooth;
} }
@ -140,11 +154,6 @@ body {
} }
/* Theme */ /* Theme */
@layer base {
body {
@apply dark:bg-neutral-900 bg-white text-black dark:text-white;
}
}
/* react-select */ /* react-select */
@layer components { @layer components {

View File

@ -10,7 +10,7 @@ module.exports = {
secondary: "#22d3ee", secondary: "#22d3ee",
accent: "#4f46e5", accent: "#4f46e5",
neutral: "#6b7280", neutral: "#6b7280",
"base-100": "#f5f5f4", "base-100": "#ffffff",
info: "#a5f3fc", info: "#a5f3fc",
success: "#22c55e", success: "#22c55e",
warning: "#facc15", warning: "#facc15",
@ -23,7 +23,7 @@ module.exports = {
secondary: "#0284c7", secondary: "#0284c7",
accent: "#818cf8", accent: "#818cf8",
neutral: "#1f2937", neutral: "#1f2937",
"base-100": "#fcfcfc", "base-100": "#171717",
info: "#009ee4", info: "#009ee4",
success: "#00b17d", success: "#00b17d",
warning: "#eac700", warning: "#eac700",