fix(router): scroll to top when href="/"
and hash already present (#32954)
When the URL already contains a hash (like `/#section`) and a `Link` with `href="/"` is clicked, the page should scroll to the top on the first click. Currently, it only happens with the second click (after `#section` has been removed from the URL). Fixes #32931 ## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `contributing.md` ## Feature - [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `yarn lint`
This commit is contained in:
parent
381ca374e5
commit
be1d308417
3 changed files with 68 additions and 1 deletions
|
@ -1615,7 +1615,7 @@ export default class Router implements BaseRouter {
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollToHash(as: string): void {
|
scrollToHash(as: string): void {
|
||||||
const [, hash] = as.split('#')
|
const [, hash = ''] = as.split('#')
|
||||||
// Scroll to top if the hash is just `#` with no value or `#top`
|
// Scroll to top if the hash is just `#` with no value or `#top`
|
||||||
// To mirror browsers
|
// To mirror browsers
|
||||||
if (hash === '' || hash === 'top') {
|
if (hash === '' || hash === 'top') {
|
||||||
|
|
16
test/integration/router-hash-navigation/pages/index.js
Normal file
16
test/integration/router-hash-navigation/pages/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div style={{ height: '100vh' }} />
|
||||||
|
<Link href="/">
|
||||||
|
<a id="top-link">top</a>
|
||||||
|
</Link>
|
||||||
|
<Link href="#section">
|
||||||
|
<a id="section-link">section link</a>
|
||||||
|
</Link>
|
||||||
|
<section id="section">section content</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
51
test/integration/router-hash-navigation/test/index.test.js
Normal file
51
test/integration/router-hash-navigation/test/index.test.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* eslint-env jest */
|
||||||
|
|
||||||
|
import { join } from 'path'
|
||||||
|
import webdriver from 'next-webdriver'
|
||||||
|
import {
|
||||||
|
findPort,
|
||||||
|
launchApp,
|
||||||
|
killApp,
|
||||||
|
nextStart,
|
||||||
|
nextBuild,
|
||||||
|
} from 'next-test-utils'
|
||||||
|
|
||||||
|
let app
|
||||||
|
let appPort
|
||||||
|
const appDir = join(__dirname, '../')
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
it('scrolls to top when href="/" and url already contains a hash', async () => {
|
||||||
|
const browser = await webdriver(appPort, '/#section')
|
||||||
|
expect(await browser.eval(() => window.scrollY)).not.toBe(0)
|
||||||
|
await browser.elementByCss('#top-link').click()
|
||||||
|
expect(await browser.eval(() => window.scrollY)).toBe(0)
|
||||||
|
await browser.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('router.isReady', () => {
|
||||||
|
describe('dev mode', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
appPort = await findPort()
|
||||||
|
app = await launchApp(appDir, appPort)
|
||||||
|
})
|
||||||
|
afterAll(async () => {
|
||||||
|
await killApp(app)
|
||||||
|
})
|
||||||
|
|
||||||
|
runTests()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('production mode', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await nextBuild(appDir)
|
||||||
|
|
||||||
|
appPort = await findPort()
|
||||||
|
app = await nextStart(appDir, appPort)
|
||||||
|
})
|
||||||
|
afterAll(() => killApp(app))
|
||||||
|
|
||||||
|
runTests()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue