diff --git a/css/dropdown.css b/css/dropdown.css new file mode 100644 index 0000000..fade259 --- /dev/null +++ b/css/dropdown.css @@ -0,0 +1,125 @@ +/* ===== Dropdown Base ===== */ +.dropdown { + position: relative; +} + +.dropdown-toggle { + cursor: pointer; + display: inline-block; +} + +/* Dropdown menu hidden by default */ +.dropdown-menu { + display: none; + position: absolute; + background-color: #333; + top: 100%; + left: 0; + min-width: 180px; + border-radius: 6px; + padding: 10px 0; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); + z-index: 1000; +} + +/* Dropdown menu links */ +.dropdown-menu li { + list-style: none; +} + +.dropdown-menu a { + display: block; + color: #fff; + padding: 8px 16px; + text-decoration: none; + transition: background 0.3s; +} + +.dropdown-menu a:hover { + background-color: #444; +} + +/* Arrow indicator (base) */ +.dropdown-toggle::after { + content: "▾"; + display: inline-block; + margin-left: 6px; + transition: transform 0.3s ease; +} + +/* Rotate arrow upward when open */ +.dropdown.open .dropdown-toggle::after { + transform: rotate(180deg); +} + +/* ===== Desktop Hover Dropdown ===== */ +@media (min-width: 769px) { + .dropdown:hover .dropdown-menu { + display: block; + } + + .dropdown-menu { + position: absolute; + background: #333; + padding: 0.5rem 1rem; + border-radius: 5px; + z-index: 100; + } +} + +/* ===== Mobile Dropdown and Hamburger ===== */ +@media (max-width: 768px) { + .nav-links { + flex-direction: column; + display: none; + } + + .nav-links.active { + display: flex; + } + + .hamburger { + display: block; + font-size: 28px; + cursor: pointer; + } + + .dropdown-menu { + position: static; + /* Prevents overlap */ + background: #333; + padding-left: 16px; + border-radius: 5px; + width: 100%; + overflow: hidden; + max-height: 0; + transition: max-height 0.3s ease; + } + + .dropdown.open .dropdown-menu { + max-height: 500px; + /* Adjust as needed */ + } + + .dropdown-toggle { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + } + + .dropdown-toggle::after { + content: "▾"; + margin-left: 8px; + transition: transform 0.3s; + } + + .dropdown.open .dropdown-toggle::after { + transform: rotate(180deg); + } + + .dropdown-menu li a { + display: block; + padding: 8px 0; + } +} \ No newline at end of file diff --git a/css/main.css b/css/main.css index 20dc181..aa511b5 100644 --- a/css/main.css +++ b/css/main.css @@ -66,30 +66,6 @@ text-align: center; } -/* =================================================== - ===== Teck Stack Section ===== -=================================================== */ -#tech-stack { - text-align: center; - /* height: 20vh; */ -} - -.tech-stack .btn { - display: inline-block; - padding: 12px 25px; - border-radius: 30px; - background: #ff9800; - color: #fff; - text-decoration: none; - font-weight: bold; - transition: background 0.3s, transform 0.3s; -} - -.tech-stack .btn:hover { - background: #e68900; - transform: translateY(-3px); -} - /* =================================================== ===== Skills Section ===== =================================================== */ @@ -151,6 +127,44 @@ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2); } +/* =================================================== + ===== Teck Stack Section ===== +=================================================== */ +#portfolio { + text-align: center; + /* height: 20vh; */ +} + +.portfolio .btn { + display: inline-block; + padding: 12px 25px; + border-radius: 30px; + background: #ff9800; + color: #fff; + text-decoration: none; + font-weight: bold; + transition: background 0.3s, transform 0.3s; +} + +.portfolio .btn:hover { + background: #e68900; + transform: translateY(-3px); +} + +.portfolio-card { + background: rgba(179, 105, 105, 0.3); + backdrop-filter: blur(10px); + border-radius: 20px; + padding: 20px; + margin: 20px 0; + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1); +} + +body.dark .portfolio-card { + background-color: #467db4; + color: #000; +} + /* =================================================== ===== Dark Mode ===== =================================================== */ @@ -245,7 +259,7 @@ body.dark #darkModeToggle:hover { /* Hover effect for interactivity */ .visitor-count:hover { - transform: translateY(-3px); + transform: translateY(-10px); box-shadow: 0 14px 30px rgba(0, 0, 0, 0.25), 0 0 30px rgba(255, 87, 34, 0.2); /* stronger glow on hover */ } diff --git a/index.html b/index.html index 7147b6b..4fbdd8d 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - Vimal Tech - Portfolio + Vimal Tech @@ -12,6 +12,7 @@ + @@ -42,11 +43,19 @@ @@ -77,12 +86,6 @@

About Me

- -
-

Tech Stack Dashboard

- Tap to read Overview -
-

Services I Offer I Preview

@@ -113,7 +116,6 @@

Project Consulting

View All Services

- Alex Food Corner Live Project
@@ -237,6 +239,14 @@

Desktop Chat Application (Local Area Network)


+ +
+
+

Portfolio

+ Tap to read Overview +
+
+

Contact Me

@@ -273,6 +283,7 @@

Contact Me

+ \ No newline at end of file diff --git a/js/common.js b/js/common.js index 9997b14..6a49da9 100644 --- a/js/common.js +++ b/js/common.js @@ -34,7 +34,6 @@ document.addEventListener("DOMContentLoaded", () => { hamburger.textContent = "☰"; } }); - } /* ============================ @@ -111,4 +110,47 @@ document.addEventListener("DOMContentLoaded", () => { }); }); } + + // Dropdown toggle for Desktop + const dropdownToggles = document.querySelectorAll(".dropdown-toggle"); + + dropdownToggles.forEach(toggle => { + toggle.addEventListener("click", (e) => { + e.preventDefault(); + const parent = toggle.parentElement; + parent.classList.toggle("open"); + + const menu = parent.querySelector(".dropdown-menu"); + if (menu) { + menu.style.display = menu.style.display === "block" ? "none" : "block"; + } + }); + }); + + // Ensure all dropdowns are closed on page load (prevents an open menu after refresh) + function resetDropdowns() { + const dropdowns = document.querySelectorAll(".dropdown"); + dropdowns.forEach(drop => { + drop.classList.remove("open"); + const menu = drop.querySelector(".dropdown-menu"); + if (menu) menu.style.display = "none"; + }); + } + + // Close dropdown when clicking outside + document.addEventListener("click", (e) => { + const isDropdownToggle = e.target.matches(".dropdown-toggle"); + const dropdown = e.target.closest(".dropdown"); + + document.querySelectorAll(".dropdown").forEach(drop => { + const menu = drop.querySelector(".dropdown-menu"); + + // If clicked outside this dropdown, close it + if (drop !== dropdown && menu) { + drop.classList.remove("open"); + menu.style.display = "none"; + } + }); + }); + }); diff --git a/js/dropdown.js b/js/dropdown.js new file mode 100644 index 0000000..b4ded7a --- /dev/null +++ b/js/dropdown.js @@ -0,0 +1,83 @@ +document.addEventListener("DOMContentLoaded", () => { + const hamburger = document.getElementById("hamburger"); + const navLinks = document.getElementById("nav-links"); + + if (!hamburger || !navLinks) return; + + // Function to initialize mobile dropdown toggles + function initMobileDropdowns() { + const dropdowns = navLinks.querySelectorAll(".dropdown"); + + dropdowns.forEach(dropdown => { + const toggle = dropdown.querySelector(".dropdown-toggle"); + const menu = dropdown.querySelector(".dropdown-menu"); + + if (!toggle || !menu) return; + + // Remove previous listener to avoid duplicates + toggle.replaceWith(toggle.cloneNode(true)); + const newToggle = dropdown.querySelector(".dropdown-toggle"); + + newToggle.addEventListener("click", (e) => { + if (window.innerWidth > 768) return; + + e.preventDefault(); + e.stopPropagation(); + + // Close other dropdowns + dropdowns.forEach(d => { + if (d !== dropdown) { + d.classList.remove("open"); + const m = d.querySelector(".dropdown-menu"); + if (m) m.style.display = "none"; + } + }); + + // Toggle current + const isOpen = dropdown.classList.toggle("open"); + menu.style.display = isOpen ? "block" : "none"; + }); + }); + + // Click outside to close + document.addEventListener("click", (e) => { + if (window.innerWidth <= 768 && !e.target.closest(".dropdown")) { + dropdowns.forEach(d => { + d.classList.remove("open"); + const menu = d.querySelector(".dropdown-menu"); + if (menu) menu.style.display = "none"; + }); + } + }); + } + + // When hamburger is clicked + hamburger.addEventListener("click", () => { + setTimeout(() => { + if (navLinks.classList.contains("active")) { + // Attach dropdown events only when menu is visible + initMobileDropdowns(); + } else { + // Hamburger closed → reset dropdowns + const dropdowns = navLinks.querySelectorAll(".dropdown"); + dropdowns.forEach(d => { + d.classList.remove("open"); + const menu = d.querySelector(".dropdown-menu"); + if (menu) menu.style.display = "none"; + }); + } + }, 10); + }); + + // Reset dropdowns on resize + window.addEventListener("resize", () => { + if (window.innerWidth > 768) { + const dropdowns = navLinks.querySelectorAll(".dropdown"); + dropdowns.forEach(d => { + d.classList.remove("open"); + const menu = d.querySelector(".dropdown-menu"); + if (menu) menu.style.display = ""; + }); + } + }); +}); diff --git a/services.html b/services.html index 63ebdb1..f56d084 100644 --- a/services.html +++ b/services.html @@ -106,7 +106,12 @@

Security & Optimization

Live Projects