Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
199 changes: 112 additions & 87 deletions src/components/DashboardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import KeyboardShortcuts from "@/components/KeyboardShortcuts";
import { Moon, Sun } from "lucide-react";
import { toast } from "sonner";

import { useIsMobile } from "@/hooks/useIsMobile";


type DashboardSyncContextValue = {
lastSynced: Date | null;
};
Expand Down Expand Up @@ -99,6 +102,8 @@ export default function DashboardHeader() {
const [isNightOwl, setIsNightOwl] = useState<boolean>(false);
const [isEarlyBird, setIsEarlyBird] = useState<boolean>(false);

const isMobile = useIsMobile();

useEffect(() => {
const computeCurrentGreeting = () => {
const currentHour = new Date().getHours();
Expand Down Expand Up @@ -204,7 +209,7 @@ export default function DashboardHeader() {
<header className="relative mb-8 overflow-hidden rounded-3xl border border-[var(--border)] bg-[var(--card)]/95 p-4 shadow-[var(--shadow-soft)] backdrop-blur-md transition-all duration-300 hover:shadow-[var(--shadow-medium)] sm:p-5 md:p-6">
<div className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-[var(--accent)]/40 to-transparent" />
<div className="pointer-events-none absolute -right-10 -top-12 h-32 w-32 rounded-full bg-[var(--accent)]/10 blur-3xl" />
<div className="relative flex min-w-0 flex-col gap-5 md:flex-row md:items-end md:justify-between">
<div className="relative flex min-w-0 gap-5 items-end justify-between">

{/* Left Section */}
<div className="min-w-0 pr-12 md:pr-0">
Expand Down Expand Up @@ -261,110 +266,130 @@ export default function DashboardHeader() {

{/* Right Section */}
{/* Right Section */}
<div className="w-full min-w-0 md:w-auto">
<div className="flex w-full min-w-0 items-center gap-3 overflow-x-auto pb-1 md:w-auto md:justify-end md:overflow-visible md:pb-0">
{isPublic === true && session?.githubLogin && (
<a
href={`/u/${session.githubLogin}`}
target="_blank"
rel="noopener noreferrer"
className="primary-button inline-flex items-center justify-center rounded-xl px-4 py-2 text-sm font-semibold"
title="View your public profile"
>
Share Profile
</a>
)}

<div className="flex shrink-0 items-center gap-2 rounded-2xl border border-[var(--border)] bg-[var(--card-muted)]/50 p-2 shadow-sm backdrop-blur-sm">
<div className="transition-transform duration-200 hover:scale-[1.05]">
<KeyboardShortcuts />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<NotificationBell />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<UserAvatar />
</div>

<div className="transition-transform duration-200 hover:rotate-12">
<ThemeToggle />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<SignOutButton />
</div>
</div>
</div>

{!isMobile &&
<div className="w-full min-w-0 md:w-auto">
<div className="flex w-full min-w-0 items-center gap-3 overflow-x-auto pb-1 md:w-auto md:justify-end md:overflow-visible md:pb-0">
{isPublic === true && session?.githubLogin && (
<a
href={`/u/${session.githubLogin}`}
target="_blank"
rel="noopener noreferrer"
className="primary-button inline-flex items-center justify-center rounded-xl px-4 py-2 text-sm font-semibold"
title="View your public profile"
>
Share Profile
</a>
)}


<div className="flex shrink-0 items-center gap-2 rounded-2xl border border-[var(--border)] bg-[var(--card-muted)]/50 p-2 shadow-sm backdrop-blur-sm">
<div className="transition-transform duration-200 hover:scale-[1.05]">
<KeyboardShortcuts />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<NotificationBell />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<UserAvatar />
</div>

<div className="transition-transform duration-200 hover:rotate-12">
<ThemeToggle />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<SignOutButton />
</div>
</div>
</div>
</div>

}
{/* Mobile hamburger button */}

{isMobile &&
<div className="flex flex-col md:flex-row justify-start items-start self-stretch">

<div className="transition-transform duration-200 hover:scale-[1.05]">
<SignOutButton />
</div>
<div className="flex flex-row">
<div className="transition-transform duration-200 hover:scale-[1.05]">
<NotificationBell />
</div>

{/* Mobile hamburger button */}
<button
type="button"
className="inline-flex items-center justify-center self-start rounded-xl border border-[var(--border)] bg-[var(--card-muted)]/70 p-2 text-[var(--card-foreground)] shadow-sm transition-all duration-200 hover:border-[var(--accent)] hover:text-[var(--accent)] sm:hidden"
onClick={() => setMenuOpen((v) => !v)}
aria-label="Toggle menu"
aria-expanded={menuOpen}
>
{menuOpen ? (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="h-5 w-5"
aria-hidden="true"
>
<path d="M18 6 6 18" />
<path d="m6 6 12 12" />
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="h-5 w-5"
aria-hidden="true"
>
<path d="M4 6h16" />
<path d="M4 12h16" />
<path d="M4 18h16" />
</svg>
)}
</button>
type="button"
className="inline-flex items-center justify-center self-start rounded-xl border border-[var(--border)] bg-[var(--card-muted)]/70 p-2 text-[var(--card-foreground)] shadow-sm transition-all duration-200 hover:border-[var(--accent)] hover:text-[var(--accent)] "
onClick={() => setMenuOpen((v) => !v)}
aria-label="Toggle menu"
aria-expanded={menuOpen}
>
{menuOpen ? (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="h-5 w-5"
aria-hidden="true"
>
<path d="M18 6 6 18" />
<path d="m6 6 12 12" />
</svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="h-5 w-5"
aria-hidden="true"
>
<path d="M4 6h16" />
<path d="M4 12h16" />
<path d="M4 18h16" />
</svg>
)}
</button>

</div>


</div>

}

</div>

{/* Mobile dropdown */}
{menuOpen && (
<div className="mt-4 space-y-3 rounded-2xl border border-[var(--border)] bg-[var(--card-muted)]/70 p-4 shadow-sm backdrop-blur-sm sm:hidden">
<div className="flex flex-wrap items-center gap-2">
<div className="transition-transform duration-200 hover:scale-[1.05]">
<div className="mt-4 space-y-3 rounded-2xl border border-[var(--border)] bg-[var(--card-muted)]/70 p-4 shadow-sm backdrop-blur-sm ">
<div className="flex flex-col flex-wrap md:flex-row md:justify-evenly md:items-center">
<div className="transition-transform duration-200 hover:scale-[1.05] ">
<KeyboardShortcuts />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<NotificationBell />
</div>


<div className="transition-transform duration-200 hover:scale-[1.05]">
<UserAvatar />
</div>

<div className="transition-transform duration-200 hover:rotate-12">
<div className="transition-transform duration-200 hover:rotate-12 ">
<ThemeToggle />
</div>

<div className="transition-transform duration-200 hover:scale-[1.05]">
<SignOutButton />
</div>

</div>

{isPublic === true && session?.githubLogin && (
Expand Down
2 changes: 1 addition & 1 deletion src/components/SignOutButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export default function SignOutButton() {
</svg>
)}

Sign out
Signout
</button>
)
}
2 changes: 1 addition & 1 deletion src/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default function ThemeToggle() {
const currentDescription = themeDefinition?.description ?? "Customize the dashboard palette";

return (
<label className="inline-flex min-h-12 w-full max-w-[260px] cursor-pointer items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--card)] px-4 py-3 text-[var(--card-foreground)] shadow-sm transition-all duration-300 hover:bg-[var(--control)] focus-within:border-[var(--accent)]">
<label className="inline-flex min-h-12 w-full max-w-[220px] md:max-w-[260px] cursor-pointer items-center gap-3 rounded-2xl border border-[var(--border)] bg-[var(--card)] px-4 py-3 text-[var(--card-foreground)] shadow-sm transition-all duration-300 hover:bg-[var(--control)] focus-within:border-[var(--accent)]">
<span className="flex h-9 w-9 items-center justify-center rounded-xl bg-[var(--accent-soft)] text-[var(--accent)]">
<PaletteIcon className="h-4 w-4" aria-hidden="true" />
</span>
Expand Down
21 changes: 21 additions & 0 deletions src/hooks/useIsMobile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useEffect,useState } from "react";

export function useIsMobile(){

const [isMobile, setIsMobile] = useState(false);

useEffect(()=>{
const handleResize = ()=>{
setIsMobile(window.innerWidth <769);
};

handleResize();

window.addEventListener("resize",handleResize);

return ()=>
window.removeEventListener("resize", handleResize);
},[]);

return isMobile;
}
Loading