diff --git a/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearch.tsx b/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearch.tsx index 702c55fda..3df7eeed8 100644 --- a/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearch.tsx +++ b/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearch.tsx @@ -18,7 +18,7 @@ import { useIsWithinMaxBreakpoint, } from '@elastic/eui' import { css } from '@emotion/react' -import { useRef, useState } from 'react' +import { useRef, useState, useEffect } from 'react' export const NavigationSearch = () => { const { euiTheme } = useEuiTheme() @@ -35,8 +35,7 @@ export const NavigationSearch = () => { const isSearching = isLoading || isFetching const handleResultClick = () => { - setIsPopoverOpen(false) - inputRef.current?.blur() + // Handled by htmx event listeners } const { @@ -85,6 +84,28 @@ export const NavigationSearch = () => { inputRef.current?.select() }) + // Close popover and blur input when htmx navigation starts from a search result + useEffect(() => { + const handleBeforeSend = (event: CustomEvent) => { + const trigger = event.detail?.elt as HTMLElement | undefined + if (trigger?.hasAttribute('data-search-result-index')) { + setIsPopoverOpen(false) + inputRef.current?.blur() + } + } + + document.addEventListener( + 'htmx:beforeSend', + handleBeforeSend as EventListener + ) + return () => { + document.removeEventListener( + 'htmx:beforeSend', + handleBeforeSend as EventListener + ) + } + }, [inputRef]) + return (
{ `} > setIsPopoverOpen(false)} ownFocus={false} disableFocusTrap={true} @@ -104,6 +125,9 @@ export const NavigationSearch = () => { panelProps={{ css: css` border-radius: ${euiTheme.size.s}; + visibility: ${isPopoverOpen ? 'visible' : 'hidden'}; + opacity: ${isPopoverOpen ? 1 : 0}; + pointer-events: ${isPopoverOpen ? 'auto' : 'none'}; `, onMouseDown: (e: React.MouseEvent) => { // Prevent input blur when clicking anywhere inside the popover panel @@ -117,7 +141,6 @@ export const NavigationSearch = () => { value={searchTerm} onChange={handleChange} onFocus={() => { - // Solo abrir el popover si hay contenido Y el usuario está interactuando if (hasContent) { setIsPopoverOpen(true) } diff --git a/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx b/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx index 2769ea435..655083d24 100644 --- a/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx +++ b/src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx @@ -193,11 +193,12 @@ const SearchResultRow = ({ return [typePrefix, ...result.parents.slice(1).map((p) => p.title)] }, [result.type, result.parents]) - const hxSelectOob = getHxSelectOob(result.url, currentPathname) - // Process htmx when element mounts or when pathname changes useEffect(() => { if (anchorRef.current) { + const hxSelectOob = getHxSelectOob(result.url, currentPathname) + anchorRef.current.setAttribute('hx-select-oob', hxSelectOob) + anchorRef.current.setAttribute('hx-swap', 'none') htmx.process(anchorRef.current) } }, [result.url, currentPathname]) @@ -206,7 +207,6 @@ const SearchResultRow = ({ hasSameTopLevelGroup ? "#content-container,#toc-nav" : "#main-container"; + public static string GetHxSelectOob(bool hasSameTopLevelGroup) => hasSameTopLevelGroup ? "#content-container,#toc-nav" : "#content-container,#toc-nav,#nav-tree,#nav-dropdown"; public const string Preload = "mousedown"; public static string GetHxAttributes( diff --git a/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs b/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs index 142f453f5..089a5724e 100644 --- a/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs +++ b/tests/Elastic.Markdown.Tests/Inline/InlineLinkTests.cs @@ -48,7 +48,7 @@ public class InlineLinkTests(ITestOutputHelper output) : LinkTestBase(output, [Fact] public void GeneratesHtml() => Html.ShouldContainHtml( - """

Elasticsearch

""" + """

Elasticsearch

""" ); [Fact] @@ -150,7 +150,7 @@ Go to [test](kibana://index.md) public void GeneratesHtml() => // language=html Html.Should().Contain( - """

Go to test

""" + """

Go to test

""" ); [Fact] @@ -175,7 +175,7 @@ Go to [](kibana://index.md) public void GeneratesHtml() => // language=html - empty crosslinks now emit an error Html.Should().Contain( - """

Go to

""" + """

Go to

""" ); [Fact] @@ -203,7 +203,7 @@ Go to [](kibana://get-started/index.md) public void GeneratesHtml() => // language=html - empty crosslinks emit an error Html.Should().Contain( - """

Go to

""" + """

Go to

""" ); [Fact]