From b5ac359b55b8918850df63337beab05cfec76faf Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Sat, 6 Mar 2021 20:06:18 -0500 Subject: [PATCH 1/2] Improve DevTools Profiler commit-selector UX 1. Replace linear scale for commit durations with log scale. This reduces the impact of one (or few) outlier times on more common smaller durations. 2. Decrease the minimum bar height to make the differences in height more noticeable. 3. Add a backgound hover highlight to increase contrast. 4. Add hover tooltip with commit duration and timestamp. --- .../views/Profiler/SnapshotCommitList.js | 49 ++++++++++++++----- .../views/Profiler/SnapshotCommitListItem.css | 5 +- .../views/Profiler/SnapshotCommitListItem.js | 9 +++- .../views/Profiler/SnapshotSelector.css | 2 +- .../src/devtools/views/Profiler/Tooltip.css | 1 + 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js index 0d309f700644b..b4b42ddc82215 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js @@ -13,6 +13,8 @@ import AutoSizer from 'react-virtualized-auto-sizer'; import {FixedSizeList} from 'react-window'; import SnapshotCommitListItem from './SnapshotCommitListItem'; import {minBarWidth} from './constants'; +import {formatDuration, formatTime} from './utils'; +import Tooltip from './Tooltip'; import styles from './SnapshotCommitList.css'; @@ -24,6 +26,7 @@ export type ItemData = {| selectedCommitIndex: number | null, selectedFilteredCommitIndex: number | null, selectCommitIndex: (index: number) => void, + setHoveredCommitIndex: (index: number) => void, startCommitDrag: (newDragState: DragState) => void, |}; @@ -166,6 +169,10 @@ function List({ } }, [dragState]); + const [hoveredCommitIndex, setHoveredCommitIndex] = useState( + null, + ); + // Pass required contextual data down to the ListItem renderer. const itemData = useMemo( () => ({ @@ -176,6 +183,7 @@ function List({ selectedCommitIndex, selectedFilteredCommitIndex, selectCommitIndex, + setHoveredCommitIndex, startCommitDrag: setDragState, }), [ @@ -186,22 +194,37 @@ function List({ selectedCommitIndex, selectedFilteredCommitIndex, selectCommitIndex, + setHoveredCommitIndex, ], ); + let tooltipLabel = null; + if (hoveredCommitIndex !== null) { + const commitDuration = commitDurations[hoveredCommitIndex]; + const commitTime = commitTimes[hoveredCommitIndex]; + tooltipLabel = `${formatDuration(commitDuration)}ms at ${formatTime( + commitTime, + )}s`; + } + return ( -
- - {SnapshotCommitListItem} - -
+ +
setHoveredCommitIndex(null)}> + + {SnapshotCommitListItem} + +
+
); } diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css index dc6592a931706..cfcc6b7a64ed4 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.css @@ -7,10 +7,13 @@ display: flex; align-items: flex-end; } +.Outer:hover { + background-color: var(--color-background); +} .Inner { width: 100%; - min-height: 5px; + min-height: 2px; background-color: var(--color-commit-did-not-render-fill); color: var(--color-commit-did-not-render-fill-text); } diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js index e8399a09bb37d..020d2876a7d51 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js @@ -31,6 +31,7 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) { maxDuration, selectedCommitIndex, selectCommitIndex, + setHoveredCommitIndex, startCommitDrag, } = itemData; @@ -41,7 +42,10 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) { // Guard against commits with duration 0 const percentage = - Math.min(1, Math.max(0, commitDuration / maxDuration)) || 0; + Math.min( + 1, + Math.max(0, Math.log(commitDuration) / Math.log(maxDuration)), + ) || 0; const isSelected = selectedCommitIndex === index; // Leave a 1px gap between snapshots @@ -62,6 +66,7 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
setHoveredCommitIndex(index)} style={{ ...style, width, @@ -77,7 +82,7 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) { style={{ height: `${Math.round(percentage * 100)}%`, backgroundColor: - percentage > 0 ? getGradientColor(percentage) : undefined, + commitDuration > 0 ? getGradientColor(percentage) : undefined, }} />
diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css index e4f8aec57d4ed..c708adcffdbc3 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.css @@ -7,7 +7,7 @@ height: 100%; min-width: 30px; margin-left: 0.25rem; - overflow: hidden; + overflow: visible; } .Commits:focus { outline: none; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.css b/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.css index 2d2bbaf34ea38..cbefd4e8598ad 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.css @@ -9,6 +9,7 @@ background-color: var(--color-tooltip-background); color: var(--color-tooltip-text); opacity: 1; + white-space: nowrap; /* Make sure this is above the DevTools, which are above the Overlay */ z-index: 10000002; } From 07b415599f5619eea8917a8a74ee628564e944fa Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 8 Mar 2021 10:11:18 -0500 Subject: [PATCH 2/2] Use natural log for snapshot selector bar height, linear for color --- .../views/Profiler/SnapshotCommitListItem.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js index 020d2876a7d51..5dccf356212cc 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitListItem.js @@ -40,12 +40,21 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) { const commitDuration = commitDurations[index]; const commitTime = commitTimes[index]; - // Guard against commits with duration 0 - const percentage = + // Use natural log for bar height. + // This prevents one (or a few) outliers from squishing the majority of other commits. + // So rather than e.g. _█_ we get something more like e.g. ▄█_ + const heightScale = Math.min( 1, Math.max(0, Math.log(commitDuration) / Math.log(maxDuration)), ) || 0; + + // Use a linear scale for color. + // This gives some visual contrast between cheaper and more expensive commits + // and somewhat compensates for the log scale height. + const colorScale = + Math.min(1, Math.max(0, commitDuration / maxDuration)) || 0; + const isSelected = selectedCommitIndex === index; // Leave a 1px gap between snapshots @@ -80,9 +89,9 @@ function SnapshotCommitListItem({data: itemData, index, style}: Props) {
0 ? getGradientColor(percentage) : undefined, + commitDuration > 0 ? getGradientColor(colorScale) : undefined, }} />