diff --git a/src/app/posts/[...slug]/page.tsx b/src/app/posts/[...slug]/page.tsx index 14a2365..82c5b10 100644 --- a/src/app/posts/[...slug]/page.tsx +++ b/src/app/posts/[...slug]/page.tsx @@ -41,12 +41,43 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { const documentHeight = document.documentElement.scrollHeight; const windowHeight = window.innerHeight; - // Get the absolute position of the element by temporarily scrolling to top + // Detect if we're on desktop or mobile layout + const isDesktop = window.innerWidth >= 640; // sm breakpoint + const proseContainer = document.querySelector('.prose'); + + console.log('Layout detection:', { + isDesktop, + windowWidth: window.innerWidth, + proseContainer: proseContainer ? 'found' : 'not found' + }); + + // Get the absolute position of the element const currentScrollY = window.scrollY; let elementTop = 0; - // If we're not at the top, scroll to top temporarily to get accurate positions - if (currentScrollY > 0) { + if (isDesktop) { + // For desktop, we need to account for the nested container structure + // The content is inside a container with padding and margins + const rect = element.getBoundingClientRect(); + elementTop = rect.top + currentScrollY; + + // If we're at the top and getting 0, try a different approach + if (elementTop === 0 && currentScrollY === 0) { + // Walk up the DOM tree to calculate position + let currentElement = element; + while (currentElement && currentElement !== document.body) { + elementTop += currentElement.offsetTop; + currentElement = currentElement.offsetParent as HTMLElement; + } + } + } else { + // For mobile, use the simpler approach + const rect = element.getBoundingClientRect(); + elementTop = rect.top + currentScrollY; + } + + // If we're not at the top, temporarily scroll to top to get accurate positions + if (currentScrollY > 0 && elementTop === currentScrollY) { // Temporarily scroll to top to get accurate element positions window.scrollTo(0, 0); @@ -63,9 +94,11 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { }, 50); return; } else { - // We're already at the top, get position directly - const rect = element.getBoundingClientRect(); - elementTop = rect.top; + // We're already at the top or have a valid position, get position directly + if (elementTop === 0 && currentScrollY === 0) { + const rect = element.getBoundingClientRect(); + elementTop = rect.top; + } performActualScroll(elementTop); } @@ -77,7 +110,8 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { currentScrollY: window.scrollY, documentHeight, windowHeight, - canScroll: documentHeight > windowHeight + canScroll: documentHeight > windowHeight, + isDesktop }); // Check if page is scrollable @@ -86,8 +120,8 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { return; } - // Calculate the target scroll position - const offset = 100; // Account for sticky header + // Calculate the target scroll position with different offsets for desktop/mobile + const offset = isDesktop ? 120 : 100; // Slightly more offset for desktop due to header const targetScrollY = Math.max(0, elementTop - offset); console.log('Scroll calculation:', { @@ -95,7 +129,8 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { targetScrollY, offset, currentScrollY: window.scrollY, - scrollDifference: targetScrollY - window.scrollY + scrollDifference: targetScrollY - window.scrollY, + isDesktop }); // Check if we need to scroll at all @@ -157,29 +192,35 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { } } - const element = document.getElementById(id); + // Find the element, but only consider visible ones + const allElements = document.querySelectorAll(`#${id}`); + let element: HTMLElement | null = null; + + // Check if we're on desktop or mobile + const isDesktop = window.innerWidth >= 640; + + for (const el of Array.from(allElements)) { + const htmlEl = el as HTMLElement; + // Check if the element is visible (not hidden by CSS) + const rect = htmlEl.getBoundingClientRect(); + const isVisible = rect.width > 0 && rect.height > 0; + + if (isVisible) { + element = htmlEl; + break; + } + } + if (element) { console.log('Found target element:', element.textContent?.substring(0, 50)); scrollToElement(element); } else if (retryCount < 5) { console.log(`Element not found for anchor: ${id}, retrying... (${retryCount + 1}/5)`); - // Retry after a short delay setTimeout(() => { findAndScrollToElement(id, retryCount + 1); }, 100); } else { - console.warn('Target element not found for anchor after retries:', id); - // Log all available IDs for debugging - const allIds = Array.from(document.querySelectorAll('[id]')).map(el => el.id); - console.log('Available IDs on page:', allIds); - - // Show a user-friendly error message - const linkElement = document.querySelector(`a[href="#${id}"]`) as HTMLElement; - if (linkElement) { - linkElement.setAttribute('title', `Heading "${id}" not found`); - linkElement.style.color = '#ef4444'; // Red color for broken links - linkElement.style.textDecoration = 'line-through'; - } + console.warn(`Element with id "${id}" not found after retries`); } }; @@ -286,6 +327,40 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { }, 2000); }; + // Add a desktop-specific test function + (window as any).testDesktopScroll = () => { + console.log('=== Desktop Scroll Test ==='); + + const isDesktop = window.innerWidth >= 640; + console.log('Layout detection:', { + isDesktop, + windowWidth: window.innerWidth, + windowHeight: window.innerHeight + }); + + // Test scrolling to a known element + const overviewElement = document.getElementById('overview'); + if (overviewElement) { + console.log('Testing desktop scroll to overview...'); + + // Get element position using desktop method + const rect = overviewElement.getBoundingClientRect(); + const elementTop = rect.top + window.scrollY; + + console.log('Desktop position calculation:', { + rectTop: rect.top, + currentScrollY: window.scrollY, + calculatedElementTop: elementTop + }); + + scrollToElement(overviewElement); + } else { + console.log('Overview element not found'); + } + + console.log('=== End Desktop Test ==='); + }; + // Add a function to list all available IDs (window as any).listIds = () => { const allIds = Array.from(document.querySelectorAll('[id]')).map(el => ({ @@ -337,7 +412,13 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { const headings = Array.from(document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]')); - headings.forEach((el, index) => { + // Filter to only visible elements + const visibleHeadings = headings.filter(el => { + const rect = (el as HTMLElement).getBoundingClientRect(); + return rect.width > 0 && rect.height > 0; + }); + + visibleHeadings.forEach((el, index) => { const element = el as HTMLElement; // Calculate absolute position @@ -357,12 +438,26 @@ export default function PostPage({ params }: { params: { slug: string[] } }) { console.log('---'); }); - console.log('=== End Positions ==='); + console.log(`=== End Positions (${visibleHeadings.length} visible elements) ===`); }; // Add a simple test function (window as any).testScrollToElement = (id: string) => { - const element = document.getElementById(id); + // Find visible element with this ID + const allElements = document.querySelectorAll(`#${id}`); + let element: HTMLElement | null = null; + + for (const el of Array.from(allElements)) { + const htmlEl = el as HTMLElement; + const rect = htmlEl.getBoundingClientRect(); + const isVisible = rect.width > 0 && rect.height > 0; + + if (isVisible) { + element = htmlEl; + break; + } + } + if (element) { console.log(`Testing scroll to ${id}...`);