Skip to content

Commit 2e68dc7

Browse files
authored
[DevTools] Give a distinct color to the root (#34690)
Stacked on #34654. The root is special since it represents "Initial Paint" (or a "Transition" when an Activity is selected). This gives it a different color in the timeline as well as gives it an outline that's clickable. Hovering the timeline now shows "Initial Paint" or "Suspense". Also made the cursor a pointer to invite you to try to click things and some rounded corners. <img width="1219" height="420" alt="Screenshot 2025-10-02 at 1 26 38 PM" src="https://github.com/user-attachments/assets/12451f93-8917-4f3b-8f01-930129e5fc13" /> <img width="1217" height="419" alt="Screenshot 2025-10-02 at 1 26 54 PM" src="https://github.com/user-attachments/assets/02b5e94c-3fbe-488d-b0f2-225b73578608" /> <img width="1215" height="419" alt="Screenshot 2025-10-02 at 1 27 24 PM" src="https://github.com/user-attachments/assets/c24e8861-e74a-4ccc-8643-ee9d04bef43c" /> <img width="1216" height="419" alt="Screenshot 2025-10-02 at 1 27 10 PM" src="https://github.com/user-attachments/assets/d5cc2b62-fa64-41bf-b485-116b1cd67467" />
1 parent ced705d commit 2e68dc7

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
.SuspenseRectsContainer {
22
padding: .25rem;
3+
cursor: pointer;
4+
outline: 1px solid var(--color-component-name);
5+
border-radius: 0.25rem;
6+
}
7+
8+
.SuspenseRectsContainer[data-highlighted='true'] {
9+
background: var(--color-dimmest);
310
}
411

512
.SuspenseRectsViewBox {
@@ -28,6 +35,8 @@
2835
pointer-events: all;
2936
outline-style: solid;
3037
outline-width: 1px;
38+
border-radius: 0.125rem;
39+
cursor: pointer;
3140
}
3241

3342
.SuspenseRectsScaledRect {
@@ -42,7 +51,7 @@
4251

4352
/* highlight this boundary */
4453
.SuspenseRectsBoundary:hover:not(:has(.SuspenseRectsBoundary:hover)) > .SuspenseRectsRect, .SuspenseRectsBoundary[data-highlighted='true'] > .SuspenseRectsRect {
45-
background-color: var(--color-background-hover);
54+
background-color: var(--color-background-hover);
4655
}
4756

4857
.SuspenseRectsRect[data-highlighted='true'] {

packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ const ViewBox = createContext<Rect>((null: any));
295295

296296
function SuspenseRectsContainer(): React$Node {
297297
const store = useContext(StoreContext);
298+
const {inspectedElementID} = useContext(TreeStateContext);
298299
const treeDispatch = useContext(TreeDispatcherContext);
299300
const suspenseTreeDispatch = useContext(SuspenseTreeDispatcherContext);
300301
// TODO: This relies on a full re-render of all children when the Suspense tree changes.
@@ -329,8 +330,13 @@ function SuspenseRectsContainer(): React$Node {
329330
});
330331
}
331332

333+
const isRootSelected = roots.includes(inspectedElementID);
334+
332335
return (
333-
<div className={styles.SuspenseRectsContainer} onClick={handleClick}>
336+
<div
337+
className={styles.SuspenseRectsContainer}
338+
onClick={handleClick}
339+
data-highlighted={isRootSelected}>
334340
<ViewBox.Provider value={boundingBox}>
335341
<div
336342
className={styles.SuspenseRectsViewBox}

packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
padding-right: 0;
3838
}
3939

40-
.SuspenseScrubberBead, .SuspenseScrubberBeadSelected {
40+
.SuspenseScrubberBead {
4141
flex: 1;
4242
height: 0.5rem;
4343
background: var(--color-background-selected);
@@ -51,9 +51,11 @@
5151
background: var(--color-background-selected);
5252
}
5353

54+
.SuspenseScrubberBeadTransition {
55+
background: var(--color-component-name);
56+
}
57+
5458
.SuspenseScrubberStepHighlight > .SuspenseScrubberBead,
55-
.SuspenseScrubberStepHighlight > .SuspenseScrubberBeadSelected,
56-
.SuspenseScrubberStep:hover > .SuspenseScrubberBead,
57-
.SuspenseScrubberStep:hover > .SuspenseScrubberBeadSelected {
59+
.SuspenseScrubberStep:hover > .SuspenseScrubberBead {
5860
height: 0.75rem;
5961
}

packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.js

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {useRef} from 'react';
1414

1515
import styles from './SuspenseScrubber.css';
1616

17+
import Tooltip from '../Components/reach-ui/tooltip';
18+
1719
export default function SuspenseScrubber({
1820
min,
1921
max,
@@ -53,24 +55,38 @@ export default function SuspenseScrubber({
5355
const steps = [];
5456
for (let index = min; index <= max; index++) {
5557
steps.push(
56-
<div
58+
<Tooltip
5759
key={index}
58-
className={
59-
styles.SuspenseScrubberStep +
60-
(highlight === index
61-
? ' ' + styles.SuspenseScrubberStepHighlight
62-
: '')
63-
}
64-
onPointerDown={handlePress.bind(null, index)}
65-
onMouseEnter={onHoverSegment.bind(null, index)}>
60+
label={
61+
index === min
62+
? // The first step in the timeline is always a Transition (Initial Paint).
63+
// TODO: Support multiple environments.
64+
'Initial Paint'
65+
: // TODO: Consider adding the name of this specific boundary if this step has only one.
66+
'Suspense'
67+
}>
6668
<div
6769
className={
68-
index <= value
69-
? styles.SuspenseScrubberBeadSelected
70-
: styles.SuspenseScrubberBead
70+
styles.SuspenseScrubberStep +
71+
(highlight === index
72+
? ' ' + styles.SuspenseScrubberStepHighlight
73+
: '')
7174
}
72-
/>
73-
</div>,
75+
onPointerDown={handlePress.bind(null, index)}
76+
onMouseEnter={onHoverSegment.bind(null, index)}>
77+
<div
78+
className={
79+
styles.SuspenseScrubberBead +
80+
(index === min
81+
? // The first step in the timeline is always a Transition (Initial Paint).
82+
// TODO: Support multiple environments.
83+
' ' + styles.SuspenseScrubberBeadTransition
84+
: '') +
85+
(index <= value ? ' ' + styles.SuspenseScrubberBeadSelected : '')
86+
}
87+
/>
88+
</div>
89+
</Tooltip>,
7490
);
7591
}
7692

0 commit comments

Comments
 (0)