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:
parent
b62771139e
commit
b10280712a
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { Outlet } from "react-router-dom"
|
||||
|
||||
import { useDark } from "./hooks/useDark"
|
||||
|
||||
function App() {
|
||||
useDark()
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
}
|
||||
}
|
||||
|
|
@ -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 />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue