1- import { useClickOutside , useDebounce } from '@react-hooks-library/core'
1+ import {
2+ useClickOutside ,
3+ useDebounce ,
4+ useKeyDown ,
5+ } from '@react-hooks-library/core'
26import {
37 Card ,
48 CaretRightIcon ,
59 EmptyState ,
610 Flex ,
7- Input ,
8- MagnifyingGlassIcon ,
11+ SearchIcon ,
912 Spinner ,
1013} from '@pluralsh/design-system'
1114import { RunStatusIcon } from 'components/ai/agent-runs/AgentRunInfoDisplays'
1215import { PRsModalIcon } from 'components/ai/agent-runs/AIAgentRunsTableCols'
1316import { GqlError } from 'components/utils/Alert'
17+ import { ExpandedInput , IconExpander } from 'components/utils/IconExpander'
1418import { WorkbenchStoredPromptMarkdown } from 'components/workbenches/workbench/WorkbenchStoredPromptMarkdown'
1519import {
1620 PullRequestBasicFragment ,
@@ -26,14 +30,15 @@ import { isNonNullable } from 'utils/isNonNullable'
2630import { JobConclusionIcon } from './WorkbenchJobsTable'
2731
2832const SEARCH_LIMIT = 20
33+ const INPUT_WIDTH = 520
2934
3035export function WorkbenchJobsSearch ( { workbenchId } : { workbenchId : string } ) {
3136 const ref = useRef < HTMLDivElement > ( null )
3237 const [ query , setQuery ] = useState ( '' )
33- const [ open , setOpen ] = useState ( false )
38+ const [ dropdownOpen , setDropdownOpen ] = useState ( false )
3439 const debouncedQuery = useDebounce ( query , 200 )
3540 const trimmedQuery = debouncedQuery . trim ( )
36- const showDropdown = open && trimmedQuery . length > 0
41+ const showDropdown = dropdownOpen && trimmedQuery . length > 0
3742
3843 const { data, loading, error } = useWorkbenchJobSearchQuery ( {
3944 variables : { workbenchId, q : trimmedQuery , limit : SEARCH_LIMIT } ,
@@ -46,22 +51,36 @@ export function WorkbenchJobsSearch({ workbenchId }: { workbenchId: string }) {
4651 [ data ?. workbenchJobSearch ]
4752 )
4853
49- useClickOutside ( ref , ( ) => setOpen ( false ) )
54+ const clearSearch = ( ) => {
55+ setQuery ( '' )
56+ setDropdownOpen ( false )
57+ }
58+
59+ const closeDropdown = ( ) => setDropdownOpen ( false )
60+
61+ useClickOutside ( ref , closeDropdown )
62+
63+ useKeyDown ( [ 'Escape' ] , clearSearch )
5064
5165 return (
5266 < SearchWrapperSC ref = { ref } >
53- < Input
54- value = { query }
55- onChange = { ( e ) => {
56- setQuery ( e . currentTarget . value )
57- setOpen ( true )
58- } }
59- onFocus = { ( ) => setOpen ( true ) }
60- placeholder = "Search jobs"
61- startIcon = { < MagnifyingGlassIcon color = "icon-light" /> }
62- showClearButton
63- width = "100%"
64- />
67+ < IconExpander
68+ tooltip = "Search jobs"
69+ icon = { < SearchIcon /> }
70+ active = { ! ! query }
71+ onClear = { clearSearch }
72+ >
73+ < ExpandedInput
74+ width = { INPUT_WIDTH }
75+ inputValue = { query }
76+ onChange = { ( value ) => {
77+ setQuery ( value )
78+ setDropdownOpen ( true )
79+ } }
80+ onFocus = { ( ) => setDropdownOpen ( true ) }
81+ placeholder = "Search jobs"
82+ />
83+ </ IconExpander >
6584 { showDropdown && (
6685 < DropdownSC
6786 fillLevel = { 1 }
@@ -92,7 +111,7 @@ export function WorkbenchJobsSearch({ workbenchId }: { workbenchId: string }) {
92111 key = { result . id }
93112 result = { result }
94113 workbenchId = { workbenchId }
95- onNavigate = { ( ) => setOpen ( false ) }
114+ onNavigate = { closeDropdown }
96115 />
97116 ) ) }
98117 </ ResultsListSC >
@@ -168,15 +187,14 @@ function WorkbenchJobSearchResultRow({
168187
169188const SearchWrapperSC = styled . div ( {
170189 position : 'relative' ,
171- width : '100%' ,
172- maxWidth : 480 ,
190+ display : 'inline-block' ,
173191} )
174192
175193const DropdownSC = styled ( Card ) ( ( { theme } ) => ( {
176194 position : 'absolute' ,
177195 top : `calc(100% + ${ theme . spacing . xsmall } px)` ,
178196 left : 0 ,
179- right : 0 ,
197+ width : '100%' ,
180198 zIndex : theme . zIndexes . modal ,
181199 maxHeight : 360 ,
182200 overflow : 'hidden' ,
0 commit comments