From 61162e28a3690c4a740c2fedd6c285c33ed55ed6 Mon Sep 17 00:00:00 2001 From: Shobhini <130296359+Shobhini@users.noreply.github.com> Date: Tue, 20 May 2025 00:53:57 +0530 Subject: [PATCH 1/3] feat: Dark mode toggle button --- index.html | 8 ++ src/App.jsx | 94 +++++++++------------- src/components/About.jsx | 58 ++++++++++++++ src/components/Card.jsx | 6 +- src/components/Contact.jsx | 110 ++++++++++++++++++++++++++ src/components/Home.jsx | 19 +++-- src/components/Resources.jsx | 98 +++++++++++++++++++++++ src/components/Sidebar.jsx | 56 +++++++++++++ src/components/ThemeToggle.jsx | 22 ++++++ src/components/nav/SideNav.jsx | 27 +++---- src/context/ThemeContext.jsx | 38 +++++++++ src/database/websites/html.json | 2 +- src/database/websites/javascript.json | 2 +- src/index.css | 53 ++++++++++--- tailwind.config.js | 56 ++++++------- 15 files changed, 523 insertions(+), 126 deletions(-) create mode 100644 src/components/About.jsx create mode 100644 src/components/Contact.jsx create mode 100644 src/components/Resources.jsx create mode 100644 src/components/Sidebar.jsx create mode 100644 src/components/ThemeToggle.jsx create mode 100644 src/context/ThemeContext.jsx diff --git a/index.html b/index.html index 0f06582..92bb92f 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,14 @@ + diff --git a/src/App.jsx b/src/App.jsx index 977243c..52a316a 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,64 +1,44 @@ -import React,{lazy, Suspense} from "react"; -import { Route, Routes, NavLink } from "react-router-dom"; -// import Nav from './components/nav/Nav.jsx'; -import SideNav from "./components/nav/SideNav.jsx"; -import ScrollToTopButton from "./components/ScrollToTopButton.jsx"; +import { lazy, Suspense } from 'react'; +import { Routes, Route } from 'react-router-dom'; +import { ThemeProvider } from './context/ThemeContext'; +import Sidebar from './components/Sidebar'; -const Home = lazy(() => import("./components/Home.jsx")); -const Books = lazy(() => import("./components/books/Index.jsx")); -const Tools = lazy(() => import("./components/tools/Index.jsx")); -const Videos = lazy(() => import("./components/videos/Index.jsx")); -const Editors = lazy(() => import("./components/editor/Index.jsx")); -const Websites = lazy(() => import("./components/websites/Index.jsx")); -const Challenges = lazy(() => import("./components/challenges/Index.jsx")); +// Lazy load components +const Home = lazy(() => import('./components/Home')); +const About = lazy(() => import('./components/About')); +const Videos = lazy(() => import('./components/videos/Index')); +const Websites = lazy(() => import('./components/websites/Index')); +const Challenges = lazy(() => import('./components/challenges/Index')); +const Books = lazy(() => import('./components/books/Index')); +const Tools = lazy(() => import('./components/tools/Index')); +const Editors = lazy(() => import('./components/editor/Index')); -const App = () => { +function App() { return ( -
- -
- - {/* Home */} - Loading

}> - - - } /> - Loading

}> - - - } /> - Loading

}> - - - } /> - Loading

}> - - - } /> - Loading

}> - - - } /> - Loading

}> - - - } /> - Loading

}> - - - } /> -
+ +
+ +
+ +
Loading...
+
+ }> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + +
- -
+ ); -}; +} export default App; \ No newline at end of file diff --git a/src/components/About.jsx b/src/components/About.jsx new file mode 100644 index 0000000..9f70619 --- /dev/null +++ b/src/components/About.jsx @@ -0,0 +1,58 @@ +import { motion } from 'framer-motion'; + +export default function About() { + return ( +
+ +

+ About Web Resources Hub +

+ +
+

+ Welcome to Web Resources Hub, your comprehensive platform for web development + learning and resources. Our mission is to empower developers of all levels + with the tools and knowledge they need to succeed in the ever-evolving + world of web development. +

+ +

+ Our Vision +

+

+ We believe that quality learning resources should be accessible to everyone. + Our platform curates the best web development resources, from beginner-friendly + tutorials to advanced technical documentation, helping you grow your skills + at your own pace. +

+ +

+ What We Offer +

+
    +
  • Comprehensive documentation for popular web technologies
  • +
  • Curated learning paths for different skill levels
  • +
  • Best practices and coding standards
  • +
  • Community-driven resource recommendations
  • +
  • Regular updates with the latest web development trends
  • +
+ +

+ Join Our Community +

+

+ Whether you're just starting your web development journey or you're an + experienced developer looking to stay updated, Web Resources Hub is here + to support your growth. Join our community of learners and contributors + to share knowledge and help others succeed. +

+
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/Card.jsx b/src/components/Card.jsx index d659a9f..83ed546 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -5,7 +5,7 @@ const Card = ({ title, link, description, i, img }) => { return ( {
-

+

{title}

-

+

{description.slice(0, 120) + "..."}

diff --git a/src/components/Contact.jsx b/src/components/Contact.jsx new file mode 100644 index 0000000..ba4c47b --- /dev/null +++ b/src/components/Contact.jsx @@ -0,0 +1,110 @@ +import { motion } from 'framer-motion'; +import { useState } from 'react'; + +export default function Contact() { + const [formData, setFormData] = useState({ + name: '', + email: '', + message: '', + }); + + const handleSubmit = (e) => { + e.preventDefault(); + // Handle form submission here + console.log('Form submitted:', formData); + }; + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prev) => ({ + ...prev, + [name]: value, + })); + }; + + return ( +
+ +

+ Contact Us +

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ +
+

+ Other Ways to Reach Us +

+

Email: contact@webresourceshub.com

+

Follow us on social media for updates and community discussions.

+
+
+
+ ); +} \ No newline at end of file diff --git a/src/components/Home.jsx b/src/components/Home.jsx index f2931e1..2de53fa 100644 --- a/src/components/Home.jsx +++ b/src/components/Home.jsx @@ -6,7 +6,7 @@ export default function Home() { const text = "Web Resources Hub"; const [currentText, setCurrentText] = useState(""); const fixedCharacter = "W"; - const [showCursor, setShowCursor] = useState(true); // State to control cursor visibility + const [showCursor, setShowCursor] = useState(true); const startTypewriter = () => { let index = currentText.length; @@ -29,35 +29,34 @@ export default function Home() { setCurrentText(fixedCharacter); startTypewriter(); - // Toggle cursor visibility with a blinking effect const cursorInterval = setInterval(() => { setShowCursor((prevShowCursor) => !prevShowCursor); }, 250); return () => { - clearInterval(cursorInterval); // Clear interval on unmount + clearInterval(cursorInterval); }; }, []); return ( -
+
-

+

{currentText} {showCursor && |}

-

- Get Empowered with
+

+ Get Empowered with
Web Development
- Resources + Resources

-

+

Explore our vast collection of web development resources, designed to give you the knowledge and tools you need to succeed in the world of web development!

diff --git a/src/components/Resources.jsx b/src/components/Resources.jsx new file mode 100644 index 0000000..6b943cc --- /dev/null +++ b/src/components/Resources.jsx @@ -0,0 +1,98 @@ +import { motion } from 'framer-motion'; +import { useState } from 'react'; + +export default function Resources() { + const [activeCategory, setActiveCategory] = useState('all'); + + const categories = [ + { id: 'all', name: 'All Resources' }, + { id: 'frontend', name: 'Frontend' }, + { id: 'backend', name: 'Backend' }, + { id: 'database', name: 'Database' }, + { id: 'devops', name: 'DevOps' }, + ]; + + const resources = [ + { + id: 1, + title: 'React Documentation', + description: 'Official React documentation with comprehensive guides and API references.', + category: 'frontend', + link: 'https://reactjs.org/docs/getting-started.html', + }, + { + id: 2, + title: 'Node.js Documentation', + description: 'Complete Node.js documentation and guides for backend development.', + category: 'backend', + link: 'https://nodejs.org/en/docs/', + }, + { + id: 3, + title: 'MongoDB University', + description: 'Free courses and tutorials for MongoDB database development.', + category: 'database', + link: 'https://university.mongodb.com/', + }, + { + id: 4, + title: 'Docker Documentation', + description: 'Learn containerization with Docker through official documentation.', + category: 'devops', + link: 'https://docs.docker.com/', + }, + ]; + + const filteredResources = activeCategory === 'all' + ? resources + : resources.filter(resource => resource.category === activeCategory); + + return ( +
+
+ {categories.map((category) => ( + + ))} +
+ + {/*
*/} +
+ + {filteredResources.map((resource) => ( + +

+ {resource.title} +

+

+ {resource.description} +

+
+ Learn More → + + + ))} +
+
+ ); +} \ No newline at end of file diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx new file mode 100644 index 0000000..5666ea0 --- /dev/null +++ b/src/components/Sidebar.jsx @@ -0,0 +1,56 @@ +import { NavLink } from 'react-router-dom'; +import { useTheme } from '../context/ThemeContext'; + +const Sidebar = () => { + const { isDarkMode, toggleTheme } = useTheme(); + + const navItems = [ + { path: '/', label: 'Home' }, + { path: '/about', label: 'About' }, + { path: '/videos', label: 'Videos' }, + { path: '/websites', label: 'Websites' }, + { path: '/challenges', label: 'Challenges' }, + { path: '/books', label: 'Books' }, + { path: '/tools', label: 'Tools' }, + { path: '/editors', label: 'Editors' }, + // { path: '/resources', label: 'Resources' }, + // { path: '/contact', label: 'Contact' }, + ]; + + return ( + + ); +}; + +export default Sidebar; \ No newline at end of file diff --git a/src/components/ThemeToggle.jsx b/src/components/ThemeToggle.jsx new file mode 100644 index 0000000..7c3faa7 --- /dev/null +++ b/src/components/ThemeToggle.jsx @@ -0,0 +1,22 @@ +import React, { useContext } from 'react'; +import { ThemeContext } from '../context/ThemeContext'; +import { FaSun, FaMoon } from 'react-icons/fa'; + +const ThemeToggle = () => { + const { isDarkMode, toggleTheme } = useContext(ThemeContext); + + return ( + + ); +}; + +export default ThemeToggle; \ No newline at end of file diff --git a/src/components/nav/SideNav.jsx b/src/components/nav/SideNav.jsx index 18cc3cb..ffe35a3 100644 --- a/src/components/nav/SideNav.jsx +++ b/src/components/nav/SideNav.jsx @@ -5,48 +5,45 @@ import SideNavMobile from "./SideNavMobile"; function SideNav() { const [showSideNav, setShowSideNav] = useState(false); - const [searchResult,setSearchResult] = useState(""); + const [searchResult, setSearchResult] = useState(""); let debounceTimer; - const clickHandler = () => { setShowSideNav(!showSideNav); }; const handleInputChange = (event) => { setSearchResult(event.target.value); - // Perform any other actions here, if needed }; - // Debounce function const debounce = (func, delay) => { clearTimeout(debounceTimer); debounceTimer = setTimeout(func, delay); - }; + }; return ( <>
-
- +
+ debounce(() => handleInputChange(e), 1500)} - style={{ background: "transparent", outline: "none",width:"100%" }} + onChange={(e) => debounce(() => handleInputChange(e), 1500)} + style={{ background: "transparent", outline: "none", width: "100%" }} placeholder="search..." + className="text-gray-200 placeholder-gray-400" >
- {/* nav */} -
- +
+
{!showSideNav ? ( -
+
{ + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within a ThemeProvider'); + } + return context; +}; + +export const ThemeProvider = ({ children }) => { + const [isDarkMode, setIsDarkMode] = useState(() => { + const savedTheme = localStorage.getItem('theme'); + return savedTheme === 'dark'; + }); + + useEffect(() => { + if (isDarkMode) { + document.documentElement.classList.add('dark'); + localStorage.setItem('theme', 'dark'); + } else { + document.documentElement.classList.remove('dark'); + localStorage.setItem('theme', 'light'); + } + }, [isDarkMode]); + + const toggleTheme = () => { + setIsDarkMode((prev) => !prev); + }; + + return ( + + {children} + + ); +}; \ No newline at end of file diff --git a/src/database/websites/html.json b/src/database/websites/html.json index f6a7a14..dbda45a 100644 --- a/src/database/websites/html.json +++ b/src/database/websites/html.json @@ -49,7 +49,7 @@ "img": "https://rb.gy/scnw5" }, { - "tag": "html" + "tag": "html", "title": "Programiz", "description": "Learn to code in Python, C/C++, Java, and other popular programming languages with our easy to follow tutorials, examples, online compiler and references.", "link": "https://www.programiz.com/", diff --git a/src/database/websites/javascript.json b/src/database/websites/javascript.json index c3c0723..07f4aab 100644 --- a/src/database/websites/javascript.json +++ b/src/database/websites/javascript.json @@ -49,7 +49,7 @@ "img": "https://rb.gy/scnw5" }, { - "tag": "js" + "tag": "js", "title": "Programiz", "description": "Learn to code in Python, C/C++, Java, and other popular programming languages with our easy to follow tutorials, examples, online compiler and references.", "link": "https://www.programiz.com/", diff --git a/src/index.css b/src/index.css index 3a74775..567d95a 100644 --- a/src/index.css +++ b/src/index.css @@ -7,34 +7,63 @@ @import url('https://fonts.googleapis.com/css2?family=Merriweather&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap'); - @tailwind base; @tailwind components; @tailwind utilities; +@layer base { + body { + @apply bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-white transition-colors duration-200; + } -/* Css for cards hover effect */ -.img-container { - overflow: hidden; + /* Code tag styles */ + code, pre, kbd, samp { + color: black !important; + } + + .dark code, .dark pre, .dark kbd, .dark samp { + color: black !important; + } } -.img-container img { + +@layer components { + /* Css for cards hover effect */ + .img-container { + overflow: hidden; + } + + .img-container img { transition: transform 0.5s; -} -.img-container img:hover { + } + + .img-container img:hover { transform: scale(0.7); + } } -/* =========================== SCROLLBAR ================ */ -::-webkit-scrollbar { +@layer utilities { + /* Scrollbar styles */ + ::-webkit-scrollbar { width: 8px; } - + ::-webkit-scrollbar-thumb { background-color: #8e8e8e; border-radius: 20px; } - + ::-webkit-scrollbar-track { background-color: #fff; border-radius: 20px; - } \ No newline at end of file + } + + /* Cursor blink animation + @keyframes blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0; } + } */ + + /* .cursor-blink { + animation: blink 1s step-end infinite; + } */ +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index 2f9caf4..b0e3770 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,34 +1,36 @@ /** @type {import('tailwindcss').Config} */ export default { content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + darkMode: 'class', theme: { - fontFamily: { - roboto: ["Roboto", "sans-serif"], - inter: ["Inter", "sans-serif"], - pacifico: ["Pacifico", "cursive"], - montserrat: ['Montserrat', "sans-serif"], - ultra: ["Ultra", "serif"], - francois: ["Francois One", "sans-serif"], - merriweather: ["Merriweather", "serif"], - lobster: ['Lobster', "cursive"] - }, - boxShadow: { - "3xl": "0 1px 8px 2px rgba(75,0,94,0.2)", - "4xl": "0 1px 15px 4px rgb(75,0,94,0.4)", - "xl" : "0px 7px 29px 0px rgba(100, 100, 111, 0.2)" - }, - dropShadow: { - xl: "0 5px 15px rgb(78, 70, 55,0.3)", - }, - colors: { - grape: { - 50: "#f3d9fa", - 100: "#eebefa", - 200: "#862e9c", - 300: "#4b005e", + extend: { + fontFamily: { + roboto: ["Roboto", "sans-serif"], + inter: ["Inter", "sans-serif"], + pacifico: ["Pacifico", "cursive"], + montserrat: ['Montserrat', "sans-serif"], + ultra: ["Ultra", "serif"], + francois: ["Francois One", "sans-serif"], + merriweather: ["Merriweather", "serif"], + lobster: ['Lobster', "cursive"] }, - extend: {}, - }, - plugins: [], + boxShadow: { + "3xl": "0 1px 8px 2px rgba(75,0,94,0.2)", + "4xl": "0 1px 15px 4px rgb(75,0,94,0.4)", + "xl": "0px 7px 29px 0px rgba(100, 100, 111, 0.2)" + }, + dropShadow: { + xl: "0 5px 15px rgb(78, 70, 55,0.3)", + }, + colors: { + grape: { + 50: "#f3d9fa", + 100: "#eebefa", + 200: "#862e9c", + 300: "#4b005e", + } + } + } }, + plugins: [], }; From d9ec08510498048e8ca768dc69a10cc85c36c5bc Mon Sep 17 00:00:00 2001 From: Shobhini <130296359+Shobhini@users.noreply.github.com> Date: Tue, 20 May 2025 13:04:16 +0530 Subject: [PATCH 2/3] UI: Changes the position and styling of Dark mode toggle button --- src/App.jsx | 2 + src/components/Resources.jsx | 102 +++++++++++++++++++++-------------- src/components/Sidebar.jsx | 12 +---- 3 files changed, 66 insertions(+), 50 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index 52a316a..babc31f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,6 +12,7 @@ const Challenges = lazy(() => import('./components/challenges/Index')); const Books = lazy(() => import('./components/books/Index')); const Tools = lazy(() => import('./components/tools/Index')); const Editors = lazy(() => import('./components/editor/Index')); +const Resources = lazy(() => import('./components/Resources')); function App() { return ( @@ -33,6 +34,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/components/Resources.jsx b/src/components/Resources.jsx index 6b943cc..842d68b 100644 --- a/src/components/Resources.jsx +++ b/src/components/Resources.jsx @@ -1,8 +1,10 @@ import { motion } from 'framer-motion'; import { useState } from 'react'; +import { useTheme } from '../context/ThemeContext'; export default function Resources() { const [activeCategory, setActiveCategory] = useState('all'); + const { isDarkMode, toggleTheme } = useTheme(); const categories = [ { id: 'all', name: 'All Resources' }, @@ -48,50 +50,70 @@ export default function Resources() { : resources.filter(resource => resource.category === activeCategory); return ( -
-
- {categories.map((category) => ( - - ))} +
+ {/* Dark mode toggle - fixed position */} +
+
- {/*
*/} -
+ {/* Main content */} +
+
+ {categories.map((category) => ( + + ))} +
- {filteredResources.map((resource) => ( - -

- {resource.title} -

-

- {resource.description} -

- + {filteredResources.map((resource) => ( + - Learn More → - -
- ))} +

+ {resource.title} +

+

+ {resource.description} +

+ + Learn More → + + + ))} +
); diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx index 5666ea0..fbd02d5 100644 --- a/src/components/Sidebar.jsx +++ b/src/components/Sidebar.jsx @@ -2,7 +2,7 @@ import { NavLink } from 'react-router-dom'; import { useTheme } from '../context/ThemeContext'; const Sidebar = () => { - const { isDarkMode, toggleTheme } = useTheme(); + const { isDarkMode } = useTheme(); const navItems = [ { path: '/', label: 'Home' }, @@ -13,8 +13,7 @@ const Sidebar = () => { { path: '/books', label: 'Books' }, { path: '/tools', label: 'Tools' }, { path: '/editors', label: 'Editors' }, - // { path: '/resources', label: 'Resources' }, - // { path: '/contact', label: 'Contact' }, + { path: '/resources', label: 'Resources' }, ]; return ( @@ -41,13 +40,6 @@ const Sidebar = () => { ))} - -
); From 69fb736b557977436f31e8be23773deac8a5e4f3 Mon Sep 17 00:00:00 2001 From: Shobhini <130296359+Shobhini@users.noreply.github.com> Date: Tue, 20 May 2025 15:05:18 +0530 Subject: [PATCH 3/3] UI: Fixed card styling and layout --- src/App.jsx | 2 +- src/components/Card.jsx | 2 +- src/components/Home.jsx | 6 +++--- src/components/Resources.jsx | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/App.jsx b/src/App.jsx index babc31f..e0e6689 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -19,7 +19,7 @@ function App() {
-
+
Loading...
diff --git a/src/components/Card.jsx b/src/components/Card.jsx index 83ed546..8df8e53 100644 --- a/src/components/Card.jsx +++ b/src/components/Card.jsx @@ -17,7 +17,7 @@ const Card = ({ title, link, description, i, img }) => {
-

+

{title}

diff --git a/src/components/Home.jsx b/src/components/Home.jsx index 2de53fa..01ee2aa 100644 --- a/src/components/Home.jsx +++ b/src/components/Home.jsx @@ -39,9 +39,9 @@ export default function Home() { }, []); return ( -
+
Resources -

+

Explore our vast collection of web development resources, designed to give you the knowledge and tools you need to succeed in the world of web development!

diff --git a/src/components/Resources.jsx b/src/components/Resources.jsx index 842d68b..5fcf8b5 100644 --- a/src/components/Resources.jsx +++ b/src/components/Resources.jsx @@ -50,12 +50,12 @@ export default function Resources() { : resources.filter(resource => resource.category === activeCategory); return ( -
+
{/* Dark mode toggle - fixed position */} -
+
{/* Main content */} -
+
{categories.map((category) => (