feat: dark mode (#12)

* feat: dark mode

* update

* update

* refactor: move to settings

---------

Co-authored-by: DIYgod <i@diygod.me>
This commit is contained in:
Stephen Zhou 2024-05-26 22:57:30 +08:00 committed by GitHub
parent b62771139e
commit b10280712a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 124 additions and 43 deletions

View File

@ -55,6 +55,8 @@
"framer-motion": "11.2.6",
"hast-util-to-jsx-runtime": "2.3.0",
"jotai": "2.8.1",
"jotai-dark": "^0.3.0",
"jotai-effect": "^1.0.0",
"lethargy": "1.0.9",
"lucide-react": "0.379.0",
"ofetch": "1.3.4",

View File

@ -104,6 +104,12 @@ importers:
jotai:
specifier: 2.8.1
version: 2.8.1(@types/react@18.3.3)(react@18.3.1)
jotai-dark:
specifier: ^0.3.0
version: 0.3.0(jotai-effect@1.0.0(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1)))(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1))(react@18.3.1)
jotai-effect:
specifier: ^1.0.0
version: 1.0.0(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1))
lethargy:
specifier: 1.0.9
version: 1.0.9
@ -3439,6 +3445,28 @@ packages:
jose@5.3.0:
resolution: {integrity: sha512-IChe9AtAE79ru084ow8jzkN2lNrG3Ntfiv65Cvj9uOCE2m5LNsdHG+9EbxWxAoWRF9TgDOqLN5jm08++owDVRg==}
jotai-dark@0.3.0:
resolution: {integrity: sha512-Vuhymer1VLaAjSW+hLowZBZa0FSKMamo3xajXubCr0Jdnp5P80vrh/5s29EQ2cp3eSa9weuUy+kdoMKEDdp/sA==}
peerDependencies:
foxact: ^0.2.33
jotai: '>=2.5.0'
jotai-effect: '*'
react: ^18.2.0
peerDependenciesMeta:
foxact:
optional: true
jotai:
optional: true
jotai-effect:
optional: true
react:
optional: true
jotai-effect@1.0.0:
resolution: {integrity: sha512-eCgKKG4BACDzuJGYTu0xZRk1C1MEOvbAhC3L8w7YufQ2lSLORwNX/WFnCuZxLFX0sDLkTUeoUzOYaw8wnXY+UQ==}
peerDependencies:
jotai: '>=2.5.0'
jotai@2.8.1:
resolution: {integrity: sha512-Gmk5Y3yJL/vN5S0rQ6AaWpXH5Q+HBGHThMHXfylVzXGVuO8YxPRtZf8Y9XYvl+h7ZMQXoHNdFi37vNsJFsiszQ==}
engines: {node: '>=12.20.0'}
@ -8871,6 +8899,16 @@ snapshots:
jose@5.3.0: {}
jotai-dark@0.3.0(jotai-effect@1.0.0(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1)))(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1))(react@18.3.1):
optionalDependencies:
jotai: 2.8.1(@types/react@18.3.3)(react@18.3.1)
jotai-effect: 1.0.0(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1))
react: 18.3.1
jotai-effect@1.0.0(jotai@2.8.1(@types/react@18.3.3)(react@18.3.1)):
dependencies:
jotai: 2.8.1(@types/react@18.3.3)(react@18.3.1)
jotai@2.8.1(@types/react@18.3.3)(react@18.3.1):
optionalDependencies:
'@types/react': 18.3.3

View File

