Skip to content

Commit aca9df4

Browse files
authored
feat(explorer): replay tool UI and menu fixes (#103238)
- adds copy and navigation for get_replay_details tool - fix size of menu button - fix session titles wrapping - fix session timestamp timezones - fix keyboard navigation not scrolling in menu - fix missing border on menu <img width="746" height="146" alt="Screenshot 2025-11-12 at 9 25 17 AM" src="https://github.com/user-attachments/assets/caf26f8f-2dd8-4a1b-944d-11c47d150494" /> <img width="770" height="444" alt="Screenshot 2025-11-12 at 9 40 03 AM" src="https://github.com/user-attachments/assets/c2b4b4df-3ddb-44fc-9047-7e7743aaa868" />
1 parent cc22538 commit aca9df4

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

static/app/views/seerExplorer/explorerMenu.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import {Activity, useCallback, useEffect, useMemo, useState} from 'react';
1+
import {Activity, useCallback, useEffect, useMemo, useRef, useState} from 'react';
22
import styled from '@emotion/styled';
3+
import moment from 'moment-timezone';
34

4-
import {DateTime} from 'sentry/components/dateTime';
5+
import TimeSince from 'sentry/components/timeSince';
56
import {space} from 'sentry/styles/space';
67
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
78
import {useExplorerSessions} from 'sentry/views/seerExplorer/hooks/useExplorerSessions';
@@ -129,12 +130,23 @@ export function useExplorerMenu({
129130
const isVisible = menuMode !== 'hidden';
130131

131132
const [selectedIndex, setSelectedIndex] = useState(0);
133+
const menuItemRefs = useRef<Array<HTMLDivElement | null>>([]);
132134

133135
// Reset selected index when items change
134136
useEffect(() => {
135137
setSelectedIndex(0);
136138
}, [menuItems]);
137139

140+
// Scroll selected item into view when selection changes
141+
useEffect(() => {
142+
if (isVisible && menuItemRefs.current[selectedIndex]) {
143+
menuItemRefs.current[selectedIndex]?.scrollIntoView({
144+
block: 'nearest',
145+
behavior: 'smooth',
146+
});
147+
}
148+
}, [selectedIndex, isVisible]);
149+
138150
// Handle keyboard navigation with higher priority
139151
const handleKeyDown = useCallback(
140152
(e: KeyboardEvent) => {
@@ -193,6 +205,9 @@ export function useExplorerMenu({
193205
{menuItems.map((item, index) => (
194206
<MenuItem
195207
key={item.key}
208+
ref={el => {
209+
menuItemRefs.current[index] = el;
210+
}}
196211
isSelected={index === selectedIndex}
197212
onClick={() => onSelect(item)}
198213
>
@@ -310,9 +325,11 @@ function useSessions({
310325
title: session.title,
311326
key: session.run_id.toString(),
312327
description: (
313-
<span>
314-
Last updated at <DateTime date={session.last_triggered_at} />
315-
</span>
328+
<TimeSince
329+
tooltipPrefix="Last updated"
330+
date={moment.utc(session.last_triggered_at).toDate()}
331+
suffix="ago"
332+
/>
316333
),
317334
handler: () => {
318335
onChangeSession(session.run_id);
@@ -338,7 +355,6 @@ const MenuPanel = styled('div')<{
338355
width: 300px;
339356
background: ${p => p.theme.background};
340357
border: 1px solid ${p => p.theme.border};
341-
border-bottom: none;
342358
border-radius: ${p => p.theme.borderRadius};
343359
box-shadow: ${p => p.theme.dropShadowHeavy};
344360
max-height: ${p =>
@@ -366,6 +382,9 @@ const ItemName = styled('div')`
366382
font-weight: 600;
367383
color: ${p => p.theme.purple400};
368384
font-size: ${p => p.theme.fontSize.sm};
385+
overflow: hidden;
386+
text-overflow: ellipsis;
387+
white-space: nowrap;
369388
`;
370389

371390
const ItemDescription = styled('div')`

static/app/views/seerExplorer/inputSection.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,12 @@ const InputRow = styled('div')`
9393

9494
const ButtonContainer = styled('div')`
9595
display: flex;
96-
align-items: stretch;
96+
align-items: center;
9797
padding: ${p => p.theme.space.sm};
9898
9999
button {
100-
flex: 1;
101-
height: 100%;
102-
min-height: 100%;
100+
width: auto;
101+
padding: ${p => p.theme.space.md};
103102
}
104103
`;
105104

static/app/views/seerExplorer/utils.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ const TOOL_FORMATTERS: Record<string, ToolFormatter> = {
153153
? `Excavating commit history${dateRangeStr} in ${repoName}...`
154154
: `Excavated commit history${dateRangeStr} in ${repoName}`;
155155
},
156+
157+
get_replay_details: (args, isLoading) => {
158+
const replayId = args.replay_id || '';
159+
const shortReplayId = replayId.slice(0, 8);
160+
return isLoading
161+
? `Watching replay ${shortReplayId}...`
162+
: `Watched replay ${shortReplayId}`;
163+
},
156164
};
157165

158166
/**
@@ -310,6 +318,16 @@ export function buildToolLinkUrl(
310318

311319
return {pathname: `/issues/${issue_id}/events/${event_id}/`};
312320
}
321+
case 'get_replay_details': {
322+
const {replay_id} = toolLink.params;
323+
if (!replay_id) {
324+
return null;
325+
}
326+
327+
return {
328+
pathname: `/organizations/${orgSlug}/replays/${replay_id}/`,
329+
};
330+
}
313331
default:
314332
return null;
315333
}

0 commit comments

Comments
 (0)