Fix sidebar scroll preservation per page with x-navigate directive
- Add x-navigate directive to all sidebar document links for Alpine navigation - Store scroll position per page using URL path as key in sessionStorage - Each page now maintains its own scroll position in the sidebar - Save scroll position before navigation and restore after navigation - Scroll position is preserved when clicking links in the sidebar - Works correctly with Alpine navigate events triggered by x-navigate directive
This commit is contained in:
@@ -259,64 +259,72 @@ class="fixed inset-y-0 left-0 top-16 w-64 bg-white border-r border-gray-200 over
|
||||
|
||||
<!-- Global Keyboard Shortcuts -->
|
||||
<script>
|
||||
// Sidebar scroll position management
|
||||
// Sidebar scroll position management per page
|
||||
function getSidebarScrollKey() {
|
||||
// Use current page URL to create a unique key for scroll position
|
||||
return 'kb_sidebar_scroll_' + window.location.pathname;
|
||||
}
|
||||
|
||||
function saveSidebarScroll() {
|
||||
const sidebar = document.getElementById('kb-sidebar');
|
||||
if (sidebar) {
|
||||
const scrollPos = sidebar.scrollTop;
|
||||
sessionStorage.setItem('kb_sidebar_scroll_pos', scrollPos);
|
||||
console.log('Saved sidebar scroll:', scrollPos);
|
||||
const key = getSidebarScrollKey();
|
||||
sessionStorage.setItem(key, scrollPos);
|
||||
console.log('Saved sidebar scroll for ' + window.location.pathname + ':', scrollPos);
|
||||
}
|
||||
}
|
||||
|
||||
function restoreSidebarScroll() {
|
||||
const sidebar = document.getElementById('kb-sidebar');
|
||||
if (sidebar) {
|
||||
// Use setTimeout to ensure DOM is fully ready
|
||||
setTimeout(() => {
|
||||
const savedPos = sessionStorage.getItem('kb_sidebar_scroll_pos');
|
||||
if (savedPos !== null) {
|
||||
const pos = parseInt(savedPos, 10);
|
||||
sidebar.scrollTop = pos;
|
||||
console.log('Restored sidebar scroll:', pos);
|
||||
sessionStorage.removeItem('kb_sidebar_scroll_pos');
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// For Livewire navigation
|
||||
document.addEventListener('livewire:navigated', saveSidebarScroll);
|
||||
document.addEventListener('livewire:navigating', () => {
|
||||
// Clear on any Livewire navigation
|
||||
saveSidebarScroll();
|
||||
});
|
||||
|
||||
// For Alpine navigate events
|
||||
document.addEventListener('alpine:navigating', saveSidebarScroll);
|
||||
document.addEventListener('alpine:navigated', restoreSidebarScroll);
|
||||
|
||||
// On page load, restore scroll position
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', restoreSidebarScroll);
|
||||
} else {
|
||||
restoreSidebarScroll();
|
||||
}
|
||||
|
||||
// Also restore on window load
|
||||
window.addEventListener('load', restoreSidebarScroll);
|
||||
|
||||
// Intercept all link clicks in sidebar to save scroll position
|
||||
document.addEventListener('click', function(e) {
|
||||
// Check if click is within sidebar
|
||||
const sidebar = document.getElementById('kb-sidebar');
|
||||
const link = e.target.closest('a');
|
||||
if (!sidebar) return;
|
||||
|
||||
if (sidebar && link && sidebar.contains(link)) {
|
||||
// Use requestAnimationFrame to ensure DOM is fully rendered
|
||||
requestAnimationFrame(() => {
|
||||
const key = getSidebarScrollKey();
|
||||
const savedPos = sessionStorage.getItem(key);
|
||||
console.log('Retrieved from sessionStorage for ' + window.location.pathname + ':', savedPos);
|
||||
|
||||
if (savedPos !== null && parseInt(savedPos, 10) > 0) {
|
||||
const pos = parseInt(savedPos, 10);
|
||||
sidebar.scrollTop = pos;
|
||||
console.log('Restored sidebar scroll for ' + window.location.pathname + ' to:', pos);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Intercept sidebar link clicks
|
||||
document.addEventListener('click', function(e) {
|
||||
const sidebar = document.getElementById('kb-sidebar');
|
||||
if (!sidebar) return;
|
||||
|
||||
const link = e.target.closest('a');
|
||||
if (sidebar.contains(link)) {
|
||||
console.log('Sidebar link clicked, saving scroll');
|
||||
saveSidebarScroll();
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Save before Alpine navigation
|
||||
document.addEventListener('alpine:navigating', saveSidebarScroll);
|
||||
|
||||
// Restore after Alpine navigation
|
||||
document.addEventListener('alpine:navigated', () => {
|
||||
console.log('Alpine navigated event fired, attempting restore');
|
||||
restoreSidebarScroll();
|
||||
});
|
||||
|
||||
// For page load/reload
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
console.log('DOMContentLoaded - calling restoreSidebarScroll');
|
||||
restoreSidebarScroll();
|
||||
});
|
||||
} else {
|
||||
console.log('Document already loaded - calling restoreSidebarScroll');
|
||||
setTimeout(restoreSidebarScroll, 100);
|
||||
}
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
@auth
|
||||
<div class="mt-6 pt-6 border-t border-gray-200">
|
||||
<a
|
||||
x-navigate
|
||||
href="{{ route('documents.create') }}"
|
||||
class="flex items-center justify-center px-4 py-2 text-sm font-medium text-white bg-indigo-600 rounded-md hover:bg-indigo-700"
|
||||
>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
$displayTitle = basename($file['document']->title);
|
||||
@endphp
|
||||
<a
|
||||
x-navigate
|
||||
href="{{ route('documents.show', $file['document']) }}"
|
||||
class="flex items-center px-2 py-1.5 text-sm text-gray-700 rounded hover:bg-gray-100 group"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user