[DevTools] Render selected outline on top of every other rect (#35012)

When rects are close together (or overlapping) the outline can end up
being covered up by sibling rects or deeper rects. This renders the
selected outline on top of everything so it's always visible.

<img width="275" height="730" alt="Screenshot 2025-10-29 at 8 43 28 PM"
src="https://github.com/user-attachments/assets/69224883-f548-45ec-ada1-1a04ec17eaf5"
/>
<img width="266" height="737" alt="Screenshot 2025-10-29 at 8 58 53 PM"
src="https://github.com/user-attachments/assets/946f7dde-450d-49fd-9fbd-57487f67f461"
/>

Additionally, this makes it so that it's not part of the translucent
tree when things are hidden by the timeline. That way it's easier to see
what is selected inside a hidden tree.

<img width="498" height="196" alt="Screenshot 2025-10-29 at 8 45 24 PM"
src="https://github.com/user-attachments/assets/723107ab-a92c-42c2-8a7d-a548ac3332d0"
/>
<img width="571" height="735" alt="Screenshot 2025-10-29 at 8 59 06 PM"
src="https://github.com/user-attachments/assets/d653f1a7-4096-45c3-b92a-ef155d4742e6"
/>
This commit is contained in:
Sebastian Markbåge 2025-10-30 15:26:49 -04:00 committed by GitHub
parent 3a0ab8a7ee
commit 6fb7754494
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 14 deletions

View File

@ -6,12 +6,6 @@
border-radius: 0.25rem;
}
.SuspenseRectsContainer[data-highlighted='true'] {
outline-color: var(--color-transition);
outline-style: solid;
outline-width: 4px;
}
.SuspenseRectsRoot {
cursor: pointer;
outline-color: var(--color-transition);
@ -106,6 +100,10 @@
pointer-events: none;
}
.SuspenseRectOutlineRoot {
outline-color: var(--color-transition);
}
.SuspenseRectsBoundary[data-selected='true'] > .SuspenseRectsRect {
box-shadow: none;
}

View File

@ -236,13 +236,6 @@ function SuspenseRects({
<span>{suspense.name}</span>
</ScaledRect>
) : null}
{selected && visible ? (
<ScaledRect
className={styles.SuspenseRectOutline}
rect={boundingBox}
adjust={true}
/>
) : null}
</ViewBox.Provider>
</ScaledRect>
);
@ -514,6 +507,28 @@ function SuspenseRectsContainer({
scaleRef.current = boundingBoxWidth;
}, [boundingBoxWidth]);
let selectedBoundingBox = null;
let selectedEnvironment = null;
if (isRootSelected) {
selectedBoundingBox = boundingBox;
selectedEnvironment = rootEnvironment;
} else if (inspectedElementID !== null) {
const selectedSuspenseNode = store.getSuspenseByID(inspectedElementID);
if (
selectedSuspenseNode !== null &&
(selectedSuspenseNode.hasUniqueSuspenders || !uniqueSuspendersOnly)
) {
selectedBoundingBox = getBoundingBox(selectedSuspenseNode.rects);
for (let i = 0; i < timeline.length; i++) {
const timelineStep = timeline[i];
if (timelineStep.id === inspectedElementID) {
selectedEnvironment = timelineStep.environment;
break;
}
}
}
}
return (
<div
className={
@ -524,7 +539,6 @@ function SuspenseRectsContainer({
}
onClick={handleClick}
onDoubleClick={handleDoubleClick}
data-highlighted={isRootSelected}
data-hovered={isRootHovered}>
<ViewBox.Provider value={boundingBox}>
<div
@ -533,6 +547,18 @@ function SuspenseRectsContainer({
{roots.map(rootID => {
return <SuspenseRectsRoot key={rootID} rootID={rootID} />;
})}
{selectedBoundingBox !== null ? (
<ScaledRect
className={
styles.SuspenseRectOutline +
(isRootSelected ? ' ' + styles.SuspenseRectOutlineRoot : '') +
' ' +
getClassNameForEnvironment(selectedEnvironment)
}
rect={selectedBoundingBox}
adjust={true}
/>
) : null}
</div>
</ViewBox.Provider>
</div>