@ -1,6 +1,9 @@
import { Outlet } from "react-router-dom"
import { useDark } from "./hooks/useDark"
function App() {
useDark()
return (
<>
<div

View File

@ -1,7 +1,6 @@
body,
#root {
@apply h-screen;
@apply text-zinc-700;
@apply cursor-default;
@apply select-none;
@ -24,3 +23,7 @@ a {
.prose a {
@apply cursor-pointer;
}
.dark {
color-scheme: dark;
}

View File

@ -5,64 +5,69 @@
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--popover-foreground: 240 10% 3.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--destructive-foreground: 0 0% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--native: 30 3.2% 87.8%;
--native-active: 60 1.8% 78.4%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--background: 0, 0%, 11.8%;
--foreground: 0 0% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--destructive-foreground: 0 0% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--native: 30 1.7% 23.5%;
--native-active: 20 2.1% 28.4%;
}
}
@ -71,6 +76,6 @@
@apply border-border;
}
body {
@apply text-foreground;
@apply text-foreground/75;
}
}

View File

@ -0,0 +1,14 @@
import { useDark } from "@renderer/hooks/useDark"
import { Switch } from "./ui/switch"
export function AppearanceSwitch() {
const { toggleDark, isDark } = useDark()
return (
<div className="flex items-center justify-between gap-4">
<p>Dark Mode</p>
<Switch checked={isDark} onCheckedChange={toggleDark} />
</div>
)
}

View File

@ -62,8 +62,8 @@ export function EntryItemWrapper({
key={entry.id}
className={cn(
"rounded-md transition-colors",
activeEntry === entry.id && "bg-[#DEDDDC]",
entry.read && "text-gray-500 opacity-90",
activeEntry === entry.id && "bg-native-active",
entry.read && "text-foreground/50",
)}
ref={itemRef}
onClick={(e) => {

View File

@ -51,7 +51,7 @@ export function EntryContent({ entryId }: { entryId: ActiveEntry }) {
new Date(entry.data?.publishedAt).toUTCString()}
</div>
</a>
<div className="prose prose-zinc mx-auto mb-32 mt-10 max-w-[550px] cursor-auto select-text text-[15px]">
<div className="prose prose-zinc mx-auto mb-32 mt-10 max-w-[550px] cursor-auto select-text break-all text-[15px] dark:prose-invert">
{content}
</div>
</div>

View File

@ -0,0 +1,13 @@
import { useAtom } from "jotai"
import { atomDark } from "jotai-dark"
const isDarkAtom = atomDark()
export function useDark() {
const [isDark, setIsDark] = useAtom(isDarkAtom)
return {
isDark,
toggleDark: setIsDark as () => void,
theme: (isDark ? "dark" : "light") as "dark" | "light",
}
}

View File

@ -1,3 +1,5 @@
import { AppearanceSwitch } from "@renderer/components/appearance-switch"
export function Component() {
return (
<>
@ -5,6 +7,7 @@ export function Component() {
<i className="i-mingcute-settings-7-line text-xl" />
General
</h1>
<AppearanceSwitch />
</>
)
}

View File

@ -40,8 +40,8 @@ export function Component() {
{tabs.map((t) => (
<Link
key={t.path}
className={`my-1 flex items-center rounded-md px-2.5 py-[3px] text-[15px] font-medium leading-loose text-zinc-600 transition-colors ${
tab === t.path ? "bg-native-active text-zinc-900" : ""
className={`my-1 flex items-center rounded-md px-2.5 py-[3px] text-[15px] font-medium leading-loose text-foreground/70 transition-colors ${
tab === t.path ? "bg-native-active text-foreground/90" : ""
}`}
to={`/settings/${t.path}`}
>

View File

@ -3,7 +3,7 @@ const { iconsPlugin, getIconCollections } = require("@egoist/tailwindcss-icons")
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: ["class"],
content: ["./src/**/*.tsx"],
content: ["./src/**/*.{ts,tsx}"],
prefix: "",
theme: {
container: {
@ -49,8 +49,8 @@ module.exports = {
foreground: "hsl(var(--card-foreground))",
},
native: {
DEFAULT: "#E1E0DF",
active: "#C9C9C7",
DEFAULT: "hsl(var(--native))",
active: "hsl(var(--native-active))",
},
},
borderRadius: {