mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix(docs): keep the nav within the viewport on tablets and laptops (#570)
The custom nav cluster (theme toggle + Fund + GitHub Star) rendered inline at every width, overriding VitePress's responsive collapse: a horizontal scrollbar at 768-959px and off-screen clipping of the buttons on 1280-1366px laptops. Show the custom cluster only at >=1440px where it fits, defer to VitePress's native nav below that, anchor the flyout menu to the start edge in RTL, and drop the redundant "Home" nav link so the nav fits at 768px. Closes #556
This commit is contained in:
@@ -25,7 +25,6 @@ function prefixLinks(items: any[], locale: string): any[] {
|
||||
// with no mapping (e.g. the version item) pass through unchanged. The nav is a
|
||||
// flat list, so no recursion is needed here.
|
||||
const NAV_KEY: Record<string, string> = {
|
||||
Home: "nav.home",
|
||||
Guide: "nav.guide",
|
||||
Tools: "nav.tools",
|
||||
"API Reference": "nav.apiReference",
|
||||
@@ -286,7 +285,9 @@ function buildBaseTheme() {
|
||||
logo: "/logo.png",
|
||||
|
||||
nav: [
|
||||
{ text: "Home", link: "/" },
|
||||
// No "Home" item: the logo already links home, and dropping it keeps the
|
||||
// nav within the viewport at 768px (see github-stars.css for the wider
|
||||
// responsive-nav fix).
|
||||
{ text: "Guide", link: "/guide/getting-started" },
|
||||
{ text: "Tools", link: "/tools/image/resize" },
|
||||
{ text: "API Reference", link: "/api/rest" },
|
||||
|
||||
@@ -1,19 +1,40 @@
|
||||
/* Hide the three-dots extra menu - its contents are now in the navbar directly */
|
||||
.VPNavBarExtra {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Also hide the default appearance toggle since we render our own */
|
||||
.VPNavBarAppearance {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Right side of navbar: toggle + GitHub button */
|
||||
/* Right-side custom nav cluster: our own appearance toggle + Fund + GitHub Star.
|
||||
VitePress's default theme collapses appearance/social/translations into a
|
||||
compact three-dots flyout below 1280px and shows them inline at >=1280px, so
|
||||
the stock nav never overflows. Our cluster is wider than that native inline
|
||||
set, so forcing it inline at every width pushed the nav past the viewport: a
|
||||
horizontal page scrollbar in the 768-959px band (the nav is in normal flow
|
||||
there) and off-screen clipping of the buttons on 1280-1366px laptops (the nav
|
||||
is position:fixed at >=960px, so it clips instead of scrolling). Fix: show our
|
||||
cluster only once the layout reaches its max width (1440px), where it fits, and
|
||||
defer to VitePress's native responsive nav below that (three-dots flyout under
|
||||
1280px, inline appearance + social from 1280-1439px). */
|
||||
.nav-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-left: 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
.nav-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
/* Our cluster carries the appearance toggle at this width, so hide VitePress's
|
||||
own inline toggle to avoid a duplicate. */
|
||||
.VPNavBarAppearance {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* VitePress anchors flyout dropdowns with a physical `right: 0`, which does not
|
||||
flip for RTL. In RTL the three-dots menu then opens off-screen to the left and
|
||||
adds horizontal overflow even while closed (it is position:absolute). Anchor it
|
||||
to the start edge so it opens inward instead. */
|
||||
:root[dir="rtl"] .VPNavBarExtra .menu {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* GitHub button group */
|
||||
@@ -118,11 +139,3 @@
|
||||
background: rgba(244, 114, 182, 0.15);
|
||||
border-color: rgba(244, 114, 182, 0.4);
|
||||
}
|
||||
|
||||
/* Hide stars and fund button on small screens, keep toggle */
|
||||
@media (max-width: 640px) {
|
||||
.github-btn-wrapper,
|
||||
.fund-btn {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,11 @@ test.describe("Theme Toggle", () => {
|
||||
const html = page.locator("html");
|
||||
const wasDark = ((await html.getAttribute("class")) ?? "").includes("dark");
|
||||
|
||||
// Click the visible toggle inside our custom nav area (the hidden default
|
||||
// VPNavBarAppearance is first in DOM order, so a bare querySelector would
|
||||
// hit it instead).
|
||||
await page.locator('.nav-bar-right button[role="switch"]').click();
|
||||
// Click whichever theme toggle is actually visible at this viewport: below
|
||||
// 1440px the nav uses VitePress's native inline toggle, at >=1440px our
|
||||
// custom cluster toggle takes over. Filtering to :visible skips the hidden
|
||||
// duplicates that sit earlier in DOM order.
|
||||
await page.locator('button[role="switch"]:visible').first().click();
|
||||
|
||||
// Assert the dark class actually toggled
|
||||
if (wasDark) {
|
||||
@@ -57,6 +58,11 @@ test.describe("Theme Toggle", () => {
|
||||
});
|
||||
|
||||
test.describe("GitHub Stars Component", () => {
|
||||
// The custom nav cluster (toggle + Fund + GitHub Star) only renders at
|
||||
// >=1440px, where it fits without overflowing the nav. Below that the nav
|
||||
// defers to VitePress's native responsive layout, so pin a wide desktop here.
|
||||
test.use({ viewport: { width: 1500, height: 900 } });
|
||||
|
||||
test("GitHub star button is visible in navbar", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const githubBtn = page.locator(".github-btn, .github-btn-wrapper").first();
|
||||
@@ -70,3 +76,22 @@ test.describe("GitHub Stars Component", () => {
|
||||
await expect(starLink).toHaveAttribute("target", "_blank");
|
||||
});
|
||||
});
|
||||
|
||||
// Regression guard for the nav overflow reported in #556. The custom nav cluster
|
||||
// used to render inline at every width, pushing the nav past narrow viewports
|
||||
// (a horizontal scrollbar at 768-959px, off-screen clipping at 1280-1366px).
|
||||
test.describe("Nav has no horizontal overflow", () => {
|
||||
for (const width of [768, 834, 900, 1024, 1280, 1366]) {
|
||||
test(`no horizontal scroll at ${width}px`, async ({ page }) => {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
await page.goto("/guide/getting-started");
|
||||
await waitForHydration(page);
|
||||
const overflow = await page.evaluate(() => {
|
||||
const de = document.documentElement;
|
||||
return de.scrollWidth - de.clientWidth;
|
||||
});
|
||||
// Allow a 1px sub-pixel rounding margin; the bug produced 300px+ scroll.
|
||||
expect(overflow).toBeLessThanOrEqual(1);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user