feat(theme): add appearance settings and theme provider integration
- Added theme selection in settings page for light, dark, and system modes. - Integrated ThemeProvider into application layout. - Updated dashboard layout to include theme toggle in the header.
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { UserNavMobile } from "@/components/user-nav-mobile";
|
||||
import { ModeToggle } from "@/components/mode-toggle";
|
||||
|
||||
export default function DashboardLayout({
|
||||
children,
|
||||
@@ -27,7 +28,10 @@ export default function DashboardLayout({
|
||||
<div className="flex-1 flex justify-center">
|
||||
<span className="font-bold text-primary text-lg">MemeGoat</span>
|
||||
</div>
|
||||
<UserNavMobile />
|
||||
<div className="flex items-center gap-2">
|
||||
<ModeToggle />
|
||||
<UserNavMobile />
|
||||
</div>
|
||||
</header>
|
||||
<main className="flex-1 overflow-y-auto bg-zinc-50 dark:bg-zinc-950">
|
||||
{children}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Loader2, Save, User as UserIcon } from "lucide-react";
|
||||
import { Loader2, Moon, Laptop, Palette, Save, Sun, User as UserIcon } from "lucide-react";
|
||||
import { useTheme } from "next-themes";
|
||||
import * as React from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { toast } from "sonner";
|
||||
@@ -24,6 +25,8 @@ import {
|
||||
FormMessage,
|
||||
} from "@/components/ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useAuth } from "@/providers/auth-provider";
|
||||
@@ -37,8 +40,14 @@ const settingsSchema = z.object({
|
||||
type SettingsFormValues = z.infer<typeof settingsSchema>;
|
||||
|
||||
export default function SettingsPage() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { user, isLoading, refreshUser } = useAuth();
|
||||
const [isSaving, setIsSaving] = React.useState(false);
|
||||
const [mounted, setMounted] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const form = useForm<SettingsFormValues>({
|
||||
resolver: zodResolver(settingsSchema),
|
||||
@@ -185,6 +194,55 @@ export default function SettingsPage() {
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="mt-8">
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-2">
|
||||
<Palette className="h-5 w-5 text-primary" />
|
||||
<CardTitle>Apparence</CardTitle>
|
||||
</div>
|
||||
<CardDescription>
|
||||
Personnalisez l'apparence de l'application selon vos préférences.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<RadioGroup
|
||||
value={mounted ? theme : "system"}
|
||||
onValueChange={(value) => setTheme(value)}
|
||||
className="grid grid-cols-1 sm:grid-cols-3 gap-4"
|
||||
>
|
||||
<div>
|
||||
<RadioGroupItem value="light" id="light" className="peer sr-only" />
|
||||
<Label
|
||||
htmlFor="light"
|
||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary cursor-pointer"
|
||||
>
|
||||
<Sun className="mb-3 h-6 w-6" />
|
||||
<span>Clair</span>
|
||||
</Label>
|
||||
</div>
|
||||
<div>
|
||||
<RadioGroupItem value="dark" id="dark" className="peer sr-only" />
|
||||
<Label
|
||||
htmlFor="dark"
|
||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary cursor-pointer"
|
||||
>
|
||||
<Moon className="mb-3 h-6 w-6" />
|
||||
<span>Sombre</span>
|
||||
</Label>
|
||||
</div>
|
||||
<div>
|
||||
<RadioGroupItem value="system" id="system" className="peer sr-only" />
|
||||
<Label
|
||||
htmlFor="system"
|
||||
className="flex flex-col items-center justify-between rounded-md border-2 border-muted bg-popover p-4 hover:bg-accent hover:text-accent-foreground peer-data-[state=checked]:border-primary [&:has([data-state=checked])]:border-primary cursor-pointer"
|
||||
>
|
||||
<Laptop className="mb-3 h-6 w-6" />
|
||||
<span>Système</span>
|
||||
</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Metadata } from "next";
|
||||
import { Ubuntu_Mono, Ubuntu_Sans } from "next/font/google";
|
||||
import { Toaster } from "@/components/ui/sonner";
|
||||
import { AuthProvider } from "@/providers/auth-provider";
|
||||
import { ThemeProvider } from "@/providers/theme-provider";
|
||||
import "./globals.css";
|
||||
|
||||
const ubuntuSans = Ubuntu_Sans({
|
||||
@@ -60,10 +61,17 @@ export default function RootLayout({
|
||||
<body
|
||||
className={`${ubuntuSans.variable} ${ubuntuMono.variable} antialiased`}
|
||||
>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
<Toaster />
|
||||
</AuthProvider>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
<Toaster />
|
||||
</AuthProvider>
|
||||
</ThemeProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user