Skip to content

Commit 80f6599

Browse files
authored
Fix HTMX navigation from "Find Pages" dropdown (#2470)
* Attempt to fix htmx linking in find docs This only happens in a production-like environment, hence I need to deploy it to test * Fix tests * Fix htmx navigation from "Find in Docs" popover * Simplify
1 parent 92cd818 commit 80f6599

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearch.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
useIsWithinMaxBreakpoint,
1919
} from '@elastic/eui'
2020
import { css } from '@emotion/react'
21-
import { useRef, useState } from 'react'
21+
import { useRef, useState, useEffect } from 'react'
2222

2323
export const NavigationSearch = () => {
2424
const { euiTheme } = useEuiTheme()
@@ -35,8 +35,7 @@ export const NavigationSearch = () => {
3535
const isSearching = isLoading || isFetching
3636

3737
const handleResultClick = () => {
38-
setIsPopoverOpen(false)
39-
inputRef.current?.blur()
38+
// Handled by htmx event listeners
4039
}
4140

4241
const {
@@ -85,6 +84,28 @@ export const NavigationSearch = () => {
8584
inputRef.current?.select()
8685
})
8786

87+
// Close popover and blur input when htmx navigation starts from a search result
88+
useEffect(() => {
89+
const handleBeforeSend = (event: CustomEvent) => {
90+
const trigger = event.detail?.elt as HTMLElement | undefined
91+
if (trigger?.hasAttribute('data-search-result-index')) {
92+
setIsPopoverOpen(false)
93+
inputRef.current?.blur()
94+
}
95+
}
96+
97+
document.addEventListener(
98+
'htmx:beforeSend',
99+
handleBeforeSend as EventListener
100+
)
101+
return () => {
102+
document.removeEventListener(
103+
'htmx:beforeSend',
104+
handleBeforeSend as EventListener
105+
)
106+
}
107+
}, [inputRef])
108+
88109
return (
89110
<div
90111
className="sticky top-0"
@@ -94,7 +115,7 @@ export const NavigationSearch = () => {
94115
`}
95116
>
96117
<EuiInputPopover
97-
isOpen={isPopoverOpen && hasContent}
118+
isOpen={hasContent}
98119
closePopover={() => setIsPopoverOpen(false)}
99120
ownFocus={false}
100121
disableFocusTrap={true}
@@ -104,6 +125,9 @@ export const NavigationSearch = () => {
104125
panelProps={{
105126
css: css`
106127
border-radius: ${euiTheme.size.s};
128+
visibility: ${isPopoverOpen ? 'visible' : 'hidden'};
129+
opacity: ${isPopoverOpen ? 1 : 0};
130+
pointer-events: ${isPopoverOpen ? 'auto' : 'none'};
107131
`,
108132
onMouseDown: (e: React.MouseEvent) => {
109133
// Prevent input blur when clicking anywhere inside the popover panel
@@ -117,7 +141,6 @@ export const NavigationSearch = () => {
117141
value={searchTerm}
118142
onChange={handleChange}
119143
onFocus={() => {
120-
// Solo abrir el popover si hay contenido Y el usuario está interactuando
121144
if (hasContent) {
122145
setIsPopoverOpen(true)
123146
}

src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,11 +193,12 @@ const SearchResultRow = ({
193193
return [typePrefix, ...result.parents.slice(1).map((p) => p.title)]
194194
}, [result.type, result.parents])
195195

196-
const hxSelectOob = getHxSelectOob(result.url, currentPathname)
197-
198196
// Process htmx when element mounts or when pathname changes
199197
useEffect(() => {
200198
if (anchorRef.current) {
199+
const hxSelectOob = getHxSelectOob(result.url, currentPathname)
200+
anchorRef.current.setAttribute('hx-select-oob', hxSelectOob)
201+
anchorRef.current.setAttribute('hx-swap', 'none')
201202
htmx.process(anchorRef.current)
202203
}
203204
}, [result.url, currentPathname])
@@ -206,7 +207,6 @@ const SearchResultRow = ({
206207
<a
207208
ref={anchorRef}
208209
href={result.url}
209-
hx-select-oob={hxSelectOob}
210210
data-search-result-index={index}
211211
onClick={onClick}
212212
onMouseEnter={onMouseEnter}

src/Elastic.Documentation.Site/Htmx.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Elastic.Documentation.Site;
88

99
public static class Htmx
1010
{
11-
public static string GetHxSelectOob(bool hasSameTopLevelGroup) => hasSameTopLevelGroup ? "#content-container,#toc-nav" : "#main-container";
11+
public static string GetHxSelectOob(bool hasSameTopLevelGroup) => hasSameTopLevelGroup ? "#content-container,#toc-nav" : "#content-container,#toc-nav,#nav-tree,#nav-dropdown";
1212
public const string Preload = "mousedown";
1313

1414
public static string GetHxAttributes(

tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class InlineLinkTests(ITestOutputHelper output) : LinkTestBase(output,
4848
[Fact]
4949
public void GeneratesHtml() =>
5050
Html.ShouldContainHtml(
51-
"""<p><a href="/docs/_static/img/observability.png" hx-get="/docs/_static/img/observability.png" hx-select-oob="#main-container" hx-swap="none" hx-push-url="true" hx-indicator="#htmx-indicator" preload="mousedown">Elasticsearch</a></p>"""
51+
"""<p><a href="/docs/_static/img/observability.png" hx-get="/docs/_static/img/observability.png" hx-select-oob="#content-container,#toc-nav" hx-swap="none" hx-push-url="true" hx-indicator="#htmx-indicator" preload="mousedown">Elasticsearch</a></p>"""
5252
);
5353

5454
[Fact]
@@ -150,7 +150,7 @@ Go to [test](kibana://index.md)
150150
public void GeneratesHtml() =>
151151
// language=html
152152
Html.Should().Contain(
153-
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/" hx-select-oob="#main-container" preload="mousedown">test</a></p>"""
153+
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/" hx-select-oob="#content-container,#toc-nav,#nav-tree,#nav-dropdown" preload="mousedown">test</a></p>"""
154154
);
155155

156156
[Fact]
@@ -175,7 +175,7 @@ Go to [](kibana://index.md)
175175
public void GeneratesHtml() =>
176176
// language=html - empty crosslinks now emit an error
177177
Html.Should().Contain(
178-
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/" hx-select-oob="#main-container" preload="mousedown"></a></p>"""
178+
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/" hx-select-oob="#content-container,#toc-nav,#nav-tree,#nav-dropdown" preload="mousedown"></a></p>"""
179179
);
180180

181181
[Fact]
@@ -203,7 +203,7 @@ Go to [](kibana://get-started/index.md)
203203
public void GeneratesHtml() =>
204204
// language=html - empty crosslinks emit an error
205205
Html.Should().Contain(
206-
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/get-started" hx-select-oob="#main-container" preload="mousedown"></a></p>"""
206+
"""<p>Go to <a href="https://docs-v3-preview.elastic.dev/elastic/kibana/tree/main/get-started" hx-select-oob="#content-container,#toc-nav,#nav-tree,#nav-dropdown" preload="mousedown"></a></p>"""
207207
);
208208

209209
[Fact]

0 commit comments

Comments
 (0)