diff --git a/.changeset/moody-beers-leave.md b/.changeset/moody-beers-leave.md new file mode 100644 index 000000000..6189030e6 --- /dev/null +++ b/.changeset/moody-beers-leave.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Prevent navigation on hash change diff --git a/packages/astro/components/ViewTransitions.astro b/packages/astro/components/ViewTransitions.astro index 69744a026..24552e10f 100644 --- a/packages/astro/components/ViewTransitions.astro +++ b/packages/astro/components/ViewTransitions.astro @@ -148,6 +148,7 @@ const { fallback = 'animate' } = Astro.props as Props; link.href && (!link.target || link.target === '_self') && link.origin === location.origin && + !link.hash && ev.button === 0 && // left clicks only !ev.metaKey && // new tab (mac) !ev.ctrlKey && // new tab (windows) @@ -162,13 +163,19 @@ const { fallback = 'animate' } = Astro.props as Props; history.pushState({ index: currentHistoryIndex }, '', link.href); } }); - window.addEventListener('popstate', () => { + window.addEventListener('popstate', ev => { if (!transitionEnabledOnThisPage()) { // The current page doesn't haven't View Transitions, // respect that with a full page reload location.reload(); return; } + // hash change creates no state. + if(ev.state === null) { + history.replaceState({ index: currentHistoryIndex }, ''); + ev.preventDefault(); + return; + } const nextIndex = history.state?.index ?? currentHistoryIndex + 1; const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back'; navigate(direction, location.href); diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro index e896a8572..bc8b64a72 100644 --- a/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro +++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/one.astro @@ -3,6 +3,9 @@ import Layout from '../components/Layout.astro'; ---

Page 1

+ test go to 2 go to 3 + +
test content
diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js index d799b5ef3..ee5db3f2f 100644 --- a/packages/astro/e2e/view-transitions.test.js +++ b/packages/astro/e2e/view-transitions.test.js @@ -153,9 +153,20 @@ test.describe('View Transitions', () => { }); test('astro:load event fires when navigating directly to a page', async ({ page, astro }) => { - // Go to page 1 + // Go to page 2 await page.goto(astro.resolveUrl('/two')); const article = page.locator('#twoarticle'); await expect(article, 'should have script content').toHaveText('works'); }); + + test('click hash links does not do navigation', async ({ page, astro }) => { + // Go to page 1 + await page.goto(astro.resolveUrl('/one')); + const p = page.locator('#one'); + await expect(p, 'should have content').toHaveText('Page 1'); + + // Clicking 1 stays put + await page.click('#click-one'); + await expect(p, 'should have content').toHaveText('Page 1'); + }); });