feat: add theme toggle to mobile profile menu

This commit is contained in:
2026-10-03 09:53:20 +03:30
parent 2912373081
commit 8bf79e3646
2 changed files with 50 additions and 13 deletions

View File

@@ -1,21 +1,57 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { DropdownMenuCheckboxItem } from "@/components/ui/dropdown-menu";
import { useTheme } from "@/components/ThemeProvider"; import { useTheme } from "@/components/ThemeProvider";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Moon, Sun } from "lucide-react"; import { Moon, Sun } from "lucide-react";
export default function ModeToggle({ className }: { className?: string }) { type ModeToggleProps = {
const { theme, setTheme } = useTheme(); className?: string;
variant?: "icon" | "menu";
};
export default function ModeToggle({ className, variant = "icon" }: ModeToggleProps) {
const { theme, resolvedTheme, setTheme } = useTheme();
const isDark = resolvedTheme === "dark" || theme === "dark";
const handleToggle = () => { const handleToggle = () => {
if (theme === "system" && typeof window !== "undefined") { setTheme(isDark ? "light" : "dark");
const prefersDark = window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
setTheme(prefersDark ? "light" : "dark");
return;
}
setTheme(theme === "dark" ? "light" : "dark");
}; };
if (variant === "menu") {
return (
<DropdownMenuCheckboxItem
checked={isDark}
onCheckedChange={(checked) => setTheme(checked ? "dark" : "light")}
onSelect={(event) => event.preventDefault()}
className={cn(
"my-1 justify-between gap-3 rounded-xl px-3 py-3 text-foreground focus:bg-secondary focus:text-foreground [&>span:first-child]:hidden",
className,
)}
aria-label="حالت نمایش"
>
<span className="flex items-center gap-2">
{isDark ? <Moon className="h-4 w-4" /> : <Sun className="h-4 w-4" />}
<span>حالت نمایش</span>
</span>
<span
dir="ltr"
aria-hidden="true"
className={cn(
"relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors",
isDark ? "bg-primary" : "bg-input",
)}
>
<span
className={cn(
"block h-5 w-5 rounded-full bg-background shadow transition-transform",
isDark ? "translate-x-5" : "translate-x-0",
)}
/>
</span>
</DropdownMenuCheckboxItem>
);
}
return ( return (
<Button <Button
variant="ghost" variant="ghost"

View File

@@ -88,22 +88,23 @@ function ProfileAvatarMenu() {
{[user?.first_name, user?.last_name].filter(Boolean).join(" ") || user?.username || "حساب کاربری"} {[user?.first_name, user?.last_name].filter(Boolean).join(" ") || user?.username || "حساب کاربری"}
</DropdownMenuLabel> </DropdownMenuLabel>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem asChild className="flex-row-reverse justify-end gap-2 rounded-xl transition-colors hover:bg-secondary hover:text-foreground focus:bg-secondary focus:text-foreground"> <DropdownMenuItem asChild className="my-1 flex-row-reverse justify-end gap-2 rounded-xl py-3 transition-colors hover:bg-secondary hover:text-foreground focus:bg-secondary focus:text-foreground">
<Link to="/profile"> <Link to="/profile">
مشاهده پروفایل مشاهده پروفایل
<UserRound className="h-4 w-4" /> <UserRound className="h-4 w-4" />
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>
{isAdminUser ? ( {isAdminUser ? (
<DropdownMenuItem asChild className="flex-row-reverse justify-end gap-2 rounded-xl transition-colors hover:bg-secondary hover:text-foreground focus:bg-secondary focus:text-foreground"> <DropdownMenuItem asChild className="my-1 flex-row-reverse justify-end gap-2 rounded-xl py-3 transition-colors hover:bg-secondary hover:text-foreground focus:bg-secondary focus:text-foreground">
<Link to="/admin"> <Link to="/admin">
داشبورد مدیریت داشبورد مدیریت
<LayoutDashboard className="h-4 w-4" /> <LayoutDashboard className="h-4 w-4" />
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>
) : null} ) : null}
<ModeToggle variant="menu" className="md:hidden" />
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem asChild className="flex-row-reverse justify-end gap-2 rounded-xl text-destructive transition-colors hover:bg-secondary hover:text-destructive focus:bg-secondary focus:text-destructive dark:text-red-300 dark:hover:text-red-200 dark:focus:text-red-200"> <DropdownMenuItem asChild className="my-1 flex-row-reverse justify-end gap-2 rounded-xl py-3 text-destructive transition-colors hover:bg-secondary hover:text-destructive focus:bg-secondary focus:text-destructive dark:text-red-300 dark:hover:text-red-200 dark:focus:text-red-200">
<Link to="/logout"> <Link to="/logout">
خروج از حساب خروج از حساب
<LogOut className="h-4 w-4" /> <LogOut className="h-4 w-4" />
@@ -157,7 +158,7 @@ export default function Navbar({ siteContent }: { siteContent: SiteContent }) {
<div className="flex items-center gap-2 md:hidden"> <div className="flex items-center gap-2 md:hidden">
{isAuthenticated ? <NotificationsBell /> : null} {isAuthenticated ? <NotificationsBell /> : null}
<ModeToggle /> {!isAuthenticated ? <ModeToggle /> : null}
<ProfileAvatarMenu /> <ProfileAvatarMenu />
</div> </div>
</div> </div>