mirror of
https://github.com/quartz-community/search.git
synced 2026-07-22 02:50:25 +00:00
fix: resolve callout z-index overlay and scroll-to-term across element boundaries
- Set sidebar z-index to auto when search opens to break stacking context that trapped the fixed search modal behind page content - Rewrite scroll-to-search-term to search textContent of block-level elements and walk text nodes to build cross-element Range, handling terms that span multiple inline elements
This commit is contained in:
parent
871c7aafb9
commit
14b1e9e7e4
5 changed files with 48 additions and 14 deletions
2
dist/components/index.js
vendored
2
dist/components/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/components/index.js.map
vendored
2
dist/components/index.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js
vendored
2
dist/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
vendored
2
dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -150,6 +150,7 @@ async function setupSearch() {
|
|||
|
||||
if (!container || !searchButton || !searchBar || !searchLayout) continue;
|
||||
|
||||
const sidebar = container.closest(".sidebar") as HTMLElement | null;
|
||||
const enablePreview = searchLayout.getAttribute("data-preview") === "true";
|
||||
const fieldPriorityAttr = searchLayout.getAttribute("data-field-priority");
|
||||
const fieldPriority: string[] = fieldPriorityAttr
|
||||
|
|
@ -280,6 +281,7 @@ async function setupSearch() {
|
|||
|
||||
const hideSearch = () => {
|
||||
container.classList.remove("active");
|
||||
if (sidebar) sidebar.style.zIndex = "";
|
||||
searchButton.setAttribute("aria-expanded", "false");
|
||||
searchBar.value = "";
|
||||
removeAllChildren(results!);
|
||||
|
|
@ -293,6 +295,7 @@ async function setupSearch() {
|
|||
|
||||
const showSearch = (type: SearchType) => {
|
||||
searchType = type;
|
||||
if (sidebar) sidebar.style.zIndex = "auto";
|
||||
container.classList.add("active");
|
||||
searchButton.setAttribute("aria-expanded", "true");
|
||||
searchBar.focus();
|
||||
|
|
@ -823,17 +826,46 @@ function scrollToSearchTerm() {
|
|||
sessionStorage.removeItem("search-term");
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
const contentEl =
|
||||
document.querySelector(".popover-hint") ?? document.querySelector("article") ?? document.body;
|
||||
const walker = document.createTreeWalker(contentEl, NodeFilter.SHOW_TEXT);
|
||||
let node: Text | null;
|
||||
while ((node = walker.nextNode() as Text | null)) {
|
||||
const text = node.nodeValue ?? "";
|
||||
const candidates = document.querySelectorAll(
|
||||
".popover-hint p, .popover-hint li, .popover-hint h1, .popover-hint h2, " +
|
||||
".popover-hint h3, .popover-hint h4, .popover-hint h5, .popover-hint h6, " +
|
||||
".popover-hint td, .popover-hint th, .popover-hint blockquote, " +
|
||||
"article p, article li, article h1, article h2, article h3",
|
||||
);
|
||||
|
||||
for (const el of Array.from(candidates)) {
|
||||
const text = el.textContent ?? "";
|
||||
const idx = text.toLowerCase().indexOf(term.toLowerCase());
|
||||
if (idx !== -1) {
|
||||
if (idx === -1) continue;
|
||||
|
||||
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
||||
let charCount = 0;
|
||||
let node: Text | null;
|
||||
let startNode: Text | null = null;
|
||||
let startOffset = 0;
|
||||
let endNode: Text | null = null;
|
||||
let endOffset = 0;
|
||||
|
||||
while ((node = walker.nextNode() as Text | null)) {
|
||||
const len = node.nodeValue?.length ?? 0;
|
||||
if (!startNode && charCount + len > idx) {
|
||||
startNode = node;
|
||||
startOffset = idx - charCount;
|
||||
}
|
||||
if (startNode && charCount + len >= idx + term.length) {
|
||||
endNode = node;
|
||||
endOffset = idx + term.length - charCount;
|
||||
break;
|
||||
}
|
||||
charCount += len;
|
||||
}
|
||||
|
||||
if (!startNode || !endNode) continue;
|
||||
|
||||
try {
|
||||
const range = document.createRange();
|
||||
range.setStart(node, idx);
|
||||
range.setEnd(node, idx + term.length);
|
||||
range.setStart(startNode, startOffset);
|
||||
range.setEnd(endNode, endOffset);
|
||||
const span = document.createElement("span");
|
||||
span.className = "search-scroll-target";
|
||||
range.surroundContents(span);
|
||||
|
|
@ -848,8 +880,10 @@ function scrollToSearchTerm() {
|
|||
}
|
||||
}, 1000);
|
||||
}, 2000);
|
||||
break;
|
||||
} catch {
|
||||
el.scrollIntoView({ block: "center", behavior: "smooth" });
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue