Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix clicking on search result from same page doesn't scroll to the heading #4048

Merged
merged 19 commits into from
Jan 25, 2025
5 changes: 5 additions & 0 deletions .changeset/tricky-llamas-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nextra": patch
---

fix clicking on search result from same page doesn't scroll to the heading
2 changes: 1 addition & 1 deletion docs/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const metadata: Metadata = {

const banner = (
<Banner dismissible={false}>
🚧 This is WIP documentation for Nextra 4.0. Dima Machina is looking{' '}
🎉 Nextra 4.0 is released. Dima Machina is looking{' '}
<Link href="https://github.com/dimaMachina">
for a new job or consulting
</Link>
Expand Down
10 changes: 9 additions & 1 deletion packages/nextra/src/client/components/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,15 @@ export const Search: FC<SearchProps> = ({
// Calling before navigation so selector `html:not(:has(*:focus))` in styles.css will work,
// and we'll have padding top since input is not focused
inputRef.current.blur()
router.push(searchResult.url)
const [url, hash] = searchResult.url.split('#')
const isSamePathname = location.pathname === url
// `useHash` hook doesn't work with NextLink, and clicking on search
// result from same page doesn't scroll to the heading
if (isSamePathname) {
location.href = `#${hash}`
} else {
router.push(searchResult.url)
}
setSearch('')
}

Expand Down
14 changes: 7 additions & 7 deletions packages/nextra/src/client/components/tabs/index.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,16 @@ export const Tabs: FC<
for (const [index, el] of Object.entries(tabPanelsRef.current.children)) {
if (el === tabPanel) {
setSelectedIndex(Number(index))
const heading = tabPanel.querySelector<HTMLHeadingElement>(
`[id="${hash}"]`
)
if (!heading) return
// Execute on next tick after `selectedIndex` update
requestAnimationFrame(() => {
const heading = tabPanel.querySelector<HTMLHeadingElement>(
`[id="${hash}"]`
const link = tabPanel.querySelector<HTMLAnchorElement>(
`a[href="#${hash}"]`
)
// @ts-expect-error Property scrollIntoView does not exist on type ChildNod
heading?.nextSibling?.scrollIntoView({
behavior: 'smooth',
block: 'start'
})
link?.click()
})
}
}
Expand Down
30 changes: 24 additions & 6 deletions packages/nextra/src/server/__tests__/compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,10 +639,13 @@ describe('Code block', () => {
<h3
id="pnpm"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'pnpm'}
<a href="#pnpm" />
</h3>
<_components.strong>{'pnpm'}</_components.strong>
{': Fast, disk space efficient package manager.'}
Expand All @@ -651,10 +654,13 @@ describe('Code block', () => {
<h3
id="npm"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'npm'}
<a href="#npm" />
</h3>
<_components.strong>{'npm'}</_components.strong>
{' is a package manager for the JavaScript programming language.'}
Expand All @@ -663,10 +669,13 @@ describe('Code block', () => {
<h3
id="yarn"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'yarn'}
<a href="#yarn" />
</h3>
<_components.strong>{'Yarn'}</_components.strong>
{' is a software packaging system.'}
Expand All @@ -678,10 +687,13 @@ describe('Code block', () => {
<h3
id="pnpm-1"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'pnpm'}
<a href="#pnpm-1" />
</h3>
<_components.strong>{'pnpm'}</_components.strong>
{': Fast, disk space efficient package manager.'}
Expand All @@ -690,10 +702,13 @@ describe('Code block', () => {
<h3
id="npm-1"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'npm'}
<a href="#npm-1" />
</h3>
<_components.strong>{'npm'}</_components.strong>
{' is a package manager for the JavaScript programming language.'}
Expand All @@ -702,10 +717,13 @@ describe('Code block', () => {
<h3
id="yarn-1"
style={{
display: 'none'
visibility: 'hidden',
width: 0,
height: 0
}}
>
{'yarn'}
<a href="#yarn-1" />
</h3>
<_components.strong>{'Yarn'}</_components.strong>
{' is a software packaging system.'}
Expand Down
20 changes: 18 additions & 2 deletions packages/nextra/src/server/remark-plugins/remark-headings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,19 @@ export const remarkHeadings: Plugin<
type: 'mdxJsxFlowElement',
name: 'h3',
data: { _mdxExplicitJsx: true },
children: [{ type: 'text', value: tabName }],
children: [
{ type: 'text', value: tabName },
{
type: 'mdxJsxFlowElement',
name: 'a',
attributes: [
{ type: 'mdxJsxAttribute', name: 'href', value: `#${id}` }
],
data: {
_mdxExplicitJsx: true
}
}
],
attributes: [
{ type: 'mdxJsxAttribute', name: 'id', value: id },
{
Expand All @@ -99,7 +111,11 @@ export const remarkHeadings: Plugin<
body: [
{
type: 'ExpressionStatement',
expression: createAstObject({ display: 'none' })
expression: createAstObject({
visibility: 'hidden',
width: 0,
height: 0
})
}
]
}
Expand Down
Loading