feat(theme): add theme switching functionality with ModeSwitcher and ThemeProvider

This commit is contained in:
ngc2207 2024-12-09 16:48:38 +08:00
parent 398c56b38b
commit 8808b4fb9b
5 changed files with 49 additions and 1 deletions

View File

@ -23,6 +23,7 @@
"lucide-react": "^0.468.0",
"next": "15.0.4",
"next-auth": "^5.0.0-beta.25",
"next-themes": "^0.4.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwind-merge": "^2.5.5",

View File

@ -14,6 +14,7 @@ import {
import { SessionProvider } from "next-auth/react";
import { AppSidebar } from "@/components/app-sidebar";
import { Separator } from "@/components/ui/separator";
import { ModeSwitcher } from "@/components/mode-switcher";
import ConfirmationDialog from "@/dialogs/ConfirmationDialog";
export default function DashboardLayout({
@ -27,6 +28,7 @@ export default function DashboardLayout({
<header className="flex h-16 shrink-0 items-center gap-2">
<div className="flex items-center gap-2 px-4">
<SidebarTrigger className="-ml-1" />
<ModeSwitcher />
<Separator orientation="vertical" className="mr-2 h-4" />
<Breadcrumb>
<BreadcrumbList>

View File

@ -2,6 +2,7 @@ import "@/app/globals.css";
import { cn } from "@/lib/utils";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { ThemeProvider } from "@/components/theme-provider";
const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
@ -20,8 +21,15 @@ export default function RootLayout({
<html lang="en" className="h-full" suppressHydrationWarning>
<body
className={cn("font-sans antialiased flex min-h-full", inter.variable)}
>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<div className="w-full">{children}</div>
</ThemeProvider>
</body>
</html>
);

View File

@ -0,0 +1,26 @@
"use client";
import * as React from "react";
import { useTheme } from "next-themes";
import { Sun, Moon } from "lucide-react";
import { Button } from "@/components/ui/button";
export function ModeSwitcher() {
const { setTheme, resolvedTheme } = useTheme();
const toggleTheme = React.useCallback(() => {
setTheme(resolvedTheme === "dark" ? "light" : "dark");
}, [resolvedTheme, setTheme]);
return (
<Button
variant="ghost"
className="group/toggle h-8 w-8 px-0"
onClick={toggleTheme}
>
<Sun className="hidden [html.dark_&]:block" />
<Moon className="hidden [html.light_&]:block" />
<span className="sr-only">Toggle theme</span>
</Button>
);
}

View File

@ -0,0 +1,11 @@
"use client";
import * as React from "react";
import { ThemeProvider as NextThemesProvider } from "next-themes";
export function ThemeProvider({
children,
...props
}: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}