Browse Source

ref(replays): update icons for replay details (#55789)

@Jesse-Box reference designs:
![Screenshot 2023-09-05 at 18 55
03](https://github.com/getsentry/sentry/assets/56095982/7645e361-b760-46ba-887e-be4730c65ea4)

<img width="592" alt="SCR-20230906-jrwj"
src="https://github.com/getsentry/sentry/assets/56095982/539048f0-d43f-4dba-816d-aff87761c273">
<img width="590" alt="SCR-20230906-jric"
src="https://github.com/getsentry/sentry/assets/56095982/c80d877e-e663-4285-80ac-7258117715e2">
<img width="585" alt="SCR-20230906-jrdw"
src="https://github.com/getsentry/sentry/assets/56095982/17458958-be94-4072-9aa7-5faa3a0823b6">
<img width="587" alt="SCR-20230906-jrcd"
src="https://github.com/getsentry/sentry/assets/56095982/931dc521-5a82-45bd-b7b5-323132a1d3d1">


Fixes https://github.com/getsentry/sentry/issues/54032 and closes
https://github.com/getsentry/team-replay/issues/122
Michelle Zhang 1 year ago
parent
commit
49f7d58744

+ 2 - 3
static/app/components/replays/breadcrumbs/breadcrumbItem.tsx

@@ -8,7 +8,6 @@ import {
 } from 'react';
 import styled from '@emotion/styled';
 
-import BreadcrumbIcon from 'sentry/components/events/interfaces/breadcrumbs/breadcrumb/type/icon';
 import ProjectBadge from 'sentry/components/idBadge/projectBadge';
 import ObjectInspector from 'sentry/components/objectInspector';
 import PanelItem from 'sentry/components/panels/panelItem';
@@ -73,7 +72,7 @@ function BreadcrumbItem({
   startTimestampMs,
   style,
 }: Props) {
-  const {color, description, projectSlug, title, type, timestampMs} =
+  const {color, description, projectSlug, title, icon, timestampMs} =
     getCrumbOrFrameData(frame);
 
   const handleDimensionChange = useCallback(
@@ -92,7 +91,7 @@ function BreadcrumbItem({
       className={className}
     >
       <IconWrapper color={color} hasOccurred>
-        <BreadcrumbIcon type={type} />
+        {icon}
       </IconWrapper>
       <CrumbDetails>
         <TitleContainer>

+ 45 - 34
static/app/utils/replays/getFrameDetails.tsx

@@ -1,9 +1,20 @@
 import {ReactNode} from 'react';
 
 import {Tooltip} from 'sentry/components/tooltip';
-import {IconWarning} from 'sentry/icons';
+import {
+  IconCursorArrow,
+  IconFire,
+  IconFix,
+  IconInfo,
+  IconInput,
+  IconKeyDown,
+  IconLocation,
+  IconSort,
+  IconTerminal,
+  IconUser,
+  IconWarning,
+} from 'sentry/icons';
 import {t, tct} from 'sentry/locale';
-import {BreadcrumbType} from 'sentry/types/breadcrumbs';
 import {TabKey} from 'sentry/utils/replays/hooks/useActiveReplayTab';
 import type {
   BreadcrumbFrame,
@@ -27,9 +38,9 @@ import stripOrigin from 'sentry/utils/url/stripOrigin';
 interface Details {
   color: Color;
   description: ReactNode;
+  icon: ReactNode;
   tabKey: TabKey;
   title: ReactNode;
-  type: BreadcrumbType;
 }
 
 const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
@@ -38,27 +49,27 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
     description: stripOrigin(frame.message ?? ''),
     tabKey: TabKey.CONSOLE,
     title: 'Replay Start',
-    type: BreadcrumbType.DEFAULT,
+    icon: <IconTerminal size="xs" />,
   }),
   navigation: (frame: NavFrame) => ({
     color: 'green300',
     description: stripOrigin((frame as NavFrame).data.to),
     tabKey: TabKey.NETWORK,
     title: 'Navigation',
-    type: BreadcrumbType.NAVIGATION,
+    icon: <IconLocation size="xs" />,
   }),
   issue: (frame: ErrorFrame) => ({
     color: 'red300',
     description: frame.message,
     tabKey: TabKey.ERRORS,
     title: defaultTitle(frame),
-    type: BreadcrumbType.ERROR,
+    icon: <IconFire size="xs" />,
   }),
   'ui.slowClickDetected': (frame: SlowClickFrame) => {
     const node = frame.data.node;
     if (isDeadClick(frame)) {
       return {
-        color: 'red300',
+        color: isDeadRageClick(frame) ? 'red300' : 'yellow300',
         description: tct(
           'Click on [selector] did not cause a visible effect within [timeout] ms',
           {
@@ -66,7 +77,7 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
             timeout: Math.round(frame.data.timeAfterClickMs),
           }
         ),
-        type: BreadcrumbType.ERROR,
+        icon: <IconCursorArrow size="xs" />,
         title: isDeadRageClick(frame) ? 'Rage Click' : 'Dead Click',
         tabKey: TabKey.DOM,
       };
@@ -80,7 +91,7 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
           duration: Math.round(frame.data.timeAfterClickMs),
         }
       ),
-      type: BreadcrumbType.WARNING,
+      icon: <IconWarning size="xs" />,
       title: 'Slow Click',
       tabKey: TabKey.DOM,
     };
@@ -95,7 +106,7 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
         }),
         tabKey: TabKey.DOM,
         title: 'Rage Click',
-        type: BreadcrumbType.ERROR,
+        icon: <IconFire size="xs" />,
       };
     }
 
