Browse Source

ref(replay): Update hydration Before/After labels to have timestamps in their tooltip (#82895)

Ryan Albrecht 2 months ago
parent
commit
271cdb8871

+ 5 - 0
static/app/components/replays/diff/replayMutationTree.tsx

@@ -3,6 +3,7 @@ import {css} from '@emotion/react';
 import styled from '@emotion/styled';
 
 import DiffFeedbackBanner from 'sentry/components/replays/diff/diffFeedbackBanner';
+import {After, Before, DiffHeader} from 'sentry/components/replays/diff/utils';
 import StructuredEventData from 'sentry/components/structuredEventData';
 import useExtractDiffMutations from 'sentry/utils/replays/hooks/useExtractDiffMutations';
 import type ReplayReader from 'sentry/utils/replays/replayReader';
@@ -32,6 +33,10 @@ export function ReplayMutationTree({replay, leftOffsetMs, rightOffsetMs}: Props)
 
   return (
     <Fragment>
+      <DiffHeader>
+        <Before startTimestampMs={replay.getStartTimestampMs()} offset={leftOffsetMs} />
+        <After startTimestampMs={replay.getStartTimestampMs()} offset={rightOffsetMs} />
+      </DiffHeader>
       {!isLoading && Object.keys(timeIndexedMutations).length === 0 ? (
         <DiffFeedbackBanner />
       ) : null}

+ 2 - 2
static/app/components/replays/diff/replaySideBySideImageDiff.tsx

@@ -20,8 +20,8 @@ export function ReplaySideBySideImageDiff({leftOffsetMs, replay, rightOffsetMs}:
   return (
     <Flex column>
       <DiffHeader>
-        <Before />
-        <After />
+        <Before startTimestampMs={replay.getStartTimestampMs()} offset={leftOffsetMs} />
+        <After startTimestampMs={replay.getStartTimestampMs()} offset={rightOffsetMs} />
       </DiffHeader>
 
       <ReplayGrid>

+ 2 - 2
static/app/components/replays/diff/replaySliderDiff.tsx

@@ -38,8 +38,8 @@ export function ReplaySliderDiff({
   return (
     <Fragment>
       <DiffHeader>
-        <Before />
-        <After />
+        <Before startTimestampMs={replay.getStartTimestampMs()} offset={leftOffsetMs} />
+        <After startTimestampMs={replay.getStartTimestampMs()} offset={rightOffsetMs} />
       </DiffHeader>
       <WithPadding>
         <Positioned style={{minHeight}} ref={positionedRef}>

+ 2 - 2
static/app/components/replays/diff/replayTextDiff.tsx

@@ -32,7 +32,7 @@ export function ReplayTextDiff({replay, leftOffsetMs, rightOffsetMs}: Props) {
     <Container>
       {!isLoading && leftBody === rightBody ? <DiffFeedbackBanner /> : null}
       <DiffHeader>
-        <Before>
+        <Before startTimestampMs={replay.getStartTimestampMs()} offset={leftOffsetMs}>
           <CopyToClipboardButton
             text={leftBody ?? ''}
             size="xs"
@@ -41,7 +41,7 @@ export function ReplayTextDiff({replay, leftOffsetMs, rightOffsetMs}: Props) {
             aria-label={t('Copy Before')}
           />
         </Before>
-        <After>
+        <After startTimestampMs={replay.getStartTimestampMs()} offset={rightOffsetMs}>
           <CopyToClipboardButton
             text={rightBody ?? ''}
             size="xs"

+ 46 - 11
static/app/components/replays/diff/utils.tsx

@@ -1,5 +1,6 @@
 import styled from '@emotion/styled';
 
+import ReplayTooltipTime from 'sentry/components/replays/replayTooltipTime';
 import {Tooltip} from 'sentry/components/tooltip';
 import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
@@ -22,15 +23,27 @@ export const DiffHeader = styled('div')`
   }
 `;
 
-const Label = styled('div')`
-  display: flex;
-  align-items: center;
-  font-weight: bold;
-`;
+interface BeforeAfterProps {
+  offset: number;
+  startTimestampMs: number;
+  children?: React.ReactNode;
+}
 
-export function Before({children}: {children?: React.ReactNode}) {
+export function Before({children, offset, startTimestampMs}: BeforeAfterProps) {
   return (
-    <Tooltip title={t('How the initial server-rendered page looked.')}>
+    <Tooltip
+      title={
+        <LeftAligned>
+          {t('The server-rendered page')}
+          <div>
+            <ReplayTooltipTime
+              timestampMs={startTimestampMs + offset}
+              startTimestampMs={startTimestampMs}
+            />
+          </div>
+        </LeftAligned>
+      }
+    >
       <Label>
         {t('Before')}
         {children}
@@ -38,12 +51,21 @@ export function Before({children}: {children?: React.ReactNode}) {
     </Tooltip>
   );
 }
-export function After({children}: {children?: React.ReactNode}) {
+
+export function After({children, offset, startTimestampMs}: BeforeAfterProps) {
   return (
     <Tooltip
-      title={t(
-        'How React re-rendered the page on your browser, after detecting a hydration error.'
-      )}
+      title={
+        <LeftAligned>
+          {t('After React re-rendered the page, and reported a hydration error')}
+          <div>
+            <ReplayTooltipTime
+              timestampMs={startTimestampMs + offset}
+              startTimestampMs={startTimestampMs}
+            />
+          </div>
+        </LeftAligned>
+      }
     >
       <Label>
         {t('After')}
@@ -52,3 +74,16 @@ export function After({children}: {children?: React.ReactNode}) {
     </Tooltip>
   );
 }
+
+const LeftAligned = styled('div')`
+  text-align: left;
+  display: flex;
+  gap: ${space(1)};
+  flex-direction: column;
+`;
+
+const Label = styled('div')`
+  display: flex;
+  align-items: center;
+  font-weight: bold;
+`;

+ 44 - 0
static/app/components/replays/replayTooltipTime.tsx

@@ -0,0 +1,44 @@
+import {Fragment} from 'react';
+import styled from '@emotion/styled';
+
+import {t} from 'sentry/locale';
+import {getFormat, getFormattedDate} from 'sentry/utils/dates';
+import formatDuration from 'sentry/utils/duration/formatDuration';
+
+interface Props {
+  startTimestampMs: number;
+  timestampMs: number;
+}
+
+export default function ReplayTooltipTime({startTimestampMs, timestampMs}: Props) {
+  return (
+    <Fragment>
+      <TooltipTime>
+        {t(
+          'Date: %s',
+          getFormattedDate(
+            timestampMs,
+            `${getFormat({year: true, seconds: true, timeZone: true})}`,
+            {
+              local: true,
+            }
+          )
+        )}
+      </TooltipTime>
+      <TooltipTime>
+        {t(
+          'Time within replay: %s',
+          formatDuration({
+            duration: [Math.abs(timestampMs - startTimestampMs), 'ms'],
+            precision: 'ms',
+            style: 'hh:mm:ss.sss',
+          })
+        )}
+      </TooltipTime>
+    </Fragment>
+  );
+}
+
+const TooltipTime = styled('div')`
+  text-align: left;
+`;

+ 5 - 29
static/app/views/replays/detail/timestampButton.tsx

@@ -3,12 +3,10 @@ import styled from '@emotion/styled';
 
 import {DateTime} from 'sentry/components/dateTime';
 import Duration from 'sentry/components/duration/duration';
+import ReplayTooltipTime from 'sentry/components/replays/replayTooltipTime';
 import {Tooltip} from 'sentry/components/tooltip';
 import {IconPlay} from 'sentry/icons';
-import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
-import {getFormat, getFormattedDate} from 'sentry/utils/dates';
-import formatDuration from 'sentry/utils/duration/formatDuration';
 import {useReplayPrefs} from 'sentry/utils/replays/playback/providers/replayPreferencesContext';
 
 type Props = {
@@ -32,28 +30,10 @@ export default function TimestampButton({
     <Tooltip
       title={
         <div>
-          <TooltipTime>
-            {t(
-              'Date: %s',
-              getFormattedDate(
-                timestampMs,
-                `${getFormat({year: true, seconds: true, timeZone: true})}`,
-                {
-                  local: true,
-                }
-              )
-            )}
-          </TooltipTime>
-          <TooltipTime>
-            {t(
-              'Time within replay: %s',
-              formatDuration({
-                duration: [Math.abs(timestampMs - startTimestampMs), 'ms'],
-                precision: 'ms',
-                style: 'hh:mm:ss.sss',
-              })
-            )}
-          </TooltipTime>
+          <ReplayTooltipTime
+            timestampMs={timestampMs}
+            startTimestampMs={startTimestampMs}
+          />
         </div>
       }
       skipWrapper
@@ -77,10 +57,6 @@ export default function TimestampButton({
   );
 }
 
-const TooltipTime = styled('div')`
-  text-align: left;
-`;
-
 const StyledButton = styled('button')`
   background: transparent;
   border: none;