diff --git a/e2e/fixtures/nav-link-item-with-hash/doc/index.mdx b/e2e/fixtures/nav-link-item-with-hash/doc/index.mdx index a432730c0..a0f618181 100644 --- a/e2e/fixtures/nav-link-item-with-hash/doc/index.mdx +++ b/e2e/fixtures/nav-link-item-with-hash/doc/index.mdx @@ -4,5 +4,5 @@ pageType: custom
contentA
-
contentB
+
A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF A LOT OF CONTENT A LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF CONTENT A LOT OF A LOT OF CONTENT A LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENTA LOT OF CONTENT
contentC
diff --git a/e2e/fixtures/nav-link-item-with-hash/rspress.config.ts b/e2e/fixtures/nav-link-item-with-hash/rspress.config.ts index 3f651736a..896fe369f 100644 --- a/e2e/fixtures/nav-link-item-with-hash/rspress.config.ts +++ b/e2e/fixtures/nav-link-item-with-hash/rspress.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ cleanUrls: true, }, themeConfig: { + hideNavbar: 'never', nav: [ { text: 'PageA', diff --git a/e2e/tests/nav-link-item-with-hash.test.ts b/e2e/tests/nav-link-item-with-hash.test.ts index e51fbee93..6e8416765 100644 --- a/e2e/tests/nav-link-item-with-hash.test.ts +++ b/e2e/tests/nav-link-item-with-hash.test.ts @@ -42,4 +42,36 @@ test.describe('basic test', async () => { await page.getByRole('link', { name: 'PageC' }).click(); await expect(page.locator('.rspress-nav-screen')).not.toBeVisible(); }); + + test('Navbar should be visible on mobile when we scroll down with hideNavbar to never', async ({ + page, + }) => { + await page.setViewportSize({ width: 375, height: 812 }); + + await page.goto(`http://localhost:${appPort}/`); + + await page.evaluate(() => { + window.scrollBy(0, 800); + }); + + // Allow to check if the rspress-nav is in the viewport + // toBeVisible() doesn't work here because it check the visibility and the display property + const isInViewport = await page.evaluate(sel => { + const element = document.querySelector(sel); + + if (!element) return false; + + const rect = element.getBoundingClientRect(); + return ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= + (window.innerHeight || document.documentElement.clientHeight) && + rect.right <= + (window.innerWidth || document.documentElement.clientWidth) + ); + }, '.rspress-nav'); + + expect(isInViewport).toBeTruthy(); + }); }); diff --git a/packages/theme-default/src/components/Nav/index.tsx b/packages/theme-default/src/components/Nav/index.tsx index b780ee4f9..0109fe8c9 100644 --- a/packages/theme-default/src/components/Nav/index.tsx +++ b/packages/theme-default/src/components/Nav/index.tsx @@ -27,7 +27,7 @@ const DEFAULT_NAV_POSITION = 'right'; export function Nav(props: NavProps) { const { beforeNavTitle, afterNavTitle, beforeNav, afterNavMenu, navTitle } = props; - const { siteData } = usePageData(); + const { siteData, page } = usePageData(); const { base } = siteData; const { pathname } = useLocation(); const [isMobile, setIsMobile] = useState(false); @@ -125,6 +125,15 @@ export function Nav(props: NavProps) { ); }; + + const computeNavPosition = () => { + // On doc page we have the menu bar that is already sticky + if (siteData.themeConfig.hideNavbar === 'never' && page.pageType !== 'doc') + return 'sticky'; + + return 'relative'; + }; + return ( <> {beforeNav} @@ -132,10 +141,7 @@ export function Nav(props: NavProps) { className={`${styles.navContainer} rspress-nav px-6 ${ // Only hidden when it's not mobile hiddenNav && !isMobile ? styles.hidden : '' - }`} - style={{ - position: isMobile ? 'relative' : 'sticky', - }} + } ${computeNavPosition()}`} >