@@ -107,7 +118,7 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
       }),
       tabKey: TabKey.DOM,
       title: 'Multi Click',
-      type: BreadcrumbType.WARNING,
+      icon: <IconWarning size="xs" />,
     };
   },
   'replay.mutations': (frame: MutationFrame) => ({
@@ -123,77 +134,77 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
         ),
     tabKey: TabKey.DOM,
     title: 'Replay',
-    type: BreadcrumbType.WARNING,
+    icon: <IconWarning size="xs" />,
   }),
   'ui.click': frame => ({
     color: 'purple300',
     description: frame.message ?? '',
     tabKey: TabKey.DOM,
     title: 'User Click',
-    type: BreadcrumbType.UI,
+    icon: <IconCursorArrow size="xs" />,
   }),
   'ui.input': () => ({
     color: 'purple300',
     description: 'User Action',
     tabKey: TabKey.DOM,
     title: 'User Input',
-    type: BreadcrumbType.UI,
+    icon: <IconInput size="xs" />,
   }),
   'ui.keyDown': () => ({
     color: 'purple300',
     description: 'User Action',
     tabKey: TabKey.DOM,
     title: 'User KeyDown',
-    type: BreadcrumbType.UI,
+    icon: <IconKeyDown size="xs" />,
   }),
   'ui.blur': () => ({
     color: 'purple300',
     description: 'User Action',
     tabKey: TabKey.DOM,
     title: 'User Blur',
-    type: BreadcrumbType.UI,
+    icon: <IconUser size="xs" />,
   }),
   'ui.focus': () => ({
     color: 'purple300',
     description: 'User Action',
     tabKey: TabKey.DOM,
     title: 'User Focus',
-    type: BreadcrumbType.UI,
+    icon: <IconUser size="xs" />,
   }),
   console: frame => ({
     color: 'gray300',
     description: frame.message ?? '',
     tabKey: TabKey.CONSOLE,
     title: 'Console',
-    type: BreadcrumbType.DEBUG,
+    icon: <IconFix size="xs" />,
   }),
   'navigation.navigate': frame => ({
     color: 'green300',
     description: stripOrigin(frame.description),
     tabKey: TabKey.NETWORK,
     title: 'Page Load',
-    type: BreadcrumbType.NAVIGATION,
+    icon: <IconLocation size="xs" />,
   }),
   'navigation.reload': frame => ({
     color: 'green300',
     description: stripOrigin(frame.description),
     tabKey: TabKey.NETWORK,
     title: 'Reload',
-    type: BreadcrumbType.NAVIGATION,
+    icon: <IconLocation size="xs" />,
   }),
   'navigation.back_forward': frame => ({
     color: 'green300',
     description: stripOrigin(frame.description),
     tabKey: TabKey.NETWORK,
     title: 'Navigate Back/Forward',
-    type: BreadcrumbType.NAVIGATION,
+    icon: <IconLocation size="xs" />,
   }),
   'navigation.push': frame => ({
     color: 'green300',
     description: stripOrigin(frame.description),
     tabKey: TabKey.NETWORK,
     title: 'Navigation',
-    type: BreadcrumbType.NAVIGATION,
+    icon: <IconLocation size="xs" />,
   }),
   'largest-contentful-paint': (frame: LargestContentfulPaintFrame) => ({
     color: 'gray300',
@@ -211,77 +222,77 @@ const MAPPER_FOR_FRAME: Record<string, (frame) => Details> = {
       ),
     tabKey: TabKey.NETWORK,
     title: 'LCP',
-    type: BreadcrumbType.INFO,
+    icon: <IconInfo size="xs" />,
   }),
   memory: () => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.MEMORY,
     title: 'Memory',
