docs: fix scrolling issue with sidebar (#2791)
This was an annoying change. Next.js feels like it should be preserving the scroll position but it doesn't, it re-renders. Drive-by change to make the transition at the bottom not animate everything (this might have been the CPU usage you were seeing @si14 ### Change Type - [x] `documentation` — Changes to the documentation only[^2] ### Release Notes - Docs: fix up scrolling.
This commit is contained in:
parent
056481899c
commit
c47360d236
2 changed files with 30 additions and 5 deletions
|
@ -12,7 +12,7 @@ import {
|
||||||
import * as Accordion from '@radix-ui/react-accordion'
|
import * as Accordion from '@radix-ui/react-accordion'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { usePathname } from 'next/navigation'
|
import { usePathname } from 'next/navigation'
|
||||||
import { createContext, useContext, useEffect } from 'react'
|
import { UIEvent, createContext, useContext, useEffect, useRef } from 'react'
|
||||||
import { SectionLinks } from './Header'
|
import { SectionLinks } from './Header'
|
||||||
import { Chevron } from './Icons'
|
import { Chevron } from './Icons'
|
||||||
import { Search } from './Search'
|
import { Search } from './Search'
|
||||||
|
@ -28,21 +28,46 @@ const linkContext = createContext<{
|
||||||
sectionId: string | null
|
sectionId: string | null
|
||||||
} | null>(null)
|
} | null>(null)
|
||||||
|
|
||||||
|
// N.B. UGH, the sidebar's scroll position keeps getting lost when navigation occurs
|
||||||
|
// and we keep track of the last known position here outside of the component because
|
||||||
|
// it keeps re-rendering.
|
||||||
|
let scrollPosition = 0
|
||||||
|
|
||||||
export function Sidebar({ headings, links, sectionId, categoryId, articleId }: SidebarProps) {
|
export function Sidebar({ headings, links, sectionId, categoryId, articleId }: SidebarProps) {
|
||||||
const activeId = articleId ?? categoryId ?? sectionId
|
const activeId = articleId ?? categoryId ?? sectionId
|
||||||
|
const sidebarRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
const pathName = usePathname()
|
const pathName = usePathname()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.classList.remove('sidebar-open')
|
document.body.classList.remove('sidebar-open')
|
||||||
|
|
||||||
document.querySelector('.sidebar__nav [data-active=true]')?.scrollIntoView({ block: 'center' })
|
const sidebarEl = sidebarRef.current
|
||||||
|
if (!sidebarEl) return
|
||||||
|
|
||||||
|
sidebarEl.scrollTo(0, scrollPosition)
|
||||||
|
|
||||||
|
const activeLink = document.querySelector('.sidebar__nav [data-active=true]') as HTMLElement
|
||||||
|
if (
|
||||||
|
activeLink &&
|
||||||
|
activeLink.offsetTop < sidebarEl.scrollTop &&
|
||||||
|
activeLink.offsetTop > sidebarEl.scrollTop + sidebarEl.clientHeight
|
||||||
|
) {
|
||||||
|
// The above will *mostly* work to keep the position but we have some accordions that will collapse
|
||||||
|
// (like in the Reference docs) and we need to scroll to the active item.
|
||||||
|
activeLink.scrollIntoView({ block: 'center' })
|
||||||
|
}
|
||||||
}, [pathName])
|
}, [pathName])
|
||||||
|
|
||||||
|
const handleScroll = (e: UIEvent) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
scrollPosition = sidebarRef.current?.scrollTop ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<linkContext.Provider value={{ activeId, articleId, categoryId, sectionId }}>
|
<linkContext.Provider value={{ activeId, articleId, categoryId, sectionId }}>
|
||||||
<div className="sidebar scroll-light" onScroll={(e) => e.stopPropagation()}>
|
<div ref={sidebarRef} className="sidebar scroll-light" onScroll={handleScroll}>
|
||||||
<Search />
|
<Search />
|
||||||
<div className="sidebar__section__links">
|
<div className="sidebar__section__links">
|
||||||
<SectionLinks sectionId={sectionId} />
|
<SectionLinks sectionId={sectionId} />
|
||||||
|
|
|
@ -675,7 +675,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer__fancybox__item {
|
.footer__fancybox__item {
|
||||||
transition: all 3s;
|
transition: opacity 3s;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
|
@ -714,7 +714,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer__fancybox__item:hover {
|
.footer__fancybox__item:hover {
|
||||||
transition: all 0s;
|
transition: opacity 0s;
|
||||||
opacity: 0.32;
|
opacity: 0.32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue