diff options
31 files changed, 138 insertions, 39 deletions
@@ -13,6 +13,7 @@ A self-hostable bookmark-everything app with a touch of AI for the data hoarders - ✨ AI-based (aka chatgpt) automatic tagging. - 🔖 [Chrome plugin](https://chromewebstore.google.com/detail/hoarder/kgcjekpmcjjogibpjebkhaanilehneje) for quick bookmarking. - 📱 An iOS app that's pending apple's review. +- 🌙 Dark mode support. - 💾 Self-hosting first. - [Planned] Archiving the content for offline reading. diff --git a/apps/web/app/dashboard/admin/page.tsx b/apps/web/app/dashboard/admin/page.tsx index 7b4c3cdd..c44d3142 100644 --- a/apps/web/app/dashboard/admin/page.tsx +++ b/apps/web/app/dashboard/admin/page.tsx @@ -2,6 +2,7 @@ import { useRouter } from "next/navigation"; import { ActionButton } from "@/components/ui/action-button"; +import { Separator } from "@/components/ui/separator"; import LoadingSpinner from "@/components/ui/spinner"; import { Table, @@ -96,7 +97,7 @@ function ServerStatsSection() { </TableRow> </TableBody> </Table> - <hr /> + <Separator /> <p className="text-xl">Background Jobs</p> <Table className="w-1/2"> <TableBody> @@ -190,13 +191,13 @@ export default function AdminPage() { } return ( - <div className="m-4 flex flex-col gap-5 rounded-md border bg-white p-4"> + <div className="m-4 flex flex-col gap-5 rounded-md border bg-background p-4"> <p className="text-2xl">Admin</p> - <hr /> + <Separator /> <ServerStatsSection /> - <hr /> + <Separator /> <UsersSection /> - <hr /> + <Separator /> <ActionsSection /> </div> ); diff --git a/apps/web/app/dashboard/bookmarks/layout.tsx b/apps/web/app/dashboard/bookmarks/layout.tsx index 8691e822..a2356d23 100644 --- a/apps/web/app/dashboard/bookmarks/layout.tsx +++ b/apps/web/app/dashboard/bookmarks/layout.tsx @@ -1,6 +1,7 @@ import React from "react"; import TopNav from "@/components/dashboard/bookmarks/TopNav"; import UploadDropzone from "@/components/dashboard/UploadDropzone"; +import { Separator } from "@/components/ui/separator"; export default function BookmarksLayout({ children, @@ -13,7 +14,7 @@ export default function BookmarksLayout({ <div> <TopNav /> </div> - <hr /> + <Separator /> <div className="my-4 flex-1 pb-4">{children}</div> </div> </UploadDropzone> diff --git a/apps/web/app/dashboard/layout.tsx b/apps/web/app/dashboard/layout.tsx index b2d3806b..68c0bfbd 100644 --- a/apps/web/app/dashboard/layout.tsx +++ b/apps/web/app/dashboard/layout.tsx @@ -15,7 +15,7 @@ export default async function Dashboard({ <div className="hidden flex-none sm:flex"> <Sidebar /> </div> - <main className="flex-1 bg-gray-100 sm:overflow-y-auto"> + <main className="flex-1 bg-muted sm:overflow-y-auto"> {serverConfig.demoMode && <DemoModeBanner />} <div className="block w-full sm:hidden"> <MobileSidebar /> diff --git a/apps/web/app/dashboard/lists/page.tsx b/apps/web/app/dashboard/lists/page.tsx index a8c53eb6..d379b1bb 100644 --- a/apps/web/app/dashboard/lists/page.tsx +++ b/apps/web/app/dashboard/lists/page.tsx @@ -1,4 +1,5 @@ import AllListsView from "@/components/dashboard/lists/AllListsView"; +import { Separator } from "@/components/ui/separator"; import { api } from "@/server/api/client"; export default async function ListsPage() { @@ -7,7 +8,7 @@ export default async function ListsPage() { return ( <div className="container mt-4 flex flex-col gap-3"> <p className="text-2xl">📋 All Lists</p> - <hr /> + <Separator /> <AllListsView initialData={lists.lists} /> </div> ); diff --git a/apps/web/app/dashboard/search/page.tsx b/apps/web/app/dashboard/search/page.tsx index 26b984a7..f09041f3 100644 --- a/apps/web/app/dashboard/search/page.tsx +++ b/apps/web/app/dashboard/search/page.tsx @@ -3,6 +3,7 @@ import { Suspense, useRef } from "react"; import BookmarksGrid from "@/components/dashboard/bookmarks/BookmarksGrid"; import { SearchInput } from "@/components/dashboard/search/SearchInput"; +import { Separator } from "@/components/ui/separator"; import { useBookmarkSearch } from "@/lib/hooks/bookmark-search"; import Loading from "../bookmarks/loading"; @@ -16,7 +17,7 @@ function SearchComp() { return ( <div className="container flex flex-col gap-3 p-4"> <SearchInput ref={inputRef} autoFocus={true} /> - <hr /> + <Separator /> {data ? <BookmarksGrid bookmarks={data.bookmarks} /> : <Loading />} </div> ); diff --git a/apps/web/app/dashboard/settings/page.tsx b/apps/web/app/dashboard/settings/page.tsx index 71712eb9..f75bc298 100644 --- a/apps/web/app/dashboard/settings/page.tsx +++ b/apps/web/app/dashboard/settings/page.tsx @@ -3,7 +3,7 @@ import { ChangePassword } from "@/components/dashboard/settings/ChangePassword"; export default async function Settings() { return ( - <div className="m-4 flex flex-col space-y-2 rounded-md border bg-white p-4"> + <div className="m-4 flex flex-col space-y-2 rounded-md border bg-background p-4"> <p className="text-2xl">Settings</p> <ChangePassword /> <ApiKeySettings /> diff --git a/apps/web/app/dashboard/tags/page.tsx b/apps/web/app/dashboard/tags/page.tsx index dec11527..ec09e34e 100644 --- a/apps/web/app/dashboard/tags/page.tsx +++ b/apps/web/app/dashboard/tags/page.tsx @@ -7,7 +7,7 @@ import { getServerAuthSession } from "@/server/auth"; function TagPill({ name, count }: { name: string; count: number }) { return ( <Link - className="flex gap-2 rounded-md border border-gray-200 bg-white px-2 py-1 text-foreground hover:bg-foreground hover:text-background" + className="flex gap-2 rounded-md border border-border bg-background px-2 py-1 text-foreground hover:bg-foreground hover:text-background" href={`/dashboard/tags/${name}`} > {name} <Separator orientation="vertical" /> {count} @@ -38,7 +38,7 @@ export default async function TagsPage() { return ( <div className="container mt-2 space-y-3"> <span className="text-2xl">All Tags</span> - <hr /> + <Separator /> <div className="flex flex-wrap gap-3">{tagPill}</div> </div> ); diff --git a/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx b/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx index 2c393fe7..96e1c19b 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarkPreview.tsx @@ -3,6 +3,7 @@ import Image from "next/image"; import Link from "next/link"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { Separator } from "@/components/ui/separator"; import { Skeleton } from "@/components/ui/skeleton"; import { Tooltip, @@ -82,7 +83,7 @@ function LinkHeader({ bookmark }: { bookmark: ZBookmark }) { <span className="my-auto">View Original</span> <ExternalLink /> </Link> - <hr /> + <Separator /> </div> ); } @@ -103,7 +104,7 @@ function TextContentSection({ bookmark }: { bookmark: ZBookmark }) { dangerouslySetInnerHTML={{ __html: bookmark.content.htmlContent || "", }} - className="prose mx-auto" + className="prose dark:prose-invert mx-auto" /> ); } @@ -111,7 +112,9 @@ function TextContentSection({ bookmark }: { bookmark: ZBookmark }) { } case "text": { content = ( - <Markdown className="prose mx-auto">{bookmark.content.text}</Markdown> + <Markdown className="prose dark:prose-invert mx-auto"> + {bookmark.content.text} + </Markdown> ); break; } @@ -195,7 +198,7 @@ export default function BookmarkPreview({ <div className="row-span-2 h-full w-full overflow-hidden p-2 md:col-span-2 lg:row-auto"> {isBookmarkStillCrawling(bookmark) ? <ContentLoading /> : content} </div> - <div className="lg:col-span1 row-span-1 flex flex-col gap-4 bg-gray-100 p-4 lg:row-auto"> + <div className="lg:col-span1 row-span-1 flex flex-col gap-4 bg-accent p-4 lg:row-auto"> {linkHeader} <CreationTime createdAt={bookmark.createdAt} /> <div className="flex gap-2"> diff --git a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx index cee620c9..81dd9361 100644 --- a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx +++ b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx @@ -1,4 +1,5 @@ import { redirect } from "next/navigation"; +import { Separator } from "@/components/ui/separator"; import { api } from "@/server/api/client"; import { getServerAuthSession } from "@/server/auth"; @@ -27,7 +28,7 @@ export default async function Bookmarks({ return ( <div className="container flex flex-col gap-3"> {header} - {showDivider && <hr />} + {showDivider && <Separator />} <UpdatableBookmarksGrid query={query} bookmarks={bookmarks} diff --git a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx index 39638553..048dab85 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx @@ -16,7 +16,7 @@ import TextCard from "./TextCard"; function BookmarkCard({ children }: { children: React.ReactNode }) { return ( - <Slot className="border-grey-100 mb-4 border bg-gray-50 duration-300 ease-in hover:shadow-lg hover:transition-all"> + <Slot className="mb-4 border border-border bg-card duration-300 ease-in hover:shadow-lg hover:transition-all"> {children} </Slot> ); diff --git a/apps/web/components/dashboard/bookmarks/EditorCard.tsx b/apps/web/components/dashboard/bookmarks/EditorCard.tsx index dfcf1f6c..d8a3c117 100644 --- a/apps/web/components/dashboard/bookmarks/EditorCard.tsx +++ b/apps/web/components/dashboard/bookmarks/EditorCard.tsx @@ -1,6 +1,7 @@ import type { SubmitErrorHandler, SubmitHandler } from "react-hook-form"; import { ActionButton } from "@/components/ui/action-button"; import { Form, FormControl, FormField, FormItem } from "@/components/ui/form"; +import { Separator } from "@/components/ui/separator"; import { Textarea } from "@/components/ui/textarea"; import { toast } from "@/components/ui/use-toast"; import { api } from "@/lib/trpc"; @@ -55,12 +56,12 @@ export default function EditorCard({ className }: { className?: string }) { <form className={cn( className, - "flex h-96 flex-col gap-2 rounded-xl bg-white p-4", + "flex h-96 flex-col gap-2 rounded-xl bg-card p-4", )} onSubmit={form.handleSubmit(onSubmit, onError)} > <p className="text-sm">NEW ITEM</p> - <hr /> + <Separator /> <FormField control={form.control} name="text" diff --git a/apps/web/components/dashboard/bookmarks/LinkCard.tsx b/apps/web/components/dashboard/bookmarks/LinkCard.tsx index 3451013d..9796ed4f 100644 --- a/apps/web/components/dashboard/bookmarks/LinkCard.tsx +++ b/apps/web/components/dashboard/bookmarks/LinkCard.tsx @@ -84,7 +84,7 @@ export default function LinkCard({ <div className="mt-1 flex justify-between text-gray-500"> <div className="my-auto"> <Link - className="line-clamp-1 hover:text-black" + className="line-clamp-1 hover:text-foreground" href={link.url} target="_blank" > diff --git a/apps/web/components/dashboard/bookmarks/TagsEditor.tsx b/apps/web/components/dashboard/bookmarks/TagsEditor.tsx index bebd53df..e11410b8 100644 --- a/apps/web/components/dashboard/bookmarks/TagsEditor.tsx +++ b/apps/web/components/dashboard/bookmarks/TagsEditor.tsx @@ -99,6 +99,17 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { closeMenuOnSelect={false} isClearable={false} isLoading={isExistingTagsLoading || isMutating} + theme={(theme) => ({ + ...theme, + // This color scheme doesn't support disabled options. + colors: { + ...theme.colors, + primary: "hsl(var(--accent))", + primary50: "hsl(var(--accent))", + primary75: "hsl(var(--accent))", + primary25: "hsl(var(--accent))", + }, + })} styles={{ multiValueRemove: () => ({ "background-color": "transparent", @@ -110,6 +121,14 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { overflowY: "auto", scrollbarWidth: "none", }), + control: (styles) => ({ + ...styles, + "background-color": "hsl(var(--background))", + "border-color": "hsl(var(--border))", + ":hover": { + "border-color": "hsl(var(--border))", + }, + }), }} components={{ MultiValueContainer: ({ children, data }) => ( @@ -118,7 +137,7 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { "flex min-h-8 space-x-1 rounded px-2", (data as { attachedBy: string }).attachedBy == "ai" ? "bg-gradient-to-tr from-purple-500 to-purple-400 text-white" - : "bg-gray-200", + : "bg-accent", )} > {children} @@ -137,8 +156,9 @@ export function TagsEditor({ bookmark }: { bookmark: ZBookmark }) { }} classNames={{ multiValueRemove: () => "my-auto", - valueContainer: () => "gap-2", - menuList: () => "text-sm", + valueContainer: () => "gap-2 bg-background", + menuList: () => "text-sm bg-background", + option: () => "text-red-500", }} /> ); diff --git a/apps/web/components/dashboard/bookmarks/TextCard.tsx b/apps/web/components/dashboard/bookmarks/TextCard.tsx index 75733063..82664390 100644 --- a/apps/web/components/dashboard/bookmarks/TextCard.tsx +++ b/apps/web/components/dashboard/bookmarks/TextCard.tsx @@ -58,7 +58,7 @@ export default function TextCard({ ), )} > - <Markdown className="prose grow overflow-hidden"> + <Markdown className="prose dark:prose-invert grow overflow-hidden"> {bookmarkedText.text} </Markdown> <div className="mt-4 flex flex-none flex-wrap gap-1 overflow-hidden"> diff --git a/apps/web/components/dashboard/lists/AllListsView.tsx b/apps/web/components/dashboard/lists/AllListsView.tsx index acb94edb..4159bc14 100644 --- a/apps/web/components/dashboard/lists/AllListsView.tsx +++ b/apps/web/components/dashboard/lists/AllListsView.tsx @@ -20,7 +20,7 @@ function ListItem({ }) { return ( <Link href={path}> - <div className="rounded-md border border-gray-200 bg-background px-4 py-2 text-lg"> + <div className="rounded-md border border-border bg-background px-4 py-2 text-lg"> <p className="text-nowrap"> {icon} {name} </p> diff --git a/apps/web/components/dashboard/settings/ApiKeySettings.tsx b/apps/web/components/dashboard/settings/ApiKeySettings.tsx index a3680863..1455e1b6 100644 --- a/apps/web/components/dashboard/settings/ApiKeySettings.tsx +++ b/apps/web/components/dashboard/settings/ApiKeySettings.tsx @@ -1,3 +1,4 @@ +import { Separator } from "@/components/ui/separator"; import { Table, TableBody, @@ -16,7 +17,7 @@ export default async function ApiKeys() { return ( <div className="pt-4"> <span className="text-xl">API Keys</span> - <hr className="my-2" /> + <Separator className="my-2" /> <div className="flex flex-col space-y-3"> <div className="flex flex-1 justify-end"> <AddApiKey /> diff --git a/apps/web/components/dashboard/settings/ChangePassword.tsx b/apps/web/components/dashboard/settings/ChangePassword.tsx index d976f3e4..a2ca0870 100644 --- a/apps/web/components/dashboard/settings/ChangePassword.tsx +++ b/apps/web/components/dashboard/settings/ChangePassword.tsx @@ -11,6 +11,7 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { Separator } from "@/components/ui/separator"; import { toast } from "@/components/ui/use-toast"; import { api } from "@/lib/trpc"; import { zodResolver } from "@hookform/resolvers/zod"; @@ -55,7 +56,7 @@ export function ChangePassword() { return ( <div className="w-full pt-4"> <span className="text-xl">Change Password</span> - <hr className="my-2" /> + <Separator className="my-2" /> <Form {...form}> <form onSubmit={form.handleSubmit(onSubmit)} diff --git a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx index 3c68433a..7306308d 100644 --- a/apps/web/components/dashboard/sidebar/ModileSidebar.tsx +++ b/apps/web/components/dashboard/sidebar/ModileSidebar.tsx @@ -12,7 +12,7 @@ import SidebarProfileOptions from "./SidebarProfileOptions"; export default async function MobileSidebar() { return ( <aside className="w-full"> - <ul className="flex justify-between space-x-2 border-b-black bg-gray-100 px-5 py-2 pt-5"> + <ul className="flex justify-between space-x-2 border-b-black px-5 py-2 pt-5"> <MobileSidebarItem logo={<PackageOpen />} path="/dashboard/bookmarks" /> <MobileSidebarItem logo={<Search />} path="/dashboard/search" /> <MobileSidebarItem logo={<ClipboardList />} path="/dashboard/lists" /> diff --git a/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx index d2b4aad3..3382f47b 100644 --- a/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx +++ b/apps/web/components/dashboard/sidebar/ModileSidebarItem.tsx @@ -15,8 +15,8 @@ export default function MobileSidebarItem({ return ( <li className={cn( - "flex w-full rounded-lg hover:bg-gray-50", - path == currentPath ? "bg-gray-50" : "", + "flex w-full rounded-lg hover:bg-background", + path == currentPath ? "bg-background" : "", )} > <Link href={path} className="mx-auto px-3 py-2"> diff --git a/apps/web/components/dashboard/sidebar/Sidebar.tsx b/apps/web/components/dashboard/sidebar/Sidebar.tsx index 0351b889..1c18e90c 100644 --- a/apps/web/components/dashboard/sidebar/Sidebar.tsx +++ b/apps/web/components/dashboard/sidebar/Sidebar.tsx @@ -22,12 +22,12 @@ export default async function Sidebar() { return ( <aside className="flex h-screen w-60 flex-col gap-5 border-r p-4"> <Link href={"/dashboard/bookmarks"}> - <div className="flex items-center rounded-lg px-1 text-slate-900"> + <div className="flex items-center rounded-lg px-1 text-foreground"> <PackageOpen /> <span className="ml-2 text-base font-semibold">Hoarder</span> </div> </Link> - <hr /> + <Separator /> <div> <ul className="space-y-2 text-sm font-medium"> <SidebarItem diff --git a/apps/web/components/dashboard/sidebar/SidebarItem.tsx b/apps/web/components/dashboard/sidebar/SidebarItem.tsx index 75a1f6ba..7e5eb3bd 100644 --- a/apps/web/components/dashboard/sidebar/SidebarItem.tsx +++ b/apps/web/components/dashboard/sidebar/SidebarItem.tsx @@ -19,8 +19,8 @@ export default function SidebarItem({ return ( <li className={cn( - "rounded-lg px-3 py-2 hover:bg-slate-100", - path == currentPath ? "bg-gray-50" : "", + "rounded-lg px-3 py-2 hover:bg-accent", + path == currentPath ? "bg-accent/50" : "", className, )} > diff --git a/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx b/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx index f931b63e..bf56b805 100644 --- a/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx +++ b/apps/web/components/dashboard/sidebar/SidebarProfileOptions.tsx @@ -7,8 +7,32 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { LogOut, MoreHorizontal } from "lucide-react"; +import { Slot } from "@radix-ui/react-slot"; +import { LogOut, Moon, MoreHorizontal, Sun } from "lucide-react"; import { signOut } from "next-auth/react"; +import { useTheme } from "next-themes"; + +function DarkModeToggle() { + const { theme, setTheme } = useTheme(); + + let comp; + if (theme == "dark") { + comp = ( + <button onClick={() => setTheme("light")}> + <Sun className="size-4" /> + <p>Light Mode</p> + </button> + ); + } else { + comp = ( + <button onClick={() => setTheme("dark")}> + <Moon className="size-4" /> + <p>Dark Mode</p> + </button> + ); + } + return <Slot className="flex flex-row gap-2">{comp}</Slot>; +} export default function SidebarProfileOptions() { return ( @@ -19,6 +43,9 @@ export default function SidebarProfileOptions() { </Button> </DropdownMenuTrigger> <DropdownMenuContent className="w-fit"> + <DropdownMenuItem> + <DarkModeToggle /> + </DropdownMenuItem> <DropdownMenuItem onClick={() => signOut({ diff --git a/apps/web/components/signin/CredentialsForm.tsx b/apps/web/components/signin/CredentialsForm.tsx index 5e3b4de9..8d7136cb 100644 --- a/apps/web/components/signin/CredentialsForm.tsx +++ b/apps/web/components/signin/CredentialsForm.tsx @@ -53,7 +53,7 @@ function SignIn() { > <div className="flex w-full flex-col space-y-2"> {signinError && ( - <p className="w-full text-center text-red-500"> + <p className="w-full text-center text-destructive"> Incorrect username or password </p> )} @@ -137,7 +137,9 @@ function SignUp() { > <div className="flex w-full flex-col space-y-2"> {errorMessage && ( - <p className="w-full text-center text-red-500">{errorMessage}</p> + <p className="w-full text-center text-destructive"> + {errorMessage} + </p> )} <FormField control={form.control} diff --git a/apps/web/components/theme-provider.tsx b/apps/web/components/theme-provider.tsx new file mode 100644 index 00000000..8efcd93b --- /dev/null +++ b/apps/web/components/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client"; + +import type { ThemeProviderProps } from "next-themes/dist/types"; +import * as React from "react"; +import { ThemeProvider as NextThemesProvider } from "next-themes"; + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return <NextThemesProvider {...props}>{children}</NextThemesProvider>; +} diff --git a/apps/web/lib/providers.tsx b/apps/web/lib/providers.tsx index ce667f8d..b700d0c1 100644 --- a/apps/web/lib/providers.tsx +++ b/apps/web/lib/providers.tsx @@ -2,6 +2,7 @@ import type { Session } from "next-auth"; import React, { useState } from "react"; +import { ThemeProvider } from "@/components/theme-provider"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { httpBatchLink, loggerLink } from "@trpc/client"; import { SessionProvider } from "next-auth/react"; @@ -73,7 +74,14 @@ export default function Providers({ <SessionProvider session={session}> <api.Provider client={trpcClient} queryClient={queryClient}> <QueryClientProvider client={queryClient}> - {children} + <ThemeProvider + attribute="class" + defaultTheme="system" + enableSystem + disableTransitionOnChange + > + {children} + </ThemeProvider> </QueryClientProvider> </api.Provider> </SessionProvider> diff --git a/apps/web/package.json b/apps/web/package.json index aa38b882..a81079f5 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -47,6 +47,7 @@ "next": "14.1.4", "next-auth": "^4.24.5", "next-pwa": "^5.6.0", + "next-themes": "^0.3.0", "prettier": "^3.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/docs/docs/01-intro.md b/docs/docs/01-intro.md index 4aae4b79..e5eac1dc 100644 --- a/docs/docs/01-intro.md +++ b/docs/docs/01-intro.md @@ -18,6 +18,7 @@ Hoarder is an open source "Bookmark Everything" app that uses AI for automatical - ✨ AI-based (aka chatgpt) automatic tagging. - 🔖 [Chrome plugin](https://chromewebstore.google.com/detail/hoarder/kgcjekpmcjjogibpjebkhaanilehneje) for quick bookmarking. - 📱 An iOS app that's pending apple's review. +- 🌙 Dark mode support. - 💾 Self-hosting first. - [Planned] Archiving the content for offline reading. diff --git a/docs/docs/04-screenshots.md b/docs/docs/04-screenshots.md index 03137367..4c211276 100644 --- a/docs/docs/04-screenshots.md +++ b/docs/docs/04-screenshots.md @@ -4,6 +4,10 @@  +## Homepage (Dark Mode) + + + ## Tags  diff --git a/docs/static/img/screenshots/homepage-dark.png b/docs/static/img/screenshots/homepage-dark.png Binary files differnew file mode 100644 index 00000000..41279c84 --- /dev/null +++ b/docs/static/img/screenshots/homepage-dark.png diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1ed0ff4..6b87e252 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -430,6 +430,9 @@ importers: next-pwa: specifier: ^5.6.0 version: 5.6.0(@babel/core@7.24.0)(next@14.1.4(@babel/core@7.24.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(webpack@5.90.3) + next-themes: + specifier: ^0.3.0 + version: 0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) prettier: specifier: ^3.2.5 version: 3.2.5 @@ -8466,6 +8469,12 @@ packages: peerDependencies: next: '>=9.0.0' + next-themes@0.3.0: + resolution: {integrity: sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w==} + peerDependencies: + react: ^16.8 || ^17 || ^18 + react-dom: ^16.8 || ^17 || ^18 + next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} @@ -23692,6 +23701,12 @@ snapshots: - webpack dev: false + next-themes@0.3.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + next-tick@1.1.0: dev: true |
