From 2821c9c229050757a7e554737dadfb3726920f40 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 16 Oct 2025 00:14:25 -0400 Subject: [PATCH 1/5] Redesign --- .../views/SuspenseTab/SuspenseRects.css | 42 +++++++++++++++---- .../views/SuspenseTab/SuspenseRects.js | 2 +- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css index 591d908735efb..f050050ab4390 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css @@ -1,12 +1,20 @@ .SuspenseRectsContainer { padding: .25rem; cursor: pointer; - outline: 1px solid var(--color-component-name); + outline-color: #6a51b2ff; + outline-style: solid; + outline-width: 1px; border-radius: 0.25rem; + background-color: color-mix(in srgb, var(--color-background) 50%, #6a51b2ff 5%); +} + +.SuspenseRectsContainer:hover:not(:has(.SuspenseRectsBoundary:hover))[data-highlighted='false'] { + outline-width: 1px; } .SuspenseRectsContainer[data-highlighted='true'] { - background: var(--color-dimmest); + outline-style: solid; + outline-width: 4px; } .SuspenseRectsViewBox { @@ -15,6 +23,11 @@ .SuspenseRectsBoundary { pointer-events: all; + border-radius: 0.125rem; +} + +.SuspenseRectsBoundary[data-visible='false'] { + background-color: transparent; } .SuspenseRectsBoundaryChildren { @@ -28,15 +41,18 @@ .SuspenseRectsRect { box-shadow: var(--elevation-4); pointer-events: all; + cursor: pointer; + border-radius: 0.125rem; + background-color: color-mix(in srgb, var(--color-background) 50%, rgba(0, 136, 250, 1) 25%); + backdrop-filter: grayscale(100%); + transition: background-color 0.2s ease-in; + outline-color: #0088fa; outline-style: solid; outline-width: 1px; - border-radius: 0.125rem; - cursor: pointer; } .SuspenseRectsScaledRect { position: absolute; - outline-color: var(--color-background-selected); } .SuspenseRectsScaledRect[data-visible='false'] { @@ -49,10 +65,18 @@ } /* highlight this boundary */ -.SuspenseRectsBoundary:hover:not(:has(.SuspenseRectsBoundary:hover)) > .SuspenseRectsRect, .SuspenseRectsBoundary[data-highlighted='true'] > .SuspenseRectsRect { - background-color: var(--color-background-hover); +.SuspenseRectsBoundary:hover:not(:has(.SuspenseRectsBoundary:hover)) > .SuspenseRectsRect { + background-color: color-mix(in srgb, var(--color-background) 50%, rgba(0, 136, 250, 1) 50%); + transition: background-color 0.2s ease-out; +} + +.SuspenseRectsBoundary[data-highlighted='true'] { + outline-color: #0088fa; + outline-style: solid; + outline-width: 4px; + box-shadow: var(--elevation-4); } -.SuspenseRectsRect[data-highlighted='true'] { - background-color: var(--color-selected-tree-highlight-active); +.SuspenseRectsBoundary[data-highlighted='true'] > .SuspenseRectsRect { + box-shadow: none; } diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js index c2a131916504c..3808117ea2b7b 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js @@ -152,6 +152,7 @@ function SuspenseRects({ rect={boundingBox} className={styles.SuspenseRectsBoundary} visible={visible} + data-highlighted={selected} suspended={suspense.isSuspended}> {visible && @@ -162,7 +163,6 @@ function SuspenseRects({ key={index} className={styles.SuspenseRectsRect} rect={rect} - data-highlighted={selected} adjust={true} onClick={handleClick} onDoubleClick={handleDoubleClick} From 67503c65e30231ac20774ca7482a7109e86888d5 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 16 Oct 2025 13:43:59 -0400 Subject: [PATCH 2/5] The outline needs to be one pixel smaller since the rects inside are now one pixel smaller Need a separate element for this. --- .../src/devtools/views/SuspenseTab/SuspenseRects.css | 11 ++++++++--- .../src/devtools/views/SuspenseTab/SuspenseRects.js | 12 +++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css index f050050ab4390..2c4c9d28376a4 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css @@ -70,13 +70,18 @@ transition: background-color 0.2s ease-out; } -.SuspenseRectsBoundary[data-highlighted='true'] { +.SuspenseRectsBoundary[data-selected='true'] { + box-shadow: var(--elevation-4); +} + +.SuspenseRectOutline { outline-color: #0088fa; outline-style: solid; outline-width: 4px; - box-shadow: var(--elevation-4); + border-radius: 0.125rem; + pointer-events: none; } -.SuspenseRectsBoundary[data-highlighted='true'] > .SuspenseRectsRect { +.SuspenseRectsBoundary[data-selected='true'] > .SuspenseRectsRect { box-shadow: none; } diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js index 3808117ea2b7b..4a45187d7fde3 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.js @@ -36,6 +36,7 @@ function ScaledRect({ rect, visible, suspended, + selected, adjust, ...props }: { @@ -43,6 +44,7 @@ function ScaledRect({ rect: Rect, visible: boolean, suspended: boolean, + selected?: boolean, adjust?: boolean, ... }): React$Node { @@ -58,6 +60,7 @@ function ScaledRect({ className={styles.SuspenseRectsScaledRect + ' ' + className} data-visible={visible} data-suspended={suspended} + data-selected={selected} style={{ // Shrink one pixel so that the bottom outline will line up with the top outline of the next one. width: adjust ? 'calc(' + width + ' - 1px)' : width, @@ -152,7 +155,7 @@ function SuspenseRects({ rect={boundingBox} className={styles.SuspenseRectsBoundary} visible={visible} - data-highlighted={selected} + selected={selected} suspended={suspense.isSuspended}> {visible && @@ -182,6 +185,13 @@ function SuspenseRects({ })} )} + {selected ? ( + + ) : null} ); From a9fe95f791e57f1632bd1477feb3aeb28bc60f1b Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 16 Oct 2025 13:49:32 -0400 Subject: [PATCH 3/5] Adjust ghostly --- .../src/devtools/views/SuspenseTab/SuspenseRects.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css index 2c4c9d28376a4..d99e9915a0779 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css @@ -60,8 +60,8 @@ outline-width: 0; } -.SuspenseRectsScaledRect[data-suspended='true'] { - opacity: 0.3; +.SuspenseRectsBoundary[data-suspended='true'] { + opacity: 0.33; } /* highlight this boundary */ From f5c1f533d8df02421dbf051f4a45270521a7b0f7 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 16 Oct 2025 14:18:23 -0400 Subject: [PATCH 4/5] Create color schemes for various suspense environments --- .../src/devtools/constants.js | 20 +++++++++++++++---- .../InspectedElementSharedStyles.css | 4 ++-- .../views/SuspenseTab/SuspenseRects.css | 12 +++++------ .../views/SuspenseTab/SuspenseScrubber.css | 10 +++++----- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/constants.js b/packages/react-devtools-shared/src/devtools/constants.js index cfb73713b089e..4e24c8fae4af7 100644 --- a/packages/react-devtools-shared/src/devtools/constants.js +++ b/packages/react-devtools-shared/src/devtools/constants.js @@ -136,8 +136,6 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = { '--color-timeline-text-dim-color': '#ccc', '--color-timeline-react-work-border': '#eeeeee', '--color-timebar-background': '#f6f6f6', - '--color-timespan-background': '#62bc6a', - '--color-timespan-background-errored': '#d57066', '--color-search-match': 'yellow', '--color-search-match-current': '#f7923b', '--color-selected-tree-highlight-active': 'rgba(0, 136, 250, 0.1)', @@ -156,6 +154,14 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = { '--color-warning-text-color': '#ffffff', '--color-warning-text-color-inverted': '#fd4d69', + '--color-suspense': '#0088fa', + '--color-transition': '#6a51b2', + '--color-suspense-server': '#62bc6a', + '--color-transition-server': '#3f7844', + '--color-suspense-other': '#f3ce49', + '--color-transition-other': '#917b2c', + '--color-suspense-errored': '#d57066', + // The styles below should be kept in sync with 'root.css' // They are repeated there because they're used by e.g. tooltips or context menus // which get rendered outside of the DOM subtree (where normal theme/styles are written). @@ -290,8 +296,6 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = { '--color-timeline-text-dim-color': '#555b66', '--color-timeline-react-work-border': '#3d424a', '--color-timebar-background': '#1d2129', - '--color-timespan-background': '#62bc6a', - '--color-timespan-background-errored': '#d57066', '--color-search-match': 'yellow', '--color-search-match-current': '#f7923b', '--color-selected-tree-highlight-active': 'rgba(23, 143, 185, 0.15)', @@ -311,6 +315,14 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = { '--color-warning-text-color': '#ffffff', '--color-warning-text-color-inverted': '#ee1638', + '--color-suspense': '#0088fa', + '--color-transition': '#6a51b2', + '--color-suspense-server': '#62bc6a', + '--color-transition-server': '#3f7844', + '--color-suspense-other': '#f3ce49', + '--color-transition-other': '#917b2c', + '--color-suspense-errored': '#d57066', + // The styles below should be kept in sync with 'root.css' // They are repeated there because they're used by e.g. tooltips or context menus // which get rendered outside of the DOM subtree (where normal theme/styles are written). diff --git a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSharedStyles.css b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSharedStyles.css index 413554008fa53..6c56aec689986 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSharedStyles.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSharedStyles.css @@ -128,13 +128,13 @@ .TimeBarSpan, .TimeBarSpanErrored { position: absolute; border-radius: 0.125rem; - background-color: var(--color-timespan-background); + background-color: var(--color-suspense); width: 100%; height: 100%; } .TimeBarSpanErrored { - background-color: var(--color-timespan-background-errored); + background-color: var(--color-suspense-errored); } .SmallHeader { diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css index d99e9915a0779..16d385d75231c 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseRects.css @@ -1,11 +1,11 @@ .SuspenseRectsContainer { padding: .25rem; cursor: pointer; - outline-color: #6a51b2ff; + outline-color: var(--color-transition); outline-style: solid; outline-width: 1px; border-radius: 0.25rem; - background-color: color-mix(in srgb, var(--color-background) 50%, #6a51b2ff 5%); + background-color: color-mix(in srgb, var(--color-transition) 5%, transparent); } .SuspenseRectsContainer:hover:not(:has(.SuspenseRectsBoundary:hover))[data-highlighted='false'] { @@ -43,10 +43,10 @@ pointer-events: all; cursor: pointer; border-radius: 0.125rem; - background-color: color-mix(in srgb, var(--color-background) 50%, rgba(0, 136, 250, 1) 25%); + background-color: color-mix(in srgb, var(--color-background) 50%, var(--color-suspense) 25%); backdrop-filter: grayscale(100%); transition: background-color 0.2s ease-in; - outline-color: #0088fa; + outline-color: var(--color-suspense); outline-style: solid; outline-width: 1px; } @@ -66,7 +66,7 @@ /* highlight this boundary */ .SuspenseRectsBoundary:hover:not(:has(.SuspenseRectsBoundary:hover)) > .SuspenseRectsRect { - background-color: color-mix(in srgb, var(--color-background) 50%, rgba(0, 136, 250, 1) 50%); + background-color: color-mix(in srgb, var(--color-background) 50%, var(--color-suspense) 50%); transition: background-color 0.2s ease-out; } @@ -75,7 +75,7 @@ } .SuspenseRectOutline { - outline-color: #0088fa; + outline-color: var(--color-suspense); outline-style: solid; outline-width: 4px; border-radius: 0.125rem; diff --git a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css index 932a23103f1a3..93740531a2139 100644 --- a/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css +++ b/packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseScrubber.css @@ -40,22 +40,22 @@ .SuspenseScrubberBead { flex: 1; height: 0.5rem; - background: var(--color-background-selected); border-radius: 0.5rem; - background: var(--color-selected-tree-highlight-active); - transition: all 0.3s ease-in-out; + background: color-mix(in srgb, var(--color-suspense) 10%, transparent); + transition: all 0.3s ease-in; } .SuspenseScrubberBeadSelected { height: 1rem; - background: var(--color-background-selected); + background: var(--color-suspense); } .SuspenseScrubberBeadTransition { - background: var(--color-component-name); + background: var(--color-transition); } .SuspenseScrubberStepHighlight > .SuspenseScrubberBead, .SuspenseScrubberStep:hover > .SuspenseScrubberBead { height: 0.75rem; + transition: all 0.3s ease-out; } From e70e1163f1689e247ea5adb6db632f93dbc1a91e Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Thu, 16 Oct 2025 14:37:19 -0400 Subject: [PATCH 5/5] Use the blueish green for "suspense" in dark mode This matches more the text that we use elsewhere. This might be too close to the green used by "server" now. --- packages/react-devtools-shared/src/devtools/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/constants.js b/packages/react-devtools-shared/src/devtools/constants.js index 4e24c8fae4af7..5c90501d70f5c 100644 --- a/packages/react-devtools-shared/src/devtools/constants.js +++ b/packages/react-devtools-shared/src/devtools/constants.js @@ -315,7 +315,7 @@ export const THEME_STYLES: {[style: Theme | DisplayDensity]: any, ...} = { '--color-warning-text-color': '#ffffff', '--color-warning-text-color-inverted': '#ee1638', - '--color-suspense': '#0088fa', + '--color-suspense': '#61dafb', '--color-transition': '#6a51b2', '--color-suspense-server': '#62bc6a', '--color-transition-server': '#3f7844',