diff --git a/package.json b/package.json index 17172e19..c4bda6a2 100644 --- a/package.json +++ b/package.json @@ -20,12 +20,14 @@ "classnames": "^2.3.2", "clsx": "^2.0.0", "next": "13.5.6", + "next-themes": "^0.2.1", "react": "^18", "react-dom": "^18", "react-hook-form": "^7.47.0", "tailwind-merge": "^1.14.0", "tailwindcss": "^3.3.3", "tsconfig-paths-webpack-plugin": "^4.1.0", + "tw-colors": "^3.1.2", "zod": "^3.22.4" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 63f550c8..bad21ce2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: next: specifier: 13.5.6 version: 13.5.6(@babel/core@7.23.2)(react-dom@18.0.0)(react@18.0.0) + next-themes: + specifier: ^0.2.1 + version: 0.2.1(next@13.5.6)(react-dom@18.0.0)(react@18.0.0) react: specifier: ^18 version: 18.0.0 @@ -44,6 +47,9 @@ dependencies: tsconfig-paths-webpack-plugin: specifier: ^4.1.0 version: 4.1.0 + tw-colors: + specifier: ^3.1.2 + version: 3.1.2(tailwindcss@3.3.3) zod: specifier: ^3.22.4 version: 3.22.4 @@ -5608,6 +5614,21 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false + + /color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + dev: false + /colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} @@ -7067,6 +7088,11 @@ packages: rimraf: 3.0.2 dev: true + /flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + dev: false + /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true @@ -7734,6 +7760,10 @@ packages: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + /is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -8392,6 +8422,10 @@ packages: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} dev: true + /lodash.foreach@4.5.0: + resolution: {integrity: sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==} + dev: false + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true @@ -8776,6 +8810,18 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true + /next-themes@0.2.1(next@13.5.6)(react-dom@18.0.0)(react@18.0.0): + resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} + peerDependencies: + next: '*' + react: '*' + react-dom: '*' + dependencies: + next: 13.5.6(@babel/core@7.23.2)(react-dom@18.0.0)(react@18.0.0) + react: 18.0.0 + react-dom: 18.0.0(react@18.0.0) + dev: false + /next@13.5.6(@babel/core@7.23.2)(react-dom@18.0.0)(react@18.0.0): resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} engines: {node: '>=16.14.0'} @@ -10392,6 +10438,12 @@ packages: engines: {node: '>=14'} dev: true + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + /simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -11046,6 +11098,17 @@ packages: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} dev: true + /tw-colors@3.1.2(tailwindcss@3.3.3): + resolution: {integrity: sha512-1C4Bo2JQUqdCA/yowaBJZbyk0U9a5Y7mc5c3XMF0Ks85vByJwB4jewtL8TkRe2Mn9H1a+/1lVfAMlqz1fvJPdg==} + peerDependencies: + tailwindcss: '>=3.0.0' + dependencies: + color: 4.2.3 + flat: 5.0.2 + lodash.foreach: 4.5.0 + tailwindcss: 3.3.3 + dev: false + /tween-functions@1.2.0: resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} dev: true diff --git a/src/app/(root)/(routes)/(home)/page.tsx b/src/app/(root)/(routes)/(home)/page.tsx index 9e326a2a..56444105 100644 --- a/src/app/(root)/(routes)/(home)/page.tsx +++ b/src/app/(root)/(routes)/(home)/page.tsx @@ -1,9 +1,11 @@ import Link from 'next/link' +import { DarkModeButton } from '@/components/ui/DarkModeButton' export default function HomePage() { return ( -
+
hi + 로긴
) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 99ebca01..d64b5807 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,8 @@ +import { Suspense } from 'react' import type { Metadata } from 'next' import { Environment } from '@/config/environment' import TanstackQueryContext from '@/contexts/TanstackQueryContext' +import ThemeProviderContext from '@/contexts/ThemeProviderContext' import { initMockApi } from '@/lib/msw/initMockApi' import '@/styles/globals.css' @@ -22,13 +24,17 @@ export default function RootLayout({ authModal: React.ReactNode }) { return ( - - - - {children} - {authModal} - - + + + + + + {children} + {authModal} + + + + ) } diff --git a/src/components/ui/DarkModeButton/DarkModeButton.tsx b/src/components/ui/DarkModeButton/DarkModeButton.tsx new file mode 100644 index 00000000..9dbb81db --- /dev/null +++ b/src/components/ui/DarkModeButton/DarkModeButton.tsx @@ -0,0 +1,44 @@ +'use client' + +import React from 'react' +import { useTheme } from 'next-themes' + +const DarkModeButton = () => { + const { theme, setTheme } = useTheme() + + return ( +
+ +
+ ) +} + +export default DarkModeButton diff --git a/src/components/ui/DarkModeButton/index.tsx b/src/components/ui/DarkModeButton/index.tsx new file mode 100644 index 00000000..362b1b9d --- /dev/null +++ b/src/components/ui/DarkModeButton/index.tsx @@ -0,0 +1,3 @@ +import { default as DarkModeButton } from './DarkModeButton' + +export { DarkModeButton } diff --git a/src/contexts/TanstackQueryContext.tsx b/src/contexts/TanstackQueryContext.tsx index 4ba239ce..5ddab72b 100644 --- a/src/contexts/TanstackQueryContext.tsx +++ b/src/contexts/TanstackQueryContext.tsx @@ -3,16 +3,16 @@ import { useState } from 'react' import { QueryClientProvider, QueryClient } from '@tanstack/react-query' -interface TanstackQueryContextProps { +type TanstackQueryContextProps = { children: React.ReactNode } -export default function TanstackQueryContext({ - children, -}: TanstackQueryContextProps) { +function TanstackQueryContext({ children }: TanstackQueryContextProps) { const [queryClient] = useState(() => new QueryClient()) return ( {children} ) } + +export default TanstackQueryContext diff --git a/src/contexts/ThemeProviderContext.tsx b/src/contexts/ThemeProviderContext.tsx new file mode 100644 index 00000000..3e7b9b54 --- /dev/null +++ b/src/contexts/ThemeProviderContext.tsx @@ -0,0 +1,22 @@ +'use client' + +import { useEffect, useState } from 'react' +import { ThemeProvider } from 'next-themes' + +type ThemeProviderContextProps = { + children: React.ReactNode +} + +const ThemeProviderContext = ({ children }: ThemeProviderContextProps) => { + const [mounted, setMounted] = useState(false) + + useEffect(() => { + setMounted(true) + }, []) + + return ( + {mounted && children} + ) +} + +export default ThemeProviderContext diff --git a/tailwind.config.js b/tailwind.config.js index ecd3c0ab..770ce5e1 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,3 +1,5 @@ +const { createThemes } = require('tw-colors') + /** @type {import('tailwindcss').Config} */ module.exports = { content: [ @@ -8,8 +10,24 @@ module.exports = { // Or if using `src` directory: './src/**/*.{js,ts,jsx,tsx,mdx}', ], + darkMode: ['class'], theme: { extend: {}, }, - plugins: [], + plugins: [ + createThemes({ + light: { + 'background-color': '#e5e5e5', + 'primary-color': '#404040', + 'card-background-color': '#d4d4d4', + 'secondary-color': '#d4d4d4', + }, + dark: { + 'background-color': '#404040', + 'primary-color': '#e5e5e5', + 'card-background-color': '#525252', + 'secondary-color': '#525252', + }, + }), + ], }