@samitouri / QOS-React-1 / commits / bb8a76c6cc

[DevTools] Show fallback in inspected element pane when no element is selected (#35503)

Sebastian "Sebbie" Silbermann committed Jan 15, 2026 at 14:28 UTC bb8a76c6cc77ea2976d690ea09f5a1b3d9b1792a
7 files changed +24 -4
packages/react-devtools-shared/src/devtools/views/Components/Components.css
+2
@@ -22,6 +22,7 @@
22 flex: 1 1 35%;
23 overflow-x: hidden;
24 overflow-y: auto;
25 + border-left: 1px solid var(--color-border);
26 }
27
28 .ResizeBarWrapper {
@@ -55,6 +56,7 @@
56
57 .InspectedElementWrapper {
58 flex: 1 1 50%;
59 + border-left: none;
60 }
61
62 .ResizeBar {
packages/react-devtools-shared/src/devtools/views/Components/Components.js
+5 -1
@@ -159,7 +159,11 @@ function Components(_: {}) {
159 <div className={styles.InspectedElementWrapper}>
160 <NativeStyleContextController>
161 <InspectedElementErrorBoundary>
162 - <InspectedElement />
162 + <InspectedElement
163 + fallbackEmpty={
164 + 'No React element selected. Select an element in the tree to inspect.'
165 + }
166 + />
167 </InspectedElementErrorBoundary>
168 </NativeStyleContextController>
169 </div>
packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.css
+5 -2
@@ -3,7 +3,6 @@
3 flex-direction: column;
4 height: 100%;
5 width: 100%;
6 - border-left: 1px solid var(--color-border);
6 border-top: 1px solid var(--color-border);
7 }
8
@@ -69,7 +68,11 @@
68 padding: 0.25rem;
69 color: var(--color-dimmer);
70 font-style: italic;
72 - border-left: 1px solid var(--color-border);
71 +}
72 +
73 +.NoInspectionFallback {
74 + padding: 0.25rem;
75 + font-style: italic;
76 }
77
78 .StrictModeNonCompliant {
packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js
+4
@@ -36,6 +36,8 @@ import Tooltip from './reach-ui/tooltip';
36
37 export type Props = {
38 actionButtons?: React.Node,
39 + /** fallback to show when no element is inspected */
40 + fallbackEmpty: React.Node,
41 };
42
43 // TODO Make edits and deletes also use transition API!
@@ -44,6 +46,7 @@ const noSourcePromise = Promise.resolve(null);
46
47 export default function InspectedElementWrapper({
48 actionButtons,
49 + fallbackEmpty,
50 }: Props): React.Node {
51 const {inspectedElementID} = useContext(TreeStateContext);
52 const bridge = useContext(BridgeContext);
@@ -193,6 +196,7 @@ export default function InspectedElementWrapper({
196 return (
197 <div className={styles.InspectedElement}>
198 <div className={styles.TitleRow} />
199 + <div className={styles.NoInspectionFallback}>{fallbackEmpty}</div>
200 </div>
201 );
202 }
packages/react-devtools-shared/src/devtools/views/InspectedElement/InspectedElementPane.js
+1
@@ -25,6 +25,7 @@ function InspectedElementPane() {
25 <div className={styles.InspectedElementPane}>
26 <InspectedElement
27 actionButtons={!hideSettings && <SettingsModalContextToggle />}
28 + fallbackEmpty={"Selected element wasn't rendered with React."}
29 />
30 <SettingsModal />
31 </div>
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.css
+2
@@ -35,6 +35,7 @@
35 flex: 0 0 calc(100% - var(--horizontal-resize-tree-percentage));
36 overflow-x: hidden;
37 overflow-y: auto;
38 + border-left: 1px solid var(--color-border);
39 }
40
41 .ResizeBarWrapper {
@@ -70,6 +71,7 @@
71
72 .InspectedElementWrapper {
73 flex: 0 0 calc(100% - var(--vertical-resize-tree-percentage));
74 + border-left: none;
75 }
76
77 .TreeWrapper + .ResizeBarWrapper .ResizeBar {
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTab.js
+5 -1
@@ -543,7 +543,11 @@ function SuspenseTab(_: {}) {
543 className={styles.InspectedElementWrapper}
544 hidden={inspectedElementHidden}>
545 <InspectedElementErrorBoundary>
546 - <InspectedElement />
546 + <InspectedElement
547 + fallbackEmpty={
548 + 'No React element selected. Select a Suspense boundary in the minimap to inspect.'
549 + }
550 + />
551 </InspectedElementErrorBoundary>
552 </div>
553 <SettingsModal />