diff --git a/README.md b/README.md index 59387caf2d..420594ba78 100644 --- a/README.md +++ b/README.md @@ -395,6 +395,37 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d + +--- + +## 🌗 Dark/Light Theme Toggle + +We’ve added a dark/light theme toggle to enhance user experience. + +### 🔧 How It Works + +- A toggle button (☀️/🌙) is available in the **NavBar**. +- Clicking it switches between **light** and **dark** mode. +- Theme preference is saved in `localStorage` so it persists across sessions. +- Tailwind CSS uses `darkMode: 'class'` (configured in `tailwind.config.js`). +- A custom `useDarkMode` hook manages toggling logic and class updates. + +### 📂 Files Modified + +- `src/common/NavBar.jsx` → Added toggle button +- `src/hooks/useDarkMode.js` → Custom hook for managing theme +- `src/index.jsx` → Ensures correct theme on initial load +- `tailwind.config.js` → Enabled `darkMode: 'class'` + +### 📸 Preview + +| Light Mode ☀️ | Dark Mode 🌙 | +|---------------|--------------| +| ![Light](https://dummyimage.com/300x150/ffffff/000000&text=Light+Mode) | ![Dark](https://dummyimage.com/300x150/000000/ffffff&text=Dark+Mode) | + +--- + + diff --git a/src/index.jsx b/src/index.jsx index e7f29a3858..3a9dfc2aa3 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -1,6 +1,6 @@ import RouteDefs from 'common/routing/RouteDefs'; import { SearchContextProvider } from 'common/search/search-context'; -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import reportWebVitals from './reportWebVitals'; import register from './registerServiceWorker'; @@ -27,33 +27,47 @@ const Index = () => { language: [] }); + const [theme, setTheme] = useState(localStorage.getItem('theme') || 'light'); + + // Effect to apply theme + useEffect(() => { + const root = document.documentElement; + if (theme === 'dark') { + root.classList.add('dark'); + } else { + root.classList.remove('dark'); + } + localStorage.setItem('theme', theme); + }, [theme]); + + const toggleTheme = () => { + setTheme(prev => (prev === 'dark' ? 'light' : 'dark')); + }; + const value = { searchTerm, setSearchTerm, filterQuery, setFilterQuery, showShareModal, - setShowShareModal + setShowShareModal, + toggleTheme, // add toggle function to context if needed in NavBar + theme }; return ( - // - // ); }; + const container = document.getElementById('root'); createRoot(container).render(); // Makes the app to work offline and load faster register(); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); diff --git a/src/plays/navbar/navListItems.jsx b/src/plays/navbar/navListItems.jsx index 6277bbbb9c..ff6b3b17d3 100644 --- a/src/plays/navbar/navListItems.jsx +++ b/src/plays/navbar/navListItems.jsx @@ -1,4 +1,5 @@ -import React, { useState } from 'react'; +import React, { useState, useContext } from 'react'; +import { SearchContext } from 'common/search/search-context'; import Collasp from '../navbar/assest/img.png'; import LogoImage from '../navbar/assest/logo.png'; import ChartImg from './assest/Chart.png'; @@ -8,171 +9,171 @@ import SettingImg from './assest/Setting.png'; import SearchImg from './assest/Search.png'; import Backgrounds from './Backgrounds'; import { FaTwitterSquare } from 'react-icons/fa'; +import { BsSun, BsMoon } from 'react-icons/bs'; const NavListItems = () => { const [open, setOpen] = useState(true); const [show, setShow] = useState('opacity-0'); - const [hide, setHide] = useState(true); // true == opacity-1 + const [hide, setHide] = useState(true); const [data, setData] = useState(Backgrounds); + // 👇 Get theme state from context + const { theme, toggleTheme } = useContext(SearchContext); + const filterResult = (catItem) => { const result = Backgrounds.filter((currentData) => { handleOpacity(); handleHide(); - return currentData.type === catItem; }); setData(result); }; - const handleOnClick = () => setOpen((prevState) => !prevState); - const handleOpacity = () => { - setShow('opacity-1'); - }; - const handleHide = () => { - setHide(false); - }; + const handleOnClick = () => setOpen((prevState) => !prevState); + const handleOpacity = () => setShow('opacity-1'); + const handleHide = () => setHide(false); const reverseClick = () => { setShow('opacity-0'); setHide('opacity-1'); }; return ( - <> - {/* Code Starts Here */} -
-
+
+
+ {/* Collapse Icon */} + collapse + + {/* Logo + Title */} +
collasp -
- play-logo -

- Develop -

+

+ Develop +

+
+ + {/* Nav Items */} +
    +
  • filterResult('dashboard')} + > + dashboard + Dashboard +
  • +
  • filterResult('ideas')} + > + ideas + Ideas +
  • +
  • filterResult('join')} + > + join + Join +
  • +
  • filterResult('build')} + > + build + Build +
  • +
  • filterResult('search')} + > + search + Search +
  • + + {/* 🌗 Dark/Light Toggle */} +
  • + {theme === 'dark' ? : } + + {theme === 'dark' ? 'Light Mode' : 'Dark Mode'} + +
  • +
+
+ + {/* Sidebar content */} +
+
+
+

+ It is a responsive NavBar that helps you to navigate + + . +

+ + +
+

+ Made with +
+
CSS3
+
React JS
+
Tailwind CSS
+
+

+
- {/* ListItems */} -
    - {/* Item1 */} -
  • filterResult('dashboard')} - > - dashboard - Dashboard -
  • - {/* Item2 */} -
  • filterResult('ideas')} - > - ideas - Ideas -
  • - {/* Item3 */} -
  • filterResult('join')} - > - join - Join -
  • - {/* Item4 */} -
  • filterResult('build')} - > - build - Build -
  • - {/* Item5 */} -
  • filterResult('search')} + {/* Dynamic Card Display */} + {data.map((values) => { + const { id, image, title, discription, statement, url } = values; + + return ( +
    - search - Search -
  • -
-
-
- {/* Fetching Values */} -
-
-

- It is a responsive NavBar that helps you to navigate - - . -

- - - -
-

- Made with -
-
CSS3
-
React JS
-
Tailwind CSS
+ nav-card-images +
+

{title}

+
{discription}
+ + +
-

-
- {data.map((values) => { - const { id, image, title, discription, statement, url } = values; - - return ( - <> -
- nav-card-images -
-

{title}

-
{discription}
- - {' '} - - -
-
- - ); - })} -
+
+ ); + })}
- +
); }; diff --git a/tailwind.config.js b/tailwind.config.js index 5d00e3a624..56e5093dc8 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,24 +1,14 @@ module.exports = { content: ['./src/**/*.{js,jsx,ts,tsx}'], + darkMode: 'class', // 👈 enable dark mode manually via a class theme: { screens: { xs: { min: '310px' }, - // => @media (min-width: 640px and max-width: 767px) { ... } - sm: { min: '640px' }, - // => @media (min-width: 640px and max-width: 767px) { ... } - md: { min: '768px' }, - // => @media (min-width: 768px and max-width: 1023px) { ... } - lg: { min: '1024px' }, - // => @media (min-width: 1024px and max-width: 1279px) { ... } - xl: { min: '1280px' }, - // => @media (min-width: 1280px and max-width: 1535px) { ... } - '2xl': { min: '1536px' } - // => @media (min-width: 1536px) { ... } }, extend: {} },