mirror of
https://github.com/prometheus/docs.git
synced 2026-02-05 15:45:27 +01:00
Fix scrolling to fragment identifiers on newly loaded large pages (#2788)
When following a link to a fragment (#foo) on a long documentation page, the browser would try to scroll to the fragment too early, before some additional client-side layout shifts (could be due to font loading, highlighting, etc.) would cause the scroll position to be wrong again. This component waits for the layout to settle and then manually scrolls to the requested fragment again. You can see the problem by clicking on: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config It usually does not scroll directly to the relabeling section, but somewhere above it. Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
import TOC from "@/components/TOC";
|
||||
import LeftNav from "./LeftNav";
|
||||
import { IconMenu2 } from "@tabler/icons-react";
|
||||
import { AnchorScroller } from "@/components/AnchorScroller";
|
||||
|
||||
export default function DocsLayout({
|
||||
children,
|
||||
@@ -85,6 +86,7 @@ export default function DocsLayout({
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
<AnchorScroller />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
31
src/components/AnchorScroller.tsx
Normal file
31
src/components/AnchorScroller.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
// A component that, when included on a page, scrolls to the element
|
||||
// indicated by the URL hash (if any) after the page loads. While the
|
||||
// browser normally does this automatically, it does so too early in
|
||||
// our case, before the layout settles, resulting in incorrect scroll
|
||||
// positions.
|
||||
export function AnchorScroller() {
|
||||
useEffect(() => {
|
||||
const hash = window.location.hash;
|
||||
if (!hash) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = document.querySelector(hash);
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for layout to settle using two wrapped requestAnimationFrame calls.
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
el.scrollIntoView({ block: "start" });
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user