From d2bf76a3515c1c3eb63aebe1d65879df2fbf2090 Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Tue, 29 Jul 2025 20:35:39 +0530 Subject: [PATCH 1/6] [UX] Add contact form toast message after submission --- index.html | 2 + package-lock.json | 6 +++ script.js | 129 +++++++++++++++++++++++++++++----------------- style.css | 35 ++++++++++++- 4 files changed, 123 insertions(+), 49 deletions(-) create mode 100644 package-lock.json diff --git a/index.html b/index.html index 6a0a07e..09a72cf 100644 --- a/index.html +++ b/index.html @@ -243,5 +243,7 @@

Keep In Touch

+ +
diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6c5c7f9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "Project-Vault", + "lockfileVersion": 3, + "requires": true, + "packages": {} +} diff --git a/script.js b/script.js index cbd8f63..7ed4e7c 100644 --- a/script.js +++ b/script.js @@ -63,18 +63,16 @@ document.addEventListener("DOMContentLoaded", () => { e.stopPropagation(); }); - - - // --- Contact Form Handling --- const contactForm = document.getElementById("contact-form"); if (contactForm) { contactForm.addEventListener("submit", function (e) { e.preventDefault(); - if (!this.checkValidity()) { - this.reportValidity(); // Show native browser messages - return; - } + if (!this.checkValidity()) { + this.reportValidity(); // Show native browser messages + return; + } + const formData = new FormData(this); const button = this.querySelector('button[type="submit"]'); const buttonText = button.querySelector(".button-text"); @@ -92,59 +90,94 @@ document.addEventListener("DOMContentLoaded", () => { loading.style.display = "none"; button.disabled = false; - alert("Thank you for your message! We'll get back to you soon."); + showToast("Thank you for your message! We'll get back to you soon."); }, 2000); }); } -const NUM_TRAILS = 30; -const snakeDots = []; - -for (let i = 0; i < NUM_TRAILS; i++) { - const dot = document.createElement("div"); - dot.classList.add("snake-dot"); - document.body.appendChild(dot); - snakeDots.push({ - el: dot, - x: window.innerWidth / 2, - y: window.innerHeight / 2, - scale: 1 - i * 0.02, - opacity: 1 - i * 0.02 - }); -} -let mouseX = window.innerWidth / 2; -let mouseY = window.innerHeight / 2; + // --- Toast Notification --- + function showToast(message) { + let toastContainer = document.getElementById("toast-container"); + + if (!toastContainer) { + toastContainer = document.createElement("div"); + toastContainer.id = "toast-container"; + toastContainer.style.position = "fixed"; + toastContainer.style.top = "20px"; + toastContainer.style.right = "20px"; + toastContainer.style.zIndex = "10000"; + document.body.appendChild(toastContainer); + } -document.addEventListener("mousemove", (e) => { - mouseX = e.clientX; - mouseY = e.clientY; -}); + const toast = document.createElement("div"); + toast.className = "toast"; + toast.textContent = message; + + Object.assign(toast.style, { + backgroundColor: "#28a745", + color: "#fff", + padding: "12px 20px", + borderRadius: "5px", + marginTop: "10px", + opacity: "0.95", + animation: "fadein 0.5s, fadeout 0.5s 2.5s", + }); -function animateSnakeCursor() { - let x = mouseX; - let y = mouseY; + toastContainer.appendChild(toast); - snakeDots.forEach((dot, i) => { - const next = snakeDots[i + 1] || { x, y }; + setTimeout(() => { + toast.remove(); + }, 3000); + } - // Faster follow speed - dot.x += (x - dot.x) * 0.35; - dot.y += (y - dot.y) * 0.35; + // --- Snake Cursor Trail --- + const NUM_TRAILS = 30; + const snakeDots = []; + + for (let i = 0; i < NUM_TRAILS; i++) { + const dot = document.createElement("div"); + dot.classList.add("snake-dot"); + document.body.appendChild(dot); + snakeDots.push({ + el: dot, + x: window.innerWidth / 2, + y: window.innerHeight / 2, + scale: 1 - i * 0.02, + opacity: 1 - i * 0.02 + }); + } - dot.el.style.left = `${dot.x}px`; - dot.el.style.top = `${dot.y}px`; - dot.el.style.transform = `translate(-50%, -50%) scale(${dot.scale})`; - dot.el.style.opacity = dot.opacity; + let mouseX = window.innerWidth / 2; + let mouseY = window.innerHeight / 2; - x = dot.x; - y = dot.y; + document.addEventListener("mousemove", (e) => { + mouseX = e.clientX; + mouseY = e.clientY; }); - requestAnimationFrame(animateSnakeCursor); -} + function animateSnakeCursor() { + let x = mouseX; + let y = mouseY; + + snakeDots.forEach((dot, i) => { + const next = snakeDots[i + 1] || { x, y }; -animateSnakeCursor(); + dot.x += (x - dot.x) * 0.35; + dot.y += (y - dot.y) * 0.35; + dot.el.style.left = `${dot.x}px`; + dot.el.style.top = `${dot.y}px`; + dot.el.style.transform = `translate(-50%, -50%) scale(${dot.scale})`; + dot.el.style.opacity = dot.opacity; + + x = dot.x; + y = dot.y; + }); + + requestAnimationFrame(animateSnakeCursor); + } + + animateSnakeCursor(); // --- Set Current Year --- const currentYearElement = document.getElementById("currentYear"); @@ -152,16 +185,16 @@ animateSnakeCursor(); currentYearElement.textContent = new Date().getFullYear(); } }); + const currentPath = window.location.pathname.split("/").pop(); -// Navbar document .querySelectorAll(".nav-link, .mobile-menu-link, .footer-ul li a") .forEach((link) => { if (link.getAttribute("href").includes(currentPath)) { link.classList.add("active"); } - // Highlight dropdown 'Components' if any of its child pages is active + const componentPages = ["website.html", "games.html", "ml.html"]; const dropdownToggle = document.querySelector(".dropdown-toggle"); diff --git a/style.css b/style.css index 5900c62..5f77331 100644 --- a/style.css +++ b/style.css @@ -897,4 +897,37 @@ footer::before { @keyframes spin { to { transform: rotate(360deg); } -} \ No newline at end of file +} + + +#toast-container { + position: fixed; + top: 20px; + right: 20px; + z-index: 9999; +} + +.toast { + padding: 12px 20px; + margin-top: 10px; + border-radius: 6px; + color: white; + font-weight: 600; + background-color: #4caf50; /* success default */ + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); + animation: fadein 0.5s ease, fadeout 0.5s ease 2.5s; +} + +.toast-error { + background-color: #f44336; +} + +@keyframes fadein { + from { opacity: 0; transform: translateY(-20px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes fadeout { + from { opacity: 1; transform: translateY(0); } + to { opacity: 0; transform: translateY(-20px); } +} From 6d1922a911b0fd4c08716446f5e06ea5b3476239 Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Tue, 29 Jul 2025 23:50:09 +0530 Subject: [PATCH 2/6] Resolved merge conflict in styles.css --- style.css | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/style.css b/style.css index 5f77331..fe68c13 100644 --- a/style.css +++ b/style.css @@ -295,6 +295,37 @@ nav a:hover, .mobile-menu-link:hover { background: rgba(255, 255, 255, 0.1); } +#toast-container { + position: fixed; + top: 20px; + right: 20px; + z-index: 9999; +} + +.toast { + padding: 12px 20px; + margin-top: 10px; + border-radius: 6px; + color: white; + font-weight: 600; + background-color: #4caf50; /* success default */ + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); + animation: fadein 0.5s ease, fadeout 0.5s ease 2.5s; +} + +.toast-error { + background-color: #f44336; +} + +@keyframes fadein { + from { opacity: 0; transform: translateY(-20px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes fadeout { + from { opacity: 1; transform: translateY(0); } + to { opacity: 0; transform: translateY(-20px); } +} /* Header */ header { @@ -900,34 +931,3 @@ footer::before { } -#toast-container { - position: fixed; - top: 20px; - right: 20px; - z-index: 9999; -} - -.toast { - padding: 12px 20px; - margin-top: 10px; - border-radius: 6px; - color: white; - font-weight: 600; - background-color: #4caf50; /* success default */ - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); - animation: fadein 0.5s ease, fadeout 0.5s ease 2.5s; -} - -.toast-error { - background-color: #f44336; -} - -@keyframes fadein { - from { opacity: 0; transform: translateY(-20px); } - to { opacity: 1; transform: translateY(0); } -} - -@keyframes fadeout { - from { opacity: 1; transform: translateY(0); } - to { opacity: 0; transform: translateY(-20px); } -} From 07928443122b86f07fb53ae593c63bac2b23ef22 Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Tue, 29 Jul 2025 23:54:08 +0530 Subject: [PATCH 3/6] Resolved merge conflict in styles.css --- style.css | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/style.css b/style.css index fe68c13..f94ce95 100644 --- a/style.css +++ b/style.css @@ -295,6 +295,11 @@ nav a:hover, .mobile-menu-link:hover { background: rgba(255, 255, 255, 0.1); } +@keyframes spin { + to { transform: rotate(360deg); } +} + + #toast-container { position: fixed; top: 20px; @@ -926,8 +931,4 @@ footer::before { animation: spin 1s ease-in-out infinite; } -@keyframes spin { - to { transform: rotate(360deg); } -} - From 5f3860be0db716225c0398eb6a65a7c4834029fe Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Tue, 29 Jul 2025 23:56:14 +0530 Subject: [PATCH 4/6] Resolved merge conflict in styles.css --- style.css | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/style.css b/style.css index f94ce95..c39cfcb 100644 --- a/style.css +++ b/style.css @@ -920,7 +920,6 @@ footer::before { transform: translateY(0); } } - .loading { display: inline-block; width: 20px; @@ -929,6 +928,4 @@ footer::before { border-radius: 50%; border-top-color: #fff; animation: spin 1s ease-in-out infinite; -} - - +} \ No newline at end of file From 4faee75a44dd1dda56d3433e058ff15ed98ad12a Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Tue, 29 Jul 2025 23:57:17 +0530 Subject: [PATCH 5/6] Resolved merge conflict in styles.css --- style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/style.css b/style.css index c39cfcb..5d97fe7 100644 --- a/style.css +++ b/style.css @@ -920,6 +920,7 @@ footer::before { transform: translateY(0); } } + .loading { display: inline-block; width: 20px; From 75e5973b989729e561f5b787032788365a768f17 Mon Sep 17 00:00:00 2001 From: Sravanthi359 Date: Wed, 30 Jul 2025 00:00:52 +0530 Subject: [PATCH 6/6] Resolved merge conflict in styles.css --- style.css | 64 ------------------------------------------------------- 1 file changed, 64 deletions(-) diff --git a/style.css b/style.css index 5d97fe7..cdf1119 100644 --- a/style.css +++ b/style.css @@ -295,71 +295,7 @@ nav a:hover, .mobile-menu-link:hover { background: rgba(255, 255, 255, 0.1); } -@keyframes spin { - to { transform: rotate(360deg); } -} - - -#toast-container { - position: fixed; - top: 20px; - right: 20px; - z-index: 9999; -} -.toast { - padding: 12px 20px; - margin-top: 10px; - border-radius: 6px; - color: white; - font-weight: 600; - background-color: #4caf50; /* success default */ - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2); - animation: fadein 0.5s ease, fadeout 0.5s ease 2.5s; -} - -.toast-error { - background-color: #f44336; -} - -@keyframes fadein { - from { opacity: 0; transform: translateY(-20px); } - to { opacity: 1; transform: translateY(0); } -} - -@keyframes fadeout { - from { opacity: 1; transform: translateY(0); } - to { opacity: 0; transform: translateY(-20px); } -} - -/* Header */ -header { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: #ffffff; - padding: 4rem 2rem; - text-align: center; - position: relative; - overflow: hidden; -} - -header::before { - content: ''; - position: absolute; - top: -50%; - left: -50%; - width: 200%; - height: 200%; - background: url('data:image/svg+xml,'); - animation: float 20s ease-in-out infinite; - opacity: 0.3; -} - -@keyframes float { - 0%, 100% { transform: translateX(0) translateY(0) rotate(0deg); } - 25% { transform: translateX(-20px) translateY(-20px) rotate(90deg); } - 50% { transform: translateX(20px) translateY(-10px) rotate(180deg); } - 75% { transform: translateX(-10px) translateY(20px) rotate(270deg); } -} header h1 { font-size: clamp(2rem, 5vw, 4rem);