Prevent navigation on hash change (#7824)

This commit is contained in:
Matthew Phillips 2023-07-27 08:42:04 -04:00 committed by GitHub
parent b063a2d8ae
commit 267487e63e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 2 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Prevent navigation on hash change

View file

@ -148,6 +148,7 @@ const { fallback = 'animate' } = Astro.props as Props;
link.href && link.href &&
(!link.target || link.target === '_self') && (!link.target || link.target === '_self') &&
link.origin === location.origin && link.origin === location.origin &&
!link.hash &&
ev.button === 0 && // left clicks only ev.button === 0 && // left clicks only
!ev.metaKey && // new tab (mac) !ev.metaKey && // new tab (mac)
!ev.ctrlKey && // new tab (windows) !ev.ctrlKey && // new tab (windows)
@ -162,13 +163,19 @@ const { fallback = 'animate' } = Astro.props as Props;
history.pushState({ index: currentHistoryIndex }, '', link.href); history.pushState({ index: currentHistoryIndex }, '', link.href);
} }
}); });
window.addEventListener('popstate', () => { window.addEventListener('popstate', ev => {
if (!transitionEnabledOnThisPage()) { if (!transitionEnabledOnThisPage()) {
// The current page doesn't haven't View Transitions, // The current page doesn't haven't View Transitions,
// respect that with a full page reload // respect that with a full page reload
location.reload(); location.reload();
return; 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 nextIndex = history.state?.index ?? currentHistoryIndex + 1;
const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back'; const direction: Direction = nextIndex > currentHistoryIndex ? 'forward' : 'back';
navigate(direction, location.href); navigate(direction, location.href);

View file

@ -3,6 +3,9 @@ import Layout from '../components/Layout.astro';
--- ---
<Layout> <Layout>
<p id="one">Page 1</p> <p id="one">Page 1</p>
<a id="click-one" href="#test">test</a>
<a id="click-two" href="/two">go to 2</a> <a id="click-two" href="/two">go to 2</a>
<a id="click-three" href="/three">go to 3</a> <a id="click-three" href="/three">go to 3</a>
<div id="test">test content</div>
</Layout> </Layout>

View file

@ -153,9 +153,20 @@ test.describe('View Transitions', () => {
}); });
test('astro:load event fires when navigating directly to a page', async ({ page, astro }) => { 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')); await page.goto(astro.resolveUrl('/two'));
const article = page.locator('#twoarticle'); const article = page.locator('#twoarticle');
await expect(article, 'should have script content').toHaveText('works'); 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');
});
}); });