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 {
|
||||
const [, hash] = as.split('#')
|
||||
const [, hash = ''] = as.split('#')
|
||||
// Scroll to top if the hash is just `#` with no value or `#top`
|
||||
// To mirror browsers
|
||||
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