diff --git a/docs/spec-driven-workflow.adoc b/docs/spec-driven-workflow.adoc index 7996bc3..854d3ad 100644 --- a/docs/spec-driven-workflow.adoc +++ b/docs/spec-driven-workflow.adoc @@ -58,7 +58,7 @@ You review at the boundaries between phases, not after every line of code. == Workflow Overview -image::workflow-diagram.png[Workflow Overview,width=800] +image::docs/workflow-diagram.png[Workflow Overview,width=800] == Cross-Cutting Concerns diff --git a/docs/spec-driven-workflow.de.adoc b/docs/spec-driven-workflow.de.adoc index 81f01d0..54aad6d 100644 --- a/docs/spec-driven-workflow.de.adoc +++ b/docs/spec-driven-workflow.de.adoc @@ -60,7 +60,7 @@ Man reviewt an den Übergängen zwischen Phasen, nicht nach jeder einzelnen Code == Workflow-Übersicht -image::workflow-diagram.png[Workflow-Übersicht,width=800] +image::docs/workflow-diagram.png[Workflow-Übersicht,width=800] == Querschnittsthemen diff --git a/website/src/components/anchor-modal.js b/website/src/components/anchor-modal.js index 32dfaa4..9974407 100644 --- a/website/src/components/anchor-modal.js +++ b/website/src/components/anchor-modal.js @@ -1,6 +1,6 @@ import { i18n } from '../i18n.js' import { fetchAnchorsData } from '../utils/data-loader.js' -import { getRouteBeforeModal } from '../utils/router.js' +import { getRouteBeforeModal, getScrollBeforeModal } from '../utils/router.js' let asciidoctor = null @@ -104,7 +104,10 @@ export function closeModal() { // Return to the page that was active before the modal opened if (window.location.hash.startsWith('#/anchor/')) { const returnTo = getRouteBeforeModal() || '/' + const scrollY = getScrollBeforeModal() window.location.hash = '#' + returnTo + // Restore scroll position after the hashchange event + requestAnimationFrame(() => window.scrollTo(0, scrollY)) } } } diff --git a/website/src/utils/router.js b/website/src/utils/router.js index 5885a8f..0c06022 100644 --- a/website/src/utils/router.js +++ b/website/src/utils/router.js @@ -5,6 +5,7 @@ const routes = new Map() let currentRoute = null let routeBeforeModal = null +let scrollBeforeModal = 0 /** * Register a route handler @@ -55,8 +56,9 @@ function handleRoute() { const safeAnchorId = /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(anchorId) ? anchorId : null if (!safeAnchorId) return - // Remember the current route so we can return to it when the modal closes + // Remember the current route and scroll position for restoring after modal close routeBeforeModal = currentRoute + scrollBeforeModal = window.scrollY // Only navigate to home if no page is currently rendered if (!currentRoute) { @@ -66,6 +68,9 @@ function handleRoute() { homeHandler() } } + // Restore scroll position (browser resets it on hash change) + window.scrollTo(0, scrollBeforeModal) + // Open the anchor modal as overlay on current page // Import dynamically to avoid circular dependency import('../components/anchor-modal.js').then(({ showAnchorDetails }) => { @@ -105,3 +110,11 @@ export function isActive(path) { export function getRouteBeforeModal() { return routeBeforeModal } + +/** + * Get the scroll position that was active before the anchor modal opened + * @returns {number} Scroll Y position + */ +export function getScrollBeforeModal() { + return scrollBeforeModal +}