diff --git a/package-lock.json b/package-lock.json index 00b4140..6cd6a49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "eslint": "8.49.0", "eslint-config-next": "13.4.19", "next": "13.4.19", + "next-themes": "^0.2.1", "postcss": "8.4.29", "react": "18.2.0", "react-dom": "18.2.0", @@ -27,6 +28,7 @@ "@commitlint/cz-commitlint": "^17.7.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", + "@tailwindcss/forms": "^0.5.6", "commitizen": "^4.3.0", "cz-conventional-changelog": "^3.3.0", "eslint-config-prettier": "^9.0.0", @@ -2045,6 +2047,18 @@ "tslib": "^2.4.0" } }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.6.tgz", + "integrity": "sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -6701,6 +6715,15 @@ "node": ">=4" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -6844,6 +6867,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz", + "integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==", + "peerDependencies": { + "next": "*", + "react": "*", + "react-dom": "*" + } + }, "node_modules/next/node_modules/postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", diff --git a/package.json b/package.json index 17d2641..ff97fd2 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "eslint": "8.49.0", "eslint-config-next": "13.4.19", "next": "13.4.19", + "next-themes": "^0.2.1", "postcss": "8.4.29", "react": "18.2.0", "react-dom": "18.2.0", @@ -31,6 +32,7 @@ "@commitlint/cz-commitlint": "^17.7.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", + "@tailwindcss/forms": "^0.5.6", "commitizen": "^4.3.0", "cz-conventional-changelog": "^3.3.0", "eslint-config-prettier": "^9.0.0", diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ae84562..9089ecf 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import './globals.css' import type { Metadata } from 'next' import { Inter } from 'next/font/google' +import { Providers } from './providers' const inter = Inter({ subsets: ['latin'] }) @@ -16,7 +17,9 @@ export default function RootLayout({ }) { return ( - {children} + + {children} + ) } diff --git a/src/app/page.tsx b/src/app/page.tsx index e174b94..a9906a5 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,16 @@ +import DarkModeToggle from '@/components/DarkModeToggle' + export default function Home() { return ( -
-
+
+
-

+

Welcome to My Next.js Boilerplate!

+
+ +
diff --git a/src/app/providers.tsx b/src/app/providers.tsx new file mode 100644 index 0000000..8bea430 --- /dev/null +++ b/src/app/providers.tsx @@ -0,0 +1,7 @@ +'use client' + +import { ThemeProvider } from 'next-themes' + +export function Providers({ children }: { children: React.ReactNode }) { + return {children} +} diff --git a/src/components/DarkModeToggle.tsx b/src/components/DarkModeToggle.tsx new file mode 100644 index 0000000..81fe5f7 --- /dev/null +++ b/src/components/DarkModeToggle.tsx @@ -0,0 +1,54 @@ +'use client' + +import { useTheme } from 'next-themes' +import { useEffect, useState } from 'react' + +export default function DarkModeToggle() { + const { theme, setTheme } = useTheme() + const [mounted, setMounted] = useState(false) + + useEffect(() => { + const prefersDark = + window.matchMedia && + window.matchMedia('(prefers-color-scheme: dark)').matches + const localTheme = localStorage.getItem('theme') + + setTheme(localTheme || (prefersDark ? 'dark' : 'light')) + setMounted(true) + }, [setTheme]) + + useEffect(() => { + if (mounted) { + localStorage.setItem('theme', theme || 'light') + } + }, [theme, mounted]) + + const toggleTheme = () => { + setTheme(theme === 'dark' ? 'light' : 'dark') + } + + return ( +
+ + +
+ ) +} diff --git a/tailwind.config.ts b/tailwind.config.ts index a6f0126..82154c0 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,3 +1,5 @@ +import forms from '@tailwindcss/forms' + import type { Config } from 'tailwindcss' const config: Config = { @@ -6,7 +8,8 @@ const config: Config = { './src/components/**/*.{js,ts,jsx,tsx,mdx}', './src/app/**/*.{js,ts,jsx,tsx,mdx}', ], + darkMode: 'class', theme: {}, - plugins: [], + plugins: [forms], } export default config