@@ -11,6 +11,45 @@ import styles from './index.module.css';
1111import useOrama from '../../hooks/useOrama.mjs' ;
1212import { relativeOrAbsolute } from '../../utils/relativeOrAbsolute.mjs' ;
1313
14+ /**
15+ * Dismisses the search modal the clicked hit sits in
16+ *
17+ * @param {MouseEvent } event
18+ */
19+ const followSearchHit = event => {
20+ if ( event . ctrlKey || event . metaKey || event . shiftKey || event . altKey ) {
21+ return ;
22+ }
23+
24+ const target = new URL ( event . currentTarget . href ) ;
25+
26+ event . preventDefault ( ) ;
27+
28+ // Escape is the only dismissal `SearchModal` exposes to the hits it renders.
29+ event . currentTarget . dispatchEvent (
30+ new KeyboardEvent ( 'keydown' , { key : 'Escape' , bubbles : true } )
31+ ) ;
32+
33+ requestAnimationFrame ( ( ) => {
34+ if ( target . pathname !== window . location . pathname ) {
35+ window . location . href = target . href ;
36+ return ;
37+ }
38+
39+ requestAnimationFrame ( ( ) =>
40+ document
41+ . getElementById ( decodeURIComponent ( target . hash . slice ( 1 ) ) )
42+ ?. scrollIntoView ( )
43+ ) ;
44+ } ) ;
45+ } ;
46+
47+ /**
48+ * A search hit link that dismisses the modal when followed.
49+ * @param {Object } props - Anchor props, as passed by `SearchHit`.
50+ */
51+ const SearchHitLink = props => < a { ...props } onClick = { followSearchHit } /> ;
52+
1453const SearchBox = ( { pathname } ) => {
1554 const client = useOrama ( pathname ) ;
1655
@@ -21,6 +60,7 @@ const SearchBox = ({ pathname }) => {
2160 noResultsTitle = "No results found for"
2261 onHit = { hit => (
2362 < SearchHit
63+ as = { SearchHitLink }
2464 document = { {
2565 ...hit . document ,
2666 href : relativeOrAbsolute ( hit . document . href , pathname ) ,
0 commit comments