Skip to content

Commit dda4d82

Browse files
DAEKYU YOONDAEKYU YOON
authored andcommitted
Fix search modal target after client-side navigation
1 parent 56da597 commit dda4d82

1 file changed

Lines changed: 56 additions & 31 deletions

File tree

src/components/PageSearch.astro

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,32 @@
33
import Default from '@astrojs/starlight/components/Search.astro';
44
---
55

6-
<button
7-
aria-label="Search"
8-
class="page-search-button"
9-
title="Search (Ctrl+K)"
10-
type="button"
11-
>
12-
<svg
13-
xmlns="http://www.w3.org/2000/svg"
14-
width="18"
15-
height="18"
16-
viewBox="0 0 24 24"
17-
fill="none"
18-
stroke="currentColor"
19-
stroke-width="2"
20-
stroke-linecap="round"
21-
stroke-linejoin="round"
6+
<div data-page-search>
7+
<button
8+
aria-label="Search"
9+
class="page-search-button"
10+
title="Search (Ctrl+K)"
11+
type="button"
2212
>
23-
<circle cx="11" cy="11" r="8"></circle>
24-
<path d="m21 21-4.35-4.35"></path>
25-
</svg>
26-
<span class="sr-only">Search</span>
27-
</button>
28-
29-
<Default />
13+
<svg
14+
xmlns="http://www.w3.org/2000/svg"
15+
width="18"
16+
height="18"
17+
viewBox="0 0 24 24"
18+
fill="none"
19+
stroke="currentColor"
20+
stroke-width="2"
21+
stroke-linecap="round"
22+
stroke-linejoin="round"
23+
>
24+
<circle cx="11" cy="11" r="8"></circle>
25+
<path d="m21 21-4.35-4.35"></path>
26+
</svg>
27+
<span class="sr-only">Search</span>
28+
</button>
29+
30+
<Default />
31+
</div>
3032

3133
<style>
3234
:global(site-search button[data-open-modal]),
@@ -126,12 +128,29 @@ import Default from '@astrojs/starlight/components/Search.astro';
126128
min-height: 16px !important;
127129
}
128130
}
131+
132+
[data-page-search] {
133+
display: contents;
134+
}
129135
</style>
130136

131137
<script>
132138
const pageSearchInitKey = '__pageSearchDelegated';
133139

134-
function findNativeSearchButton() {
140+
function findNativeSearchButton(sourceButton) {
141+
const scopedRoot = sourceButton?.closest('[data-page-search]');
142+
if (scopedRoot instanceof HTMLElement) {
143+
const scoped = scopedRoot.querySelector(
144+
'site-search button[data-open-modal], button[data-open-modal], .sl-search-button'
145+
);
146+
if (
147+
scoped instanceof HTMLElement &&
148+
!scoped.classList.contains('page-search-button')
149+
) {
150+
return scoped;
151+
}
152+
}
153+
135154
const selectors = [
136155
'site-search button[data-open-modal]',
137156
'button[data-open-modal]',
@@ -140,17 +159,23 @@ import Default from '@astrojs/starlight/components/Search.astro';
140159
];
141160

142161
for (const selector of selectors) {
143-
const candidate = document.querySelector(selector);
144-
if (!(candidate instanceof HTMLElement)) continue;
145-
if (candidate.classList.contains('page-search-button')) continue;
146-
return candidate;
162+
const candidates = Array.from(document.querySelectorAll(selector))
163+
.filter(
164+
(candidate) =>
165+
candidate instanceof HTMLElement &&
166+
!candidate.classList.contains('page-search-button')
167+
);
168+
const latest = candidates.at(-1);
169+
if (latest instanceof HTMLElement) {
170+
return latest;
171+
}
147172
}
148173

149174
return null;
150175
}
151176

152-
function triggerSearch() {
153-
const nativeButton = findNativeSearchButton();
177+
function triggerSearch(sourceButton) {
178+
const nativeButton = findNativeSearchButton(sourceButton);
154179
if (nativeButton && typeof nativeButton.click === 'function') {
155180
nativeButton.click();
156181
return;
@@ -195,7 +220,7 @@ import Default from '@astrojs/starlight/components/Search.astro';
195220

196221
e.preventDefault();
197222
e.stopPropagation();
198-
triggerSearch();
223+
triggerSearch(pageSearchButton);
199224
});
200225

201226
window[pageSearchInitKey] = true;

0 commit comments

Comments
 (0)