@@ -11,7 +11,7 @@ import {TextArea} from '@sentry/scraps/textarea';
1111
1212import { addErrorMessage } from 'sentry/actionCreators/indicator' ;
1313import { openConfirmModal } from 'sentry/components/confirm' ;
14- import { DropdownMenu } from 'sentry/components/dropdownMenu' ;
14+ import { DropdownMenu , type MenuItemProps } from 'sentry/components/dropdownMenu' ;
1515import { Duration } from 'sentry/components/duration' ;
1616import { SeerMarkdown } from 'sentry/components/seer/markdown' ;
1717import { ChartContent } from 'sentry/components/seer/markdown/embeds/components/chart' ;
@@ -21,7 +21,6 @@ import {
2121 IconChevron ,
2222 IconClose ,
2323 IconEllipsis ,
24- IconRefresh ,
2524 IconReturn ,
2625 IconSeer ,
2726} from 'sentry/icons' ;
@@ -150,33 +149,50 @@ export function InvestigationCell({
150149 }
151150 }
152151
153- const refinementButton = (
154- < Button
155- size = "xs"
156- variant = "transparent"
157- icon = { < IconSeer size = "xs" /> }
158- aria-label = { t ( 'Ask Seer about %s' , displayTitle ) }
159- disabled = { waitingForDependencies }
160- onClick = { panelOpen ? ( ) => setPanelOpen ( false ) : openPanel }
161- />
152+ const actionItems : MenuItemProps [ ] = [ ] ;
153+ if ( block . kind === 'query' ) {
154+ actionItems . push ( {
155+ key : 'rerun' ,
156+ label : t ( 'Rerun' ) ,
157+ disabled :
158+ ! canRun ||
159+ rerunMutation . isPending ||
160+ isExecutionActive ( block . currentExecution ?. status ) ||
161+ ! ( block . generationPrompt || block . content ) . trim ( ) ,
162+ onAction : ( ) => void rerun ( ) ,
163+ } ) ;
164+ }
165+ actionItems . push (
166+ {
167+ key : 'refine' ,
168+ label : t ( 'Refine' ) ,
169+ disabled : waitingForDependencies ,
170+ onAction : openPanel ,
171+ } ,
172+ {
173+ key : 'delete' ,
174+ label : t ( 'Delete' ) ,
175+ priority : 'danger' ,
176+ disabled :
177+ ! canRun ||
178+ deleteMutation . isPending ||
179+ isExecutionActive ( block . currentExecution ?. status ) ,
180+ onAction : ( ) =>
181+ openConfirmModal ( {
182+ message : t ( 'Are you sure you want to delete this cell?' ) ,
183+ priority : 'danger' ,
184+ confirmText : t ( 'Delete' ) ,
185+ onConfirm : ( ) =>
186+ deleteMutation . mutate ( {
187+ block,
188+ investigationVersion : investigation . version ,
189+ } ) ,
190+ } ) ,
191+ }
162192 ) ;
163193
164- const queryHeaderActions = (
165- < Flex align = "center" gap = "xs" flexShrink = { 0 } >
166- { refinementButton }
167- < Button
168- size = "xs"
169- variant = "transparent"
170- icon = { < IconRefresh size = "xs" /> }
171- aria-label = { t ( 'Rerun %s' , displayTitle ) }
172- busy = { rerunMutation . isPending }
173- disabled = {
174- ! canRun ||
175- isExecutionActive ( block . currentExecution ?. status ) ||
176- ! ( block . generationPrompt || block . content ) . trim ( )
177- }
178- onClick = { ( ) => void rerun ( ) }
179- />
194+ const cellActions = (
195+ < CellActions data-cell-actions flexShrink = { 0 } >
180196 < DropdownMenu
181197 position = "bottom-end"
182198 usePortal
@@ -187,30 +203,9 @@ export function InvestigationCell({
187203 icon : < IconEllipsis size = "xs" /> ,
188204 'aria-label' : t ( 'Cell actions for %s' , displayTitle ) ,
189205 } }
190- items = { [
191- {
192- key : 'delete' ,
193- label : t ( 'Delete' ) ,
194- priority : 'danger' ,
195- disabled :
196- ! canRun ||
197- deleteMutation . isPending ||
198- isExecutionActive ( block . currentExecution ?. status ) ,
199- onAction : ( ) =>
200- openConfirmModal ( {
201- message : t ( 'Are you sure you want to delete this cell?' ) ,
202- priority : 'danger' ,
203- confirmText : t ( 'Delete' ) ,
204- onConfirm : ( ) =>
205- deleteMutation . mutate ( {
206- block,
207- investigationVersion : investigation . version ,
208- } ) ,
209- } ) ,
210- } ,
211- ] }
206+ items = { actionItems }
212207 />
213- </ Flex >
208+ </ CellActions >
214209 ) ;
215210
216211 const panel = panelOpen ? (
@@ -240,7 +235,7 @@ export function InvestigationCell({
240235 { block . kind === 'query' ? (
241236 < Fragment >
242237 < QueryResult
243- actions = { queryHeaderActions }
238+ actions = { cellActions }
244239 block = { block }
245240 progressState = { progressState }
246241 />
@@ -250,8 +245,8 @@ export function InvestigationCell({
250245 < Fragment >
251246 < CellResult
252247 block = { block }
248+ actions = { cellActions }
253249 progressState = { progressState }
254- refinementButton = { refinementButton }
255250 streamedMarkdown = {
256251 isExecutionActive ( block . currentExecution ?. status )
257252 ? streamedTextQuery . data ?. partialMarkdown
@@ -266,20 +261,20 @@ export function InvestigationCell({
266261}
267262
268263function CellResult ( {
264+ actions,
269265 block,
270266 progressState,
271- refinementButton,
272267 streamedMarkdown,
273268} : {
269+ actions : React . ReactNode ;
274270 block : InvestigationBlock ;
275271 progressState : CellProgressState ;
276- refinementButton : React . ReactNode ;
277272 streamedMarkdown ?: string | null ;
278273} ) {
279274 const markdown =
280275 streamedMarkdown ?? getTextOutput ( block . output ) ?? ( block . content . trim ( ) || null ) ;
281276 return (
282- < Stack
277+ < CellHoverSurface
283278 position = "relative"
284279 flex = { 1 }
285280 minWidth = { 0 }
@@ -288,15 +283,15 @@ function CellResult({
288283 data-cell-variant = "unbordered"
289284 >
290285 < Container position = "absolute" top = { 0 } right = { 0 } >
291- { refinementButton }
286+ { actions }
292287 </ Container >
293288 < CellExecutionAlert block = { block } />
294289 { markdown ? (
295290 < SeerMarkdown raw = { markdown } />
296291 ) : (
297292 < CellProgress state = { progressState } />
298293 ) }
299- </ Stack >
294+ </ CellHoverSurface >
300295 ) ;
301296}
302297
@@ -321,7 +316,7 @@ function QueryResult({
321316 getChartMetadata ( chart ) ;
322317
323318 return (
324- < Stack width = "100%" gap = "sm" >
319+ < CellHoverSurface width = "100%" gap = "sm" >
325320 < QueryDisclosureButton
326321 size = "sm"
327322 variant = "transparent"
@@ -381,7 +376,7 @@ function QueryResult({
381376 </ Container >
382377 </ Stack >
383378 ) : null }
384- </ Stack >
379+ </ CellHoverSurface >
385380 ) ;
386381}
387382
@@ -1131,6 +1126,23 @@ const QueryDisclosureButton = styled(Button)`
11311126 text-align: left;
11321127` ;
11331128
1129+ const CellActions = styled ( Flex ) `
1130+ opacity: 0;
1131+ ` ;
1132+
1133+ const CellHoverSurface = styled ( Stack ) `
1134+ &:hover ${ CellActions } ,
1135+ &:focus-within ${ CellActions } {
1136+ opacity: 1;
1137+ }
1138+
1139+ @media (hover: none) {
1140+ ${ CellActions } {
1141+ opacity: 1;
1142+ }
1143+ }
1144+ ` ;
1145+
11341146const QueryTable = styled ( 'table' ) `
11351147 min-width: 100%;
11361148 border-collapse: collapse;
0 commit comments