Skip to content

Commit 6fb2f2e

Browse files
style(replays): update some css on chapter list (#95747)
fix some wonky css on the chapter list for ai summary: ### 1. error text & highlight matches breadcrumb (the shade was too dark) <img width="840" height="692" alt="Screenshot 2025-07-16 at 4 07 44 PM" src="https://github.com/user-attachments/assets/30604040-c230-4867-9eea-9aaedb6c6923" /> ### 2. error/feedback chapter, when expanded, has an arrow down chevron to match other chapters <img width="844" height="459" alt="SCR-20250716-ogcl" src="https://github.com/user-attachments/assets/1f51b9c8-d9ac-48a8-9e70-f5dfac6adf64" /> ### 3. remove the top gap in the chapter background when hovered ### 4. background color of nested breadcrumbs is lighter to match figma design https://github.com/user-attachments/assets/55cba370-32ec-412b-9d3f-79291d4a5571
1 parent 22ebf38 commit 6fb2f2e

File tree

1 file changed

+50
-20
lines changed

1 file changed

+50
-20
lines changed

static/app/views/replays/detail/ai/chapterList.tsx

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ function ChapterRow({
103103
const {onClickTimestamp} = useCrumbHandlers();
104104
const [currentHoverTime] = useCurrentHoverTime();
105105
const [isHovered, setIsHovered] = useState(false);
106+
const [isOpen, setIsOpen] = useState(false);
106107

107108
const startOffset = Math.max(start - (replay?.getStartTimestampMs() ?? 0), 0);
108109
const endOffset = Math.max(end - (replay?.getStartTimestampMs() ?? 0), 0);
@@ -113,6 +114,8 @@ function ChapterRow({
113114

114115
return (
115116
<ChapterWrapper
117+
data-has-error={Boolean(error)}
118+
data-has-feedback={Boolean(feedback)}
116119
className={classNames(className, {
117120
beforeCurrentTime: hasOccurred,
118121
afterCurrentTime: !hasOccurred,
@@ -122,10 +125,9 @@ function ChapterRow({
122125
})}
123126
onMouseEnter={() => setIsHovered(true)}
124127
onMouseLeave={() => setIsHovered(false)}
128+
onToggle={e => setIsOpen(e.currentTarget.open)}
125129
>
126130
<Chapter
127-
error={error}
128-
feedback={feedback}
129131
onClick={() =>
130132
trackAnalytics('replay.ai-summary.chapter-clicked', {
131133
chapter_type: error ? 'error' : feedback ? 'feedback' : undefined,
@@ -135,13 +137,13 @@ function ChapterRow({
135137
>
136138
<ChapterIconWrapper>
137139
{error ? (
138-
isHovered ? (
139-
<ChapterIconArrow direction="right" size="xs" color="errorText" />
140+
isOpen || isHovered ? (
141+
<ChapterIconArrow direction="right" size="xs" color="red300" />
140142
) : (
141-
<IconFire size="xs" color="errorText" />
143+
<IconFire size="xs" color="red300" />
142144
)
143145
) : feedback ? (
144-
isHovered ? (
146+
isOpen || isHovered ? (
145147
<ChapterIconArrow direction="right" size="xs" color="pink300" />
146148
) : (
147149
<IconMegaphone size="xs" color="pink300" />
@@ -237,6 +239,24 @@ const ChapterWrapper = styled('details')`
237239
&.activeChapter .beforeCurrentTime:last-child {
238240
border-bottom-color: ${p => p.theme.purple300};
239241
}
242+
243+
/* the border-top is used to eliminate some of the top gap */
244+
245+
&:hover {
246+
border-top: 1px solid ${p => p.theme.backgroundSecondary};
247+
}
248+
249+
[data-has-feedback='true'] {
250+
&:hover {
251+
border-top: 1px solid ${p => p.theme.pink100};
252+
}
253+
}
254+
255+
[data-has-error='true'] {
256+
&:hover {
257+
border-top: 1px solid ${p => p.theme.red100};
258+
}
259+
}
240260
`;
241261

242262
const ChapterBreadcrumbRow = styled(BreadcrumbRow)`
@@ -245,29 +265,22 @@ const ChapterBreadcrumbRow = styled(BreadcrumbRow)`
245265
&::before {
246266
display: none;
247267
}
248-
&:last-child {
249-
background-color: transparent;
250-
}
251-
details[open]:last-child &:last-child {
252-
background-color: ${p => p.theme.background};
268+
269+
&:hover {
270+
background-color: ${p => p.theme.backgroundSecondary};
253271
}
254272
`;
255273

256-
const Chapter = styled('summary')<{error?: boolean; feedback?: boolean}>`
274+
const Chapter = styled('summary')`
257275
cursor: pointer;
258276
display: flex;
259277
align-items: center;
260278
font-size: ${p => p.theme.fontSize.lg};
261279
padding: 0 ${space(0.75)};
262-
color: ${p =>
263-
p.error ? p.theme.errorText : p.feedback ? p.theme.pink300 : p.theme.textColor};
280+
color: ${p => p.theme.textColor};
281+
264282
&:hover {
265-
background-color: ${p =>
266-
p.error
267-
? p.theme.red100
268-
: p.feedback
269-
? p.theme.pink100
270-
: p.theme.backgroundSecondary};
283+
background-color: ${p => p.theme.backgroundSecondary};
271284
}
272285
273286
/* sorry */
@@ -279,6 +292,22 @@ const Chapter = styled('summary')<{error?: boolean; feedback?: boolean}>`
279292
&::-webkit-details-marker {
280293
display: none;
281294
}
295+
296+
[data-has-feedback='true'] & {
297+
color: ${p => p.theme.pink300};
298+
299+
&:hover {
300+
background-color: ${p => p.theme.pink100};
301+
}
302+
}
303+
304+
[data-has-error='true'] & {
305+
color: ${p => p.theme.red300};
306+
307+
&:hover {
308+
background-color: ${p => p.theme.red100};
309+
}
310+
}
282311
`;
283312

284313
const ChapterTitle = styled('div')`
@@ -295,6 +324,7 @@ const ChapterTitle = styled('div')`
295324
}
296325
297326
border-bottom: 1px solid ${p => p.theme.innerBorder};
327+
margin-bottom: -1px; /* Compensate for border to fully eliminate gap */
298328
299329
details:last-child:not([open]) & {
300330
border-bottom: none;

0 commit comments

Comments
 (0)