1
1
import { forwardRef , useLayoutEffect , useMemo , useRef } from 'react' ;
2
+ import { css } from '@emotion/react' ;
2
3
import styled from '@emotion/styled' ;
3
4
4
5
import { Button } from 'sentry/components/core/button' ;
@@ -151,33 +152,43 @@ function SearchIndicator({
151
152
) ;
152
153
}
153
154
154
- const ActionButtons = forwardRef < HTMLDivElement , { trailingItems ?: React . ReactNode } > (
155
- ( { trailingItems = null } , ref ) => {
156
- const { dispatch, handleSearch, disabled, query} = useSearchQueryBuilder ( ) ;
155
+ const ActionButtons = forwardRef <
156
+ HTMLDivElement ,
157
+ { initialQuery : string ; trailingItems ?: React . ReactNode }
158
+ > ( ( { trailingItems = null , initialQuery} , ref ) => {
159
+ const { dispatch, handleSearch, disabled, query} = useSearchQueryBuilder ( ) ;
160
+ const unsubmittedChanges = query !== initialQuery ;
157
161
158
- if ( disabled ) {
159
- return null ;
160
- }
161
-
162
- return (
163
- < ButtonsWrapper ref = { ref } >
164
- { trailingItems }
165
- { query === '' ? null : (
166
- < ActionButton
167
- aria-label = { t ( 'Clear search query' ) }
168
- size = "zero"
169
- icon = { < IconClose /> }
170
- borderless
171
- onClick = { ( ) => {
172
- dispatch ( { type : 'CLEAR' } ) ;
173
- handleSearch ( '' ) ;
174
- } }
175
- />
176
- ) }
177
- </ ButtonsWrapper >
178
- ) ;
162
+ if ( disabled ) {
163
+ return null ;
179
164
}
180
- ) ;
165
+
166
+ return (
167
+ < ButtonsWrapper ref = { ref } >
168
+ { trailingItems }
169
+ { query === '' ? null : (
170
+ < ActionButton
171
+ aria-label = { t ( 'Clear search query' ) }
172
+ size = "zero"
173
+ icon = { < IconClose size = "sm" /> }
174
+ borderless
175
+ onClick = { ( ) => {
176
+ dispatch ( { type : 'CLEAR' } ) ;
177
+ handleSearch ( '' ) ;
178
+ } }
179
+ />
180
+ ) }
181
+ < ActionButton
182
+ aria-label = { t ( 'Submit search query' ) }
183
+ size = "zero"
184
+ icon = { < IconSearch size = "sm" /> }
185
+ borderless
186
+ priority = { unsubmittedChanges ? 'primary' : 'default' }
187
+ onClick = { ( ) => handleSearch ( query ) }
188
+ />
189
+ </ ButtonsWrapper >
190
+ ) ;
191
+ } ) ;
181
192
182
193
export function SearchQueryBuilder ( {
183
194
className,
@@ -312,18 +323,20 @@ export function SearchQueryBuilder({
312
323
data-test-id = "search-query-builder"
313
324
>
314
325
< PanelProvider >
315
- < SearchIndicator
326
+ { /* <SearchIndicator
316
327
initialQuery={initialQuery}
317
328
showUnsubmittedIndicator={showUnsubmittedIndicator}
318
- />
329
+ /> */ }
319
330
{ ! parsedQuery || queryInterface === QueryInterfaceType . TEXT ? (
320
331
< PlainTextQueryInput label = { label } />
321
332
) : (
322
333
< TokenizedQueryGrid label = { label } actionBarWidth = { actionBarWidth } />
323
334
) }
324
- { size !== 'small' && (
325
- < ActionButtons ref = { actionBarRef } trailingItems = { trailingItems } />
326
- ) }
335
+ < ActionButtons
336
+ ref = { actionBarRef }
337
+ trailingItems = { trailingItems }
338
+ initialQuery = { initialQuery }
339
+ />
327
340
</ PanelProvider >
328
341
</ Wrapper >
329
342
</ SearchQueryBuilderContext . Provider >
@@ -342,15 +355,22 @@ const Wrapper = styled(Input.withComponent('div'))`
342
355
343
356
const ButtonsWrapper = styled ( 'div' ) `
344
357
position: absolute;
345
- right: 9px ;
346
- top: 9px ;
358
+ right: 3px ;
359
+ top: 3px ;
347
360
display: flex;
348
361
align-items: center;
349
362
gap: ${ space ( 0.5 ) } ;
350
363
` ;
351
364
352
365
const ActionButton = styled ( Button ) `
353
- color: ${ p => p . theme . subText } ;
366
+ ${ p =>
367
+ p . priority !== 'primary' &&
368
+ css `
369
+ color : ${ p . theme . subText } ;
370
+ ` }
371
+
372
+ height: 30px;
373
+ width: 30px;
354
374
` ;
355
375
356
376
const PositionedSearchIconContainer = styled ( 'div' ) `
0 commit comments