@@ -18,6 +18,7 @@ import {
1818 Stack ,
1919 Table ,
2020 Text ,
21+ TextInput ,
2122 Title ,
2223 Tooltip ,
2324} from "@mantine/core" ;
@@ -28,8 +29,10 @@ import {
2829 IconGraph ,
2930 IconLayoutGrid ,
3031 IconList ,
32+ IconSearch ,
3133 IconTable ,
3234 IconToggleLeft ,
35+ IconX ,
3336} from "@tabler/icons-react" ;
3437import { useQuery , useQueryClient } from "@tanstack/react-query" ;
3538import { createLazyFileRoute , useSearch } from "@tanstack/react-router" ;
@@ -212,6 +215,9 @@ const SearchPage = () => {
212215 // Entity type filter state
213216 const [ selectedTypes , setSelectedTypes ] = useState < string [ ] > ( [ ] ) ;
214217
218+ // Search within results refinement state
219+ const [ refinementQuery , setRefinementQuery ] = useState < string > ( "" ) ;
220+
215221 // Search duration tracking
216222 const [ searchStartTime , setSearchStartTime ] = useState < number > ( 0 ) ;
217223 const [ searchDuration , setSearchDuration ] = useState < number > ( 0 ) ;
@@ -449,12 +455,28 @@ const SearchPage = () => {
449455 const hasResults = searchResults && searchResults . length > 0 ;
450456 const hasQuery = Boolean ( searchFilters . query . trim ( ) ) ;
451457
452- // Filter results by selected entity types
458+ // Filter results by selected entity types and refinement query
453459 const filteredResults = useMemo ( ( ) => {
454460 if ( ! searchResults ) return [ ] ;
455- if ( selectedTypes . length === 0 ) return searchResults ;
456- return searchResults . filter ( result => selectedTypes . includes ( result . entity_type ) ) ;
457- } , [ searchResults , selectedTypes ] ) ;
461+
462+ let results = searchResults ;
463+
464+ // Filter by entity type
465+ if ( selectedTypes . length > 0 ) {
466+ results = results . filter ( result => selectedTypes . includes ( result . entity_type ) ) ;
467+ }
468+
469+ // Filter by refinement query (search within results)
470+ if ( refinementQuery . trim ( ) ) {
471+ const query = refinementQuery . toLowerCase ( ) ;
472+ results = results . filter ( result =>
473+ result . display_name . toLowerCase ( ) . includes ( query ) ||
474+ ( result . id && result . id . toLowerCase ( ) . includes ( query ) )
475+ ) ;
476+ }
477+
478+ return results ;
479+ } , [ searchResults , selectedTypes , refinementQuery ] ) ;
458480
459481 // Sort and filter results by selected sort option
460482 const sortedResults = useMemo ( ( ) => {
@@ -891,6 +913,37 @@ const SearchPage = () => {
891913 placeholder = "Search for works, authors, institutions, topics... e.g. 'machine learning', 'Marie Curie', 'MIT'"
892914 />
893915
916+ { /* Search Within Results Refinement */ }
917+ { hasQuery && hasResults && (
918+ < Card padding = "sm" radius = "sm" style = { { border : BORDER_STYLE_GRAY_3 } } >
919+ < TextInput
920+ placeholder = "Search within results..."
921+ value = { refinementQuery }
922+ onChange = { ( e ) => setRefinementQuery ( e . currentTarget . value ) }
923+ leftSection = { < IconSearch size = { ICON_SIZE . SM } /> }
924+ rightSection = {
925+ refinementQuery && (
926+ < ActionIcon
927+ size = "sm"
928+ variant = "transparent"
929+ color = "gray"
930+ onClick = { ( ) => setRefinementQuery ( '' ) }
931+ aria-label = "Clear refinement"
932+ >
933+ < IconX size = { ICON_SIZE . XS } />
934+ </ ActionIcon >
935+ )
936+ }
937+ size = "sm"
938+ />
939+ { refinementQuery && (
940+ < Text size = "xs" c = "dimmed" mt = "xs" >
941+ Filtering { sortedResults . length } of { searchResults . length } results by "{ refinementQuery } "
942+ </ Text >
943+ ) }
944+ </ Card >
945+ ) }
946+
894947 { hasQuery && < Card style = { { border : BORDER_STYLE_GRAY_3 } } > { renderSearchResults ( ) } </ Card > }
895948
896949 { ! hasQuery && renderEmptyState ( handleQuickSearch ) }
0 commit comments