From 10da7d0a16ea8ec750f448322c16d827a5adc73c Mon Sep 17 00:00:00 2001 From: ArraysID Date: Sun, 27 Apr 2025 05:56:52 +0700 Subject: [PATCH] feat: migrate simple theme switcher component --- apps/landing/src/app/_components/header.tsx | 2 + .../app/_components/simple-theme-toggle.tsx | 42 +++++++++++++++++++ .../src/app/_components/theme-provider.tsx | 8 ++++ apps/landing/src/app/layout.tsx | 12 +++++- libs/shadcn-ui/src/atoms/icons.tsx | 4 ++ package-lock.json | 11 +++++ package.json | 1 + 7 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 apps/landing/src/app/_components/simple-theme-toggle.tsx create mode 100644 apps/landing/src/app/_components/theme-provider.tsx diff --git a/apps/landing/src/app/_components/header.tsx b/apps/landing/src/app/_components/header.tsx index a47520c..ffd53b4 100644 --- a/apps/landing/src/app/_components/header.tsx +++ b/apps/landing/src/app/_components/header.tsx @@ -9,6 +9,7 @@ import { cn } from '@imphnen-frontend-service/utils'; import Image from 'next/image'; import Link from 'next/link'; import { useEffect, useState } from 'react'; +import { SimpleThemeToggle } from './simple-theme-toggle'; export function Header() { const [isScrolled, setIsScrolled] = useState(false); @@ -80,6 +81,7 @@ export function Header() {
+ diff --git a/apps/landing/src/app/_components/simple-theme-toggle.tsx b/apps/landing/src/app/_components/simple-theme-toggle.tsx new file mode 100644 index 0000000..5a0cf64 --- /dev/null +++ b/apps/landing/src/app/_components/simple-theme-toggle.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { + Button, + MoonIcon, + SunIcon, +} from '@imphnen-frontend-service/shadcn-ui/atoms'; +import { useTheme } from 'next-themes'; +import { useEffect, useState } from 'react'; + +export function SimpleThemeToggle() { + const { theme, setTheme } = useTheme(); + const [mounted, setMounted] = useState(false); + + useEffect(() => { + setMounted(true); + }, []); + + if (!mounted) { + return null; + } + + const toggleTheme = () => { + setTheme(theme === 'dark' ? 'light' : 'dark'); + }; + + return ( + + ); +} diff --git a/apps/landing/src/app/_components/theme-provider.tsx b/apps/landing/src/app/_components/theme-provider.tsx new file mode 100644 index 0000000..4db6c3c --- /dev/null +++ b/apps/landing/src/app/_components/theme-provider.tsx @@ -0,0 +1,8 @@ +'use client'; + +import type { ThemeProviderProps } from 'next-themes'; +import { ThemeProvider as NextThemesProvider } from 'next-themes'; + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children}; +} diff --git a/apps/landing/src/app/layout.tsx b/apps/landing/src/app/layout.tsx index 7fadcce..8bc43a7 100644 --- a/apps/landing/src/app/layout.tsx +++ b/apps/landing/src/app/layout.tsx @@ -1,6 +1,7 @@ import { type Metadata } from 'next'; import { Inter } from 'next/font/google'; import '../styles/globals.css'; +import { ThemeProvider } from './_components/theme-provider'; const inter = Inter({ subsets: ['latin'] }); @@ -16,7 +17,16 @@ export default function RootLayout({ }) { return ( - {children} + + + {children} + + ); } diff --git a/libs/shadcn-ui/src/atoms/icons.tsx b/libs/shadcn-ui/src/atoms/icons.tsx index 4b45951..9843457 100644 --- a/libs/shadcn-ui/src/atoms/icons.tsx +++ b/libs/shadcn-ui/src/atoms/icons.tsx @@ -7,9 +7,11 @@ import { LuLaptop as LaptopIcon, LuMenu as MenuIcon, LuMessageCircle as MessageCircleIcon, + LuMoon as MoonIcon, LuQuote as QuoteIcon, LuShare2 as Share2Icon, LuSparkles as SparklesIcon, + LuSun as SunIcon, LuUsers as UsersIcon, LuVideo as VideoIcon, LuX as XIcon, @@ -24,9 +26,11 @@ export { LaptopIcon, MenuIcon, MessageCircleIcon, + MoonIcon, QuoteIcon, Share2Icon, SparklesIcon, + SunIcon, UsersIcon, VideoIcon, XIcon, diff --git a/package-lock.json b/package-lock.json index f4e5e33..286a13f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "framer-motion": "^12.9.2", "js-cookie": "^3.0.5", "next": "~15.2.4", + "next-themes": "^0.4.6", "react": "^19.1.0", "react-dom": "^19.1.0", "react-hook-form": "^7.55.0", @@ -24544,6 +24545,16 @@ } } }, + "node_modules/next-themes": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", + "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" + } + }, "node_modules/next/node_modules/@swc/helpers": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", diff --git a/package.json b/package.json index 49a3103..5cd0d94 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "framer-motion": "^12.9.2", "js-cookie": "^3.0.5", "next": "~15.2.4", + "next-themes": "^0.4.6", "react": "^19.1.0", "react-dom": "^19.1.0", "react-hook-form": "^7.55.0",