From e210aecd14f7381ea2955087563af9cfd5b526e6 Mon Sep 17 00:00:00 2001 From: Srajal-code1 Date: Thu, 23 Oct 2025 17:47:19 +0530 Subject: [PATCH] add a minimal and matching UI back to top button --- components/footer.html | 8 ++++ script.js | 96 ++++++++++++++++++++++++++++++++++++++++++ style.css | 35 +++++++++++++++ 3 files changed, 139 insertions(+) diff --git a/components/footer.html b/components/footer.html index e15cf8b..8cf461c 100644 --- a/components/footer.html +++ b/components/footer.html @@ -46,3 +46,11 @@

Newsletter

© 2023 Love Alchemy. All rights reserved. Made with for love

+ + + diff --git a/script.js b/script.js index 1226b3b..f6b23d9 100644 --- a/script.js +++ b/script.js @@ -399,6 +399,102 @@ function combineNumbers(num1, num2, supportMaster = true) { return combined } +// Back button behavior — added for site-wide quick navigation +;(function() { + function scrollToTopSmooth() { + try { + window.scrollTo({ top: 0, behavior: 'smooth' }) + } catch (err) { + window.scrollTo(0, 0) + } + } + + function initBackBtn(backBtn) { + if (!backBtn) return + + const SHOW_AFTER = 200 + function updateBackBtnVisibility() { + const y = window.scrollY || window.pageYOffset + if (y > SHOW_AFTER) { + backBtn.style.opacity = '1' + backBtn.style.pointerEvents = 'auto' + backBtn.style.transform = 'translateY(0) scale(1)' + } else { + backBtn.style.opacity = '0' + backBtn.style.pointerEvents = 'none' + backBtn.style.transform = 'translateY(8px) scale(0.98)' + } + } + + // Apply initial inline styles for a smooth transition even if CSS hasn't loaded yet + backBtn.style.transition = 'opacity 0.18s ease, transform 0.18s ease' + backBtn.style.opacity = '0' + backBtn.style.pointerEvents = 'none' + backBtn.style.transform = 'translateY(8px) scale(0.98)' + + // Bind scroll listener + window.addEventListener('scroll', () => { + if (typeof window.requestAnimationFrame === 'function') { + window.requestAnimationFrame(updateBackBtnVisibility) + } else { + updateBackBtnVisibility() + } + }, { passive: true }) + + backBtn.addEventListener('click', (e) => { + e.preventDefault() + e.stopPropagation() + scrollToTopSmooth() + }) + + // Keyboard support + window.addEventListener('keydown', (e) => { + if (e.key === 'Escape' || e.key === 'Home') { + scrollToTopSmooth() + } + }) + + // Initial visibility check in case page is already scrolled + updateBackBtnVisibility() + } + + // Try to initialize immediately + document.addEventListener('DOMContentLoaded', () => { + const btn = document.getElementById('backBtn') + if (btn) { + initBackBtn(btn) + return + } + + // If footer is injected later, observe DOM mutations for the button + const observer = new MutationObserver((mutations, obs) => { + const found = document.getElementById('backBtn') + if (found) { + initBackBtn(found) + obs.disconnect() + } + }) + + observer.observe(document.body, { childList: true, subtree: true }) + + // Fallback: short polling for up to 3 seconds + const start = Date.now() + const poll = setInterval(() => { + const found = document.getElementById('backBtn') + if (found) { + clearInterval(poll) + observer.disconnect() + initBackBtn(found) + return + } + if (Date.now() - start > 3000) { + clearInterval(poll) + observer.disconnect() + } + }, 150) + }) +})() + function mapToPercent(combined, num1, num2) { let base diff --git a/style.css b/style.css index 6611f09..93874b6 100644 --- a/style.css +++ b/style.css @@ -398,6 +398,41 @@ body { background: rgba(255,255,255,0.03); color: #fff; } + +/* Floating back button (bottom-right) */ +.back-btn { + position: fixed; + right: 18px; + bottom: 18px; + width: 52px; + height: 52px; + border-radius: 50%; + display: inline-grid; + place-items: center; + background: linear-gradient(180deg, rgba(255,255,255,0.06), rgba(255,255,255,0.03)); + border: 1px solid rgba(255,255,255,0.08); + color: var(--accent2); + box-shadow: 0 8px 24px rgba(0,0,0,0.36); + cursor: pointer; + z-index: 1200; + transition: transform 0.12s ease, box-shadow 0.12s ease, opacity 0.12s ease; +} + +.back-btn svg { color: var(--accent2); } + +.back-btn:active { transform: translateY(2px) scale(0.98); } +.back-btn:focus { outline: none; box-shadow: 0 0 0 6px rgba(255,46,99,0.09); } + +/* Subtle hide on very small screens to avoid overlapping form controls */ +@media (max-width: 360px) { + .back-btn { right: 12px; bottom: 12px; width: 48px; height: 48px; } +} + +/* Dark-mode variant */ +body.dark-mode .back-btn { + background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)); + border: 1px solid rgba(255,255,255,0.04); +} .contact-actions { display: flex; gap: 8px;