diff --git a/static/css/style.css b/static/css/style.css index 701145ca..8371970b 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -1018,4 +1018,45 @@ body.modal-open { position: relative; transform: none; } +} + +/* Back to Top Button */ +.back-to-top { + position: fixed; + bottom: 20px; + right: 20px; + width: 36px; + height: 36px; + border-radius: 50%; + background: var(--card-bg); + border: 1px solid var(--border-color); + color: var(--text-color); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + opacity: 0; + visibility: hidden; + transform: translateY(10px); + transition: all 0.3s ease; + z-index: var(--z-overlay); +} + +.back-to-top.visible { + opacity: 1; + visibility: visible; + transform: translateY(0); +} + +.back-to-top:hover { + background: var(--lora-accent); + color: white; + transform: translateY(-2px); +} + +/* Ensure the button doesn't overlap with other corner controls on mobile */ +@media (max-width: 768px) { + .back-to-top { + bottom: 60px; /* Give some extra space from bottom on mobile */ + } } \ No newline at end of file diff --git a/static/js/main.js b/static/js/main.js index 652fab27..c213a0ca 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -14,7 +14,8 @@ import { copyTriggerWord, openCivitai, toggleFolderTags, - initFolderTagsVisibility + initFolderTagsVisibility, + initBackToTop } from './utils/uiHelpers.js'; import { initializeInfiniteScroll } from './utils/infiniteScroll.js'; import { showDeleteModal, confirmDelete, closeDeleteModal } from './utils/modalUtils.js'; @@ -48,6 +49,7 @@ document.addEventListener('DOMContentLoaded', () => { restoreFolderFilter(); initTheme(); initFolderTagsVisibility(); + initBackToTop(); window.searchManager = new SearchManager(); }); diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index 37b031db..a646085e 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -119,4 +119,36 @@ export function initFolderTagsVisibility() { folderTags.classList.add('collapsed'); btn.title = 'Expand folder tags'; } +} + +export function initBackToTop() { + const button = document.createElement('button'); + button.className = 'back-to-top'; + button.innerHTML = ''; + button.title = 'Back to top'; + document.body.appendChild(button); + + // Show/hide button based on scroll position + const toggleBackToTop = () => { + const scrollThreshold = window.innerHeight * 1.5; + if (window.scrollY > scrollThreshold) { + button.classList.add('visible'); + } else { + button.classList.remove('visible'); + } + }; + + // Smooth scroll to top + button.addEventListener('click', () => { + window.scrollTo({ + top: 0, + behavior: 'smooth' + }); + }); + + // Listen for scroll events + window.addEventListener('scroll', toggleBackToTop); + + // Initial check + toggleBackToTop(); } \ No newline at end of file