-    type: BreadcrumbType.INFO,
+    icon: <IconInfo size="xs" />,
   }),
   paint: () => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: 'Paint',
-    type: BreadcrumbType.INFO,
+    icon: <IconInfo size="xs" />,
   }),
   'resource.css': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.fetch': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.iframe': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.img': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.link': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.other': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.script': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
   'resource.xhr': frame => ({
     color: 'gray300',
     description: undefined,
     tabKey: TabKey.NETWORK,
     title: frame.description,
-    type: BreadcrumbType.HTTP,
+    icon: <IconSort size="xs" rotated />,
   }),
 };
 
@@ -290,7 +301,7 @@ const MAPPER_DEFAULT = (frame): Details => ({
   description: frame.message ?? '',
   tabKey: TabKey.CONSOLE,
   title: defaultTitle(frame),
-  type: BreadcrumbType.DEFAULT,
+  icon: <IconTerminal size="xs" />,
 });
 
 export default function getFrameDetails(frame: ReplayFrame): Details {

+ 2 - 3
static/app/views/replays/detail/domMutations/domMutationRow.tsx

@@ -4,7 +4,6 @@ import classNames from 'classnames';
 import beautify from 'js-beautify';
 
 import {CodeSnippet} from 'sentry/components/codeSnippet';
-import BreadcrumbIcon from 'sentry/components/events/interfaces/breadcrumbs/breadcrumb/type/icon';
 import {space} from 'sentry/styles/space';
 import type {Extraction} from 'sentry/utils/replays/extractDomNodes';
 import getFrameDetails from 'sentry/utils/replays/getFrameDetails';
@@ -36,7 +35,7 @@ function DomMutationRow({
   const isBeforeHover =
     currentHoverTime === undefined || currentHoverTime >= frame.offsetMs;
 
-  const {color, title, type} = getFrameDetails(frame);
+  const {color, title, icon} = getFrameDetails(frame);
 
   return (
     <MutationListItem
@@ -51,7 +50,7 @@ function DomMutationRow({
       style={style}
     >
       <IconWrapper color={color} hasOccurred={hasOccurred}>
-        <BreadcrumbIcon type={type} />
+        {icon}
       </IconWrapper>
       <List>
         <Row>

+ 2 - 3
static/app/views/replays/detail/perfTable/perfRow.tsx

@@ -2,7 +2,6 @@ import {CSSProperties, Fragment, useCallback} from 'react';
 import styled from '@emotion/styled';
 import classNames from 'classnames';
 
-import BreadcrumbIcon from 'sentry/components/events/interfaces/breadcrumbs/breadcrumb/type/icon';
 import {Tooltip} from 'sentry/components/tooltip';
 import {IconClock, IconRefresh} from 'sentry/icons';
 import {tct} from 'sentry/locale';
@@ -35,7 +34,7 @@ export default function PerfRow({
   traceRow,
 }: Props) {
   const {lcpFrames, replayFrame: frame, paintFrames, flattenedTraces} = traceRow;
-  const {color, description, title, type} = getFrameDetails(frame);
+  const {color, description, title, icon} = getFrameDetails(frame);
   const lcp = lcpFrames.length ? getFrameDetails(lcpFrames[0]) : null;
 
   const handleDimensionChange = useCallback(
@@ -72,7 +71,7 @@ export default function PerfRow({
       <Vertical style={{gap: space(1)}}>
         <Horizontal style={{gap: space(1)}}>
           <IconWrapper color={color} hasOccurred={hasOccurred}>
-            <BreadcrumbIcon type={type} />
+            {icon}
           </IconWrapper>
           <Vertical style={{flexGrow: 1}}>
             <Title hasOccurred={hasOccurred}>{title}</Title>