mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
fix(docs): restore search overlay behavior (#134)
This commit is contained in:
parent
6a60977eb5
commit
611f830fe0
5 changed files with 85 additions and 4 deletions
4
docs-site/app/api/search/route.ts
Normal file
4
docs-site/app/api/search/route.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { source } from "@/lib/source";
|
||||
import { createFromSource } from "fumadocs-core/search/server";
|
||||
|
||||
export const { GET } = createFromSource(source);
|
||||
|
|
@ -69,7 +69,11 @@
|
|||
--color-fd-muted-foreground: #7a8d96;
|
||||
}
|
||||
|
||||
html, body {
|
||||
/* Keep html overflow at the default `visible` so body's overflow
|
||||
propagates to the viewport (per CSS Overflow spec). That lets
|
||||
`react-remove-scroll-bar` lock viewport scroll via body alone while
|
||||
leaving the sticky sidebar placeholder anchored to the viewport. */
|
||||
body {
|
||||
overflow-x: clip;
|
||||
}
|
||||
|
||||
|
|
@ -778,8 +782,8 @@ body::after {
|
|||
mix-blend-mode: overlay;
|
||||
}
|
||||
|
||||
/* Make sure content stays above background */
|
||||
body > * {
|
||||
/* Make sure page content stays above the decorative background. */
|
||||
.ktx-site-shell {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ export default function RootLayout({ children }: { children: ReactNode }) {
|
|||
suppressHydrationWarning
|
||||
>
|
||||
<body>
|
||||
<RootProvider>{children}</RootProvider>
|
||||
<RootProvider search={{ options: { api: "/ktx/api/search" } }}>
|
||||
<div className="ktx-site-shell">{children}</div>
|
||||
</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -111,3 +111,21 @@ test("/ktx/docs redirects to the docs introduction", async () => {
|
|||
`${docsBasePath}/docs/getting-started/introduction`,
|
||||
);
|
||||
});
|
||||
|
||||
test("/ktx/api/search returns docs search results", async () => {
|
||||
const response = await fetch(
|
||||
`${docsSiteUrl}${docsBasePath}/api/search?query=setup`,
|
||||
);
|
||||
|
||||
assert.equal(response.status, 200);
|
||||
|
||||
const results = await response.json();
|
||||
assert.ok(Array.isArray(results), "search response should be an array");
|
||||
assert.ok(
|
||||
results.some(
|
||||
(result) =>
|
||||
typeof result.url === "string" && result.url.startsWith("/docs/"),
|
||||
),
|
||||
"search should return at least one docs result",
|
||||
);
|
||||
});
|
||||
|
|
|
|||
53
docs-site/tests/docs-search-behavior.test.mjs
Normal file
53
docs-site/tests/docs-search-behavior.test.mjs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { test } from "node:test";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const docsSiteDir = join(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
|
||||
async function readDocsFile(path) {
|
||||
return readFile(join(docsSiteDir, path), "utf8");
|
||||
}
|
||||
|
||||
test("root provider uses the base-path-aware search API", async () => {
|
||||
const layout = await readDocsFile("app/layout.tsx");
|
||||
|
||||
assert.match(layout, /search=\{\{/);
|
||||
assert.match(layout, /api:\s*"\/ktx\/api\/search"/);
|
||||
});
|
||||
|
||||
test("site background stacking does not target every body child", async () => {
|
||||
const css = await readDocsFile("app/global.css");
|
||||
|
||||
assert.doesNotMatch(css, /body\s*>\s*\*\s*\{[^}]*z-index/s);
|
||||
assert.match(css, /\.ktx-site-shell\s*\{[^}]*z-index:\s*2/s);
|
||||
});
|
||||
|
||||
test("search lock relies on body overflow propagation, not html or sidebar overrides", async () => {
|
||||
const css = await readDocsFile("app/global.css");
|
||||
|
||||
// Body still clips horizontal overflow defensively.
|
||||
assert.match(css, /(^|\s)body\s*\{[^}]*overflow-x:\s*clip/s);
|
||||
|
||||
// html must keep its default `visible` overflow so body's lock
|
||||
// (`overflow: hidden` from react-remove-scroll-bar) propagates to the
|
||||
// viewport. Locking html directly breaks `position: sticky` on the
|
||||
// sidebar placeholder.
|
||||
assert.doesNotMatch(css, /(^|\s)html\s*,?\s*\{[^}]*overflow(-y|\s*:)\s*(hidden|clip)/s);
|
||||
assert.doesNotMatch(
|
||||
css,
|
||||
/html:has\(body\[data-scroll-locked\]\)[^{]*\{[^}]*overflow:\s*(hidden|clip)/s,
|
||||
);
|
||||
|
||||
// No site-specific overrides to body's data-scroll-locked overflow or
|
||||
// to the sidebar placeholder when locked.
|
||||
assert.doesNotMatch(
|
||||
css,
|
||||
/html\s+body\[data-scroll-locked\][^{]*\{[^}]*overflow:/s,
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
css,
|
||||
/body\[data-scroll-locked\]\s+\[data-sidebar-placeholder\][^{]*\{[^}]*position:\s*fixed/s,
|
||||
);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue