@@ -38,18 +38,26 @@ interface SearchProps {
3838 }
3939 lane : LaneConfig
4040 } [ ]
41+ verifiers ?: {
42+ id : string
43+ name : string
44+ type : string
45+ logo : string
46+ totalNetworks : number
47+ } [ ]
4148 small ?: boolean
4249 environment : Environment
4350}
4451
45- function Search ( { chains, tokens, small, environment, lanes } : SearchProps ) {
52+ function Search ( { chains, tokens, small, environment, lanes, verifiers = [ ] } : SearchProps ) {
4653 const [ search , setSearch ] = useState ( "" )
4754 const [ debouncedSearch , setDebouncedSearch ] = useState ( "" )
4855 const [ openSearchMenu , setOpenSearchMenu ] = useState ( false )
4956 const [ isActive , setIsActive ] = useState ( false )
5057 const [ networksResults , setNetworksResults ] = useState < typeof chains > ( [ ] )
5158 const [ tokensResults , setTokensResults ] = useState < typeof tokens > ( [ ] )
5259 const [ lanesResults , setLanesResults ] = useState < typeof lanes > ( [ ] )
60+ const [ verifiersResults , setVerifiersResults ] = useState < typeof verifiers > ( [ ] )
5361 const searchRef = useRef < HTMLDivElement > ( null )
5462 const workerRef = useRef < Worker | null > ( null )
5563 const workerReadyRef = useRef ( false )
@@ -59,10 +67,11 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
5967 if ( workerReadyRef . current || typeof window === "undefined" ) return
6068 workerRef . current = new Worker ( new URL ( "~/workers/data-worker.ts" , import . meta. url ) , { type : "module" } )
6169 workerRef . current . onmessage = ( event : MessageEvent < WorkerResponse > ) => {
62- const { networks, tokens : workerTokens , lanes : workerLanes } = event . data
70+ const { networks, tokens : workerTokens , lanes : workerLanes , verifiers : workerVerifiers } = event . data
6371 setNetworksResults ( networks || [ ] )
6472 setTokensResults ( workerTokens || [ ] )
6573 setLanesResults ( workerLanes || [ ] )
74+ setVerifiersResults ( workerVerifiers || [ ] )
6675 }
6776 workerReadyRef . current = true
6877 }
@@ -90,6 +99,7 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
9099 setNetworksResults ( [ ] )
91100 setTokensResults ( [ ] )
92101 setLanesResults ( [ ] )
102+ setVerifiersResults ( [ ] )
93103 return
94104 }
95105
@@ -102,11 +112,12 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
102112 chains,
103113 tokens,
104114 lanes,
115+ verifiers,
105116 } ,
106117 }
107118 workerRef . current . postMessage ( message )
108119 }
109- } , [ debouncedSearch , chains , tokens , lanes ] )
120+ } , [ debouncedSearch , chains , tokens , lanes , verifiers ] )
110121
111122 // Handle menu visibility
112123 useEffect ( ( ) => {
@@ -146,15 +157,15 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
146157 < img src = "/assets/icons/search.svg" alt = "Search icon" />
147158 < input
148159 type = "search"
149- placeholder = "Network/Token/Lane"
160+ placeholder = "Network/Token/Lane/Verifier "
150161 value = { search }
151162 onChange = { ( e ) => setSearch ( e . target . value ) }
152163 onFocus = { ( ) => {
153164 setIsActive ( true )
154165 ensureWorker ( )
155166 } }
156167 onBlur = { ( ) => setIsActive ( false ) }
157- aria-label = "Search networks, tokens, and lanes "
168+ aria-label = "Search networks, tokens, lanes, and verifiers "
158169 aria-describedby = { openSearchMenu ? "search-results" : undefined }
159170 />
160171 { openSearchMenu && (
@@ -167,9 +178,12 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
167178 aria-live = "polite"
168179 aria-label = "Search results"
169180 >
170- { networksResults . length === 0 && tokensResults . length === 0 && (
171- < span className = "ccip-hero__search-results__no-result" > No results found</ span >
172- ) }
181+ { networksResults . length === 0 &&
182+ tokensResults . length === 0 &&
183+ lanesResults . length === 0 &&
184+ verifiersResults . length === 0 && (
185+ < span className = "ccip-hero__search-results__no-result" > No results found</ span >
186+ ) }
173187 { networksResults . length > 0 && (
174188 < >
175189 < span className = "ccip-hero__search-results__title" > Networks</ span >
@@ -284,6 +298,36 @@ function Search({ chains, tokens, small, environment, lanes }: SearchProps) {
284298 </ ul >
285299 </ >
286300 ) }
301+
302+ { verifiersResults . length > 0 && (
303+ < >
304+ < span className = "ccip-hero__search-results__title" > Verifiers</ span >
305+ < ul aria-label = "Verifiers" >
306+ { verifiersResults . map ( ( verifier ) => (
307+ < li key = { verifier . id } >
308+ < a href = { `/ccip/directory/${ environment } /verifiers#${ verifier . id } ` } >
309+ < img
310+ src = { verifier . logo }
311+ alt = { `${ verifier . name } verifier logo` }
312+ loading = "lazy"
313+ onError = { ( { currentTarget } ) => {
314+ currentTarget . onerror = null // prevents looping
315+ currentTarget . src = fallbackTokenIconUrl
316+ } }
317+ />
318+ { verifier . name }
319+ { ! small && (
320+ < span >
321+ { verifier . totalNetworks } { verifier . totalNetworks > 1 ? "networks" : "network" } |{ " " }
322+ { verifier . type }
323+ </ span >
324+ ) }
325+ </ a >
326+ </ li >
327+ ) ) }
328+ </ ul >
329+ </ >
330+ ) }
287331 </ div >
288332 ) }
289333 </ div >
0 commit comments