Skip to content

Commit 0891e0d

Browse files
committed
dark mode
1 parent 2a65b91 commit 0891e0d

24 files changed

+280
-158
lines changed

apps/desktop-v2/app/globals.css

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
11
@tailwind base;
22
@tailwind components;
3-
@tailwind utilities;
4-
5-
body {
6-
background-color: white;
7-
}
3+
@tailwind utilities;

apps/desktop-v2/app/layout.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import "./globals.css";
22
import type { Metadata } from "next";
33
import { manrope } from "@/components/fonts";
4-
import { ToastClientWrapper } from "./toast-client-wrapper";
4+
import { SupernovaToastProvider } from "./supernova-toast-provider";
5+
import { ThemeProvider } from "./theme-provider";
56

67
export const metadata: Metadata = {
78
title: "Supernova | Today",
@@ -12,15 +13,20 @@ interface RootLayoutProps {
1213
}
1314

1415
function RootLayout({ children }: RootLayoutProps) {
16+
const isDesktop = process.env.TAURI_PLATFORM !== undefined; // because this means it's local maybe; TODO: check if this is the case
1517
return (
1618
<html lang="en">
1719
<body className={manrope.className}>
1820
{/* drag region because titlebar is overlay */}
19-
<div
20-
data-tauri-drag-region="self"
21-
className="h-5 bg-transparent z-10 absolute top-0"
22-
/>
23-
<ToastClientWrapper>{children}</ToastClientWrapper>
21+
{isDesktop && (
22+
<div
23+
data-tauri-drag-region="self"
24+
className="h-7 bg-transparent border-b border-gray-200 dark:border-zinc-700 sticky top-0 bg-white dark:bg-zinc-900"
25+
/>
26+
)}
27+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
28+
<SupernovaToastProvider>{children}</SupernovaToastProvider>
29+
</ThemeProvider>
2430
</body>
2531
</html>
2632
);

apps/desktop-v2/app/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,10 @@ function Home() {
142142
collapsible
143143
>
144144
<Accordion.AccordionItem value="supernova-dones">
145-
<Accordion.AccordionTrigger className="flex items-center justify-between w-full hover:bg-gray-100 rounded px-1">
146-
<p className="text-xs text-teal-800">Dones ({doneTasks.length})</p>{" "}
145+
<Accordion.AccordionTrigger className="flex items-center justify-between w-full hover:bg-gray-100 dark:hover:bg-zinc-800 rounded px-1">
146+
<p className="text-xs text-teal-800 dark:text-teal-500">
147+
Dones ({doneTasks.length})
148+
</p>{" "}
147149
<ChevronDownIcon className="text-teal-800" />
148150
</Accordion.AccordionTrigger>
149151
<Accordion.AccordionContent className="py-2">

apps/desktop-v2/app/settings/page.tsx

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
"use client";
22

3-
import { ChevronLeftIcon } from "@radix-ui/react-icons";
3+
import {
4+
ChevronLeftIcon,
5+
ExitIcon,
6+
GitHubLogoIcon,
7+
} from "@radix-ui/react-icons";
48
import Link from "next/link";
59
import { homeRoute } from "../meta";
610
import { Button } from "../../components/button";
@@ -13,10 +17,15 @@ import { withAuth } from "@/hocs/withAuth";
1317
import { authRoute } from "../auth/meta";
1418
import { AlertDialog } from "../../components/alert-dialog";
1519
import useSupernovaToast from "@/hooks/useSupernovaToast";
20+
import { useTheme } from "next-themes";
1621

1722
const SettingsPage = () => {
1823
const { makeToast } = useSupernovaToast();
1924
const router = useRouter();
25+
const [open, setOpen] = useState(false);
26+
const [isMounted, setIsMounted] = useState(false);
27+
const { theme, setTheme } = useTheme();
28+
2029
useEffect(() => {
2130
Mousetrap.bind("esc", () => {
2231
router.push(homeRoute);
@@ -25,7 +34,18 @@ const SettingsPage = () => {
2534
Mousetrap.unbind("esc");
2635
};
2736
}, [router]);
28-
const [open, setOpen] = useState(false);
37+
38+
useEffect(() => {
39+
setIsMounted(true);
40+
}, []);
41+
42+
useEffect(() => {
43+
console.log(theme);
44+
}, [theme]);
45+
46+
if (!isMounted) {
47+
return null;
48+
}
2949

3050
return (
3151
<main className="flex max-h-screen flex-col items-center pt-5 mb-10 px-5 gap-[10px]">
@@ -51,7 +71,7 @@ const SettingsPage = () => {
5171
</div>
5272
<h1 className="text-xl font-semibold">Settings</h1>
5373
<hr className="h-[2px] w-32 bg-gray-300" />
54-
<div className="flex flex-col w-full gap-4">
74+
<div className="flex flex-col w-full max-w-lg gap-4">
5575
<div className="flex justify-between">
5676
<div className="inline-flex gap-2">
5777
<Image
@@ -81,26 +101,40 @@ const SettingsPage = () => {
81101
<Button disabled>Coming soon</Button>
82102
</div>
83103
<div className="flex justify-between">
84-
<div className="inline-flex gap-2">
85-
<Image
86-
src="/icons/svg/github.png"
87-
width={25}
88-
height={20}
89-
unoptimized
90-
alt="Github icon"
91-
/>
104+
<div className="inline-flex gap-2 items-center">
105+
<GitHubLogoIcon />
92106
<p>Pull issues and PRs from Github</p>
93107
</div>
94108
<Button disabled>Coming soon</Button>
95109
</div>
110+
<div className="flex justify-between">
111+
<div className="inline-flex gap-2">
112+
<p>Appearance</p>
113+
</div>
114+
<select
115+
className="border rounded-md p-1 bg-black text-white"
116+
name="appearance"
117+
value={theme}
118+
onChange={(e) => {
119+
e.currentTarget.value === "system"
120+
? setTheme("system")
121+
: setTheme(e.currentTarget.value);
122+
}}
123+
>
124+
<option value="system">System setting</option>
125+
<option value="light">Light</option>
126+
<option value="dark">Dark</option>
127+
</select>
128+
</div>
96129
</div>
97130
<Button
98-
className="mt-auto"
131+
className="mt-auto gap-1"
99132
onClick={() => {
100133
setOpen(true);
101134
}}
102135
>
103136
Logout
137+
<ExitIcon />
104138
</Button>
105139
</main>
106140
);

apps/desktop-v2/app/toast-client-wrapper.tsx renamed to apps/desktop-v2/app/supernova-toast-provider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { PropsWithChildren } from "react";
44
import { Toaster } from "sonner";
55

6-
export const ToastClientWrapper: React.FC<PropsWithChildren> = ({
6+
export const SupernovaToastProvider: React.FC<PropsWithChildren> = ({
77
children,
88
}) => {
99
return (
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use client";
2+
import * as React from "react";
3+
import { ThemeProvider as NextThemesProvider } from "next-themes";
4+
import type { ThemeProviderProps } from "next-themes/dist/types";
5+
6+
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
7+
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
8+
}

apps/desktop-v2/components/alert-dialog.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ export const AlertDialog = ({
2929
return (
3030
<Dialog.Root open={open} onOpenChange={setOpen}>
3131
<Dialog.Portal>
32-
<Dialog.Overlay className={`bg-gray-400 opacity-50 fixed inset-0`} />
32+
<Dialog.Overlay
33+
className={`bg-gray-400 dark:bg-zinc-900 opacity-50 fixed inset-0`}
34+
/>
3335
<Dialog.Content
34-
className={`bg-white p-3 data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none`}
36+
className={`bg-white dark:bg-zinc-800 dark:border dark:border-zinc-600 p-3 data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none`}
3537
>
3638
<div className="flex flex-col">{description}</div>
3739
<div className="flex justify-end">

apps/desktop-v2/components/button.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
1-
import { ButtonHTMLAttributes } from "react";
1+
import useUserSettings from "@/hooks/useUserSettings";
2+
import { useTheme } from "next-themes";
3+
import { ButtonHTMLAttributes, useEffect } from "react";
24
import { twMerge } from "tailwind-merge";
35

46
type Props = ButtonHTMLAttributes<HTMLButtonElement> & {
5-
bgVariant?: "black" | "white";
7+
bgVariant?: "black" | "white" | "red";
68
};
79

8-
export const Button = ({ bgVariant = "black", ...props }: Props) => {
10+
export const Button = ({ bgVariant, ...props }: Props) => {
11+
const { theme } = useTheme();
12+
const { systemAppearance } = useUserSettings();
13+
// if not set, set bgVariant based on theme and system appearance
14+
if (bgVariant === undefined) {
15+
if (theme === "dark") {
16+
bgVariant = "white";
17+
} else if (theme === "light") {
18+
bgVariant = "black";
19+
} else {
20+
if (systemAppearance === "dark") {
21+
bgVariant = "white";
22+
} else {
23+
bgVariant = "black";
24+
}
25+
}
26+
}
927
return (
1028
<button
1129
{...props}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from "react";
2+
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
3+
import { CheckIcon } from "@radix-ui/react-icons";
4+
import { twMerge } from "tailwind-merge";
5+
6+
export const CustomCheckbox = React.forwardRef<
7+
React.ElementRef<typeof CheckboxPrimitive.Root>,
8+
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
9+
>(({ className, ...props }, ref) => {
10+
return (
11+
<CheckboxPrimitive.Root
12+
ref={ref}
13+
className={twMerge(
14+
`h-4 w-4 shrink-0 rounded-sm border border-slate-300 dark:border-zinc-700 bg-white dark:bg-zinc-700 shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 ${
15+
props.checked &&
16+
"bg-green-400 dark:bg-green-600 data-[state=checked]:text-white"
17+
}`,
18+
className
19+
)}
20+
{...props}
21+
>
22+
<CheckboxPrimitive.Indicator
23+
className={"flex items-center justify-center text-current"}
24+
>
25+
{props.checked && (
26+
<CheckIcon className="h-full w-full data-[state=checked]:visible" />
27+
)}
28+
</CheckboxPrimitive.Indicator>
29+
</CheckboxPrimitive.Root>
30+
);
31+
});
32+
CustomCheckbox.displayName = CheckboxPrimitive.Root.displayName;

apps/desktop-v2/components/command-center.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ export const SupernovaCommandCenter = ({
3636
return (
3737
<Dialog.Root open={open} onOpenChange={setOpen}>
3838
<Dialog.Portal>
39-
<Dialog.Overlay className={`bg-gray-400 opacity-50 fixed inset-0`} />
39+
<Dialog.Overlay
40+
className={`bg-gray-400 dark:bg-zinc-950 opacity-70 fixed inset-0`}
41+
/>
4042
<Dialog.Content
4143
className={`data-[state=open]:animate-contentShow fixed top-[50%] left-[50%] max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] rounded-[6px] shadow-[hsl(206_22%_7%_/_35%)_0px_10px_38px_-10px,_hsl(206_22%_7%_/_20%)_0px_10px_20px_-15px] focus:outline-none`}
4244
>
43-
<Command className="bg-white rounded-lg p-4 flex flex-col gap-2">
45+
<Command className="bg-white dark:bg-zinc-800 rounded-lg p-4 flex flex-col gap-2">
4446
{context.chosenTask !== undefined &&
4547
context.chosenTask !== null && (
4648
<div>
@@ -61,7 +63,7 @@ export const SupernovaCommandCenter = ({
6163
<SupernovaGlobeLogoImage width={20} height={20} priority />
6264
<Command.Input
6365
placeholder="Find a command..."
64-
className="outline-none"
66+
className="outline-none bg-transparent"
6567
autoFocus
6668
/>
6769
</div>
@@ -74,7 +76,7 @@ export const SupernovaCommandCenter = ({
7476
{commands.map((command) => (
7577
<Command.Item
7678
key={command.label}
77-
className=" data-[selected='true']:bg-slate-100 flex items-center gap-2 justify-between hover:bg-slate-200 rounded-md px-2 py-1"
79+
className=" data-[selected='true']:bg-slate-100 dark:data-[selected='true']:bg-zinc-900 data-[selected='true']:cursor-pointer flex items-center gap-2 justify-between hover:bg-slate-200 rounded-md px-2 py-1"
7880
onSelect={() => {
7981
setOpen(false);
8082
command.cb();

0 commit comments

Comments
 (0)