aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/header
diff options
context:
space:
mode:
authorMd Saban <45597394+mdsaban@users.noreply.github.com>2024-10-12 18:37:20 +0530
committerGitHub <noreply@github.com>2024-10-12 14:07:20 +0100
commit1f768be0485bbfa6b542dd24183fe8389acb9355 (patch)
treeb803eefba19cddfad988b3bd1979b693fbc0f694 /apps/web/components/dashboard/header
parente2644ebc11e9521ece054a846f8c993c322a8332 (diff)
downloadkarakeep-1f768be0485bbfa6b542dd24183fe8389acb9355.tar.zst
feature(web): Introduce a new sticky navbar. Fixes 520 (#515)
* ui: add global header * fix: design fixes * fix: tests * fix navbar background, hide y scrollbar and change sidebar footer to show version --------- Co-authored-by: MohamedBassem <me@mbassem.com>
Diffstat (limited to 'apps/web/components/dashboard/header')
-rw-r--r--apps/web/components/dashboard/header/Header.tsx71
-rw-r--r--apps/web/components/dashboard/header/ProfileOptions.tsx75
2 files changed, 146 insertions, 0 deletions
diff --git a/apps/web/components/dashboard/header/Header.tsx b/apps/web/components/dashboard/header/Header.tsx
new file mode 100644
index 00000000..11e3b3c3
--- /dev/null
+++ b/apps/web/components/dashboard/header/Header.tsx
@@ -0,0 +1,71 @@
+import React from "react";
+import Link from "next/link";
+import { redirect } from "next/navigation";
+import GlobalActions from "@/components/dashboard/GlobalActions";
+import ProfileOptions from "@/components/dashboard/header/ProfileOptions";
+import { SearchInput } from "@/components/dashboard/search/SearchInput";
+import HoarderLogo from "@/components/HoarderIcon";
+import { Button } from "@/components/ui/button";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "@/components/ui/tooltip";
+import { getServerAuthSession } from "@/server/auth";
+import { Settings, Shield } from "lucide-react";
+
+export default async function Header() {
+ const session = await getServerAuthSession();
+ if (!session) {
+ redirect("/");
+ }
+
+ const adminItem =
+ session.user.role == "admin"
+ ? [
+ {
+ name: "Admin",
+ icon: <Shield size={18} />,
+ path: "/dashboard/admin",
+ },
+ ]
+ : [];
+
+ const headerItems = [
+ ...adminItem,
+ {
+ name: "Settings",
+ icon: <Settings size={18} />,
+ path: "/dashboard/settings",
+ },
+ ];
+
+ return (
+ <header className="sticky left-0 right-0 top-0 z-50 flex h-16 items-center justify-between overflow-x-auto overflow-y-hidden bg-background p-4 shadow">
+ <div className="hidden items-center sm:flex">
+ <Link href={"/dashboard/bookmarks"} className="w-56">
+ <HoarderLogo height={20} gap="8px" />
+ </Link>
+ </div>
+ <div className="flex w-full gap-2">
+ <SearchInput className="min-w-40 bg-muted" />
+ <GlobalActions />
+ </div>
+ <div className="hidden items-center sm:flex">
+ {headerItems.map((item) => (
+ <Tooltip key={item.name} delayDuration={0}>
+ <TooltipTrigger asChild>
+ <Button variant="ghost">
+ <Link href={item.path} className="flex items-center">
+ {item.icon}
+ </Link>
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent side="bottom">{item.name}</TooltipContent>
+ </Tooltip>
+ ))}
+ <ProfileOptions />
+ </div>
+ </header>
+ );
+}
diff --git a/apps/web/components/dashboard/header/ProfileOptions.tsx b/apps/web/components/dashboard/header/ProfileOptions.tsx
new file mode 100644
index 00000000..df31171c
--- /dev/null
+++ b/apps/web/components/dashboard/header/ProfileOptions.tsx
@@ -0,0 +1,75 @@
+"use client";
+
+import Link from "next/link";
+import { redirect } from "next/navigation";
+import { useToggleTheme } from "@/components/theme-provider";
+import { Button } from "@/components/ui/button";
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { LogOut, Moon, Paintbrush, Sun } from "lucide-react";
+import { signOut, useSession } from "next-auth/react";
+import { useTheme } from "next-themes";
+
+function DarkModeToggle() {
+ const { theme } = useTheme();
+
+ if (theme == "dark") {
+ return (
+ <>
+ <Sun className="mr-2 size-4" />
+ <span>Light Mode</span>
+ </>
+ );
+ } else {
+ return (
+ <>
+ <Moon className="mr-2 size-4" />
+ <span>Dark Mode</span>
+ </>
+ );
+ }
+}
+
+export default function SidebarProfileOptions() {
+ const toggleTheme = useToggleTheme();
+ const { data: session } = useSession();
+ if (!session) return redirect("/");
+
+ return (
+ <DropdownMenu>
+ <DropdownMenuTrigger asChild>
+ <Button
+ className="border-new-gray-200 aspect-square rounded-full border-4 bg-black p-0 text-white"
+ variant="ghost"
+ >
+ {session.user.name?.charAt(0) ?? "U"}
+ </Button>
+ </DropdownMenuTrigger>
+ <DropdownMenuContent className="w-fit">
+ <DropdownMenuItem asChild>
+ <Link href="/dashboard/cleanups">
+ <Paintbrush className="mr-2 size-4" />
+ Cleanups
+ </Link>
+ </DropdownMenuItem>
+ <DropdownMenuItem onClick={toggleTheme}>
+ <DarkModeToggle />
+ </DropdownMenuItem>
+ <DropdownMenuItem
+ onClick={() =>
+ signOut({
+ callbackUrl: "/",
+ })
+ }
+ >
+ <LogOut className="mr-2 size-4" />
+ <span>Sign Out</span>
+ </DropdownMenuItem>
+ </DropdownMenuContent>
+ </DropdownMenu>
+ );
+}