@@ -20,9 +20,10 @@ import {
2020} from "@pythnetwork/component-library/unstyled/ListBox" ;
2121import { useDrawer } from "@pythnetwork/component-library/useDrawer" ;
2222import { useLogger } from "@pythnetwork/component-library/useLogger" ;
23+ import { useDetectBrowserInfo } from '@pythnetwork/react-hooks/use-detect-browser-info' ;
2324import { matchSorter } from "match-sorter" ;
2425import type { ReactNode } from "react" ;
25- import { useCallback , useEffect , useMemo , useState } from "react" ;
26+ import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
2627
2728import { Cluster , ClusterToName } from "../../services/pyth" ;
2829import { AssetClassBadge } from "../AssetClassBadge" ;
@@ -132,10 +133,19 @@ const SearchDialogContents = ({
132133 feeds,
133134 publishers,
134135} : SearchDialogContentsProps ) => {
136+ /** hooks */
135137 const drawer = useDrawer ( ) ;
136138 const logger = useLogger ( ) ;
139+ const browserInfo = useDetectBrowserInfo ( ) ;
140+
141+ /** refs */
142+ const openTabModifierActiveRef = useRef ( false ) ;
143+ const middleMousePressedRef = useRef ( false ) ;
144+
145+ /** state */
137146 const [ search , setSearch ] = useState ( "" ) ;
138147 const [ type , setType ] = useState < ResultType | "" > ( "" ) ;
148+
139149 const closeDrawer = useCallback ( ( ) => {
140150 drawer . close ( ) . catch ( ( error : unknown ) => {
141151 logger . error ( error ) ;
@@ -231,13 +241,29 @@ const SearchDialogContents = ({
231241 : ( result . name ?? result . publisherKey )
232242 }
233243 className = { styles . item ?? "" }
234- onAction = { closeDrawer }
235244 href = {
236245 result . type === ResultType . PriceFeed
237246 ? `/price-feeds/${ encodeURIComponent ( result . symbol ) } `
238247 : `/publishers/${ ClusterToName [ result . cluster ] } /${ encodeURIComponent ( result . publisherKey ) } `
239248 }
240249 data-is-first = { result . id === results [ 0 ] ?. id ? "" : undefined }
250+ onPointerDown = { e => {
251+ middleMousePressedRef . current = e . button === 1 ;
252+ // on press is too abstracted and doesn't give us the native event
253+ // for determining if the user clicked their middle mouse button,
254+ // so we need to use the native onClick directly
255+ middleMousePressedRef . current = e . button === 1 ;
256+ openTabModifierActiveRef . current = ( browserInfo ?. isMacOS && e . metaKey ) ?? e . ctrlKey ;
257+ } }
258+ onPointerUp = { ( ) => {
259+ const userWantsNewTab = middleMousePressedRef . current || openTabModifierActiveRef . current ;
260+
261+ // they want a new tab, the search popover stays open
262+ if ( ! userWantsNewTab ) closeDrawer ( ) ;
263+
264+ middleMousePressedRef . current = false ;
265+ openTabModifierActiveRef . current = false ;
266+ } }
241267 >
242268 < div className = { styles . smallScreen } >
243269 { result . type === ResultType . PriceFeed ? (
0 commit comments