feat: add theme toggle to mobile profile menu
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user