Repository: facebook/react
Pull request: [DevTools] Linkify Source View

This makes it so you can click the source location itself to view the source. This is similar styling as the link to jump to function props like events and actions. We're going to need a lot more linkifying to jump to various source locations. Also, I always was trying to click this file anyway.

Hover state:

<img width="485" height="382" alt="Screenshot 2025-07-21 at 4 36 10 PM" src="https://github.com/user-attachments/assets/1f0f8f8c-6866-4e62-ab84-1fb5ba012986" />


Changed files:
filename: packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSourcePanel.css
patch: @@ -18,3 +18,18 @@
   max-width: 100%;
   margin-left: 1rem;
 }
+
+.Link {
+  color: var(--color-link);
+  white-space: pre;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  flex: 1;
+  cursor: pointer;
+  border-radius: 0.125rem;
+  padding: 0px 2px;
+}
+
+.Link:hover {
+  background-color: var(--color-background-hover);
+}

filename: packages/react-devtools-shared/src/devtools/views/Components/InspectedElementSourcePanel.js
patch: @@ -8,6 +8,7 @@
  */
 
 import * as React from 'react';
+import {useCallback, useContext} from 'react';
 import {copy} from 'clipboard-js';
 import {toNormalUrl} from 'jsc-safe-url';
 
@@ -16,6 +17,8 @@ import ButtonIcon from '../ButtonIcon';
 import Skeleton from './Skeleton';
 import {withPermissionsCheck} from 'react-devtools-shared/src/frontend/utils/withPermissionsCheck';
 
+import ViewElementSourceContext from './ViewElementSourceContext';
+
 import type {Source as InspectedElementSource} from 'react-devtools-shared/src/shared/types';
 import styles from './InspectedElementSourcePanel.css';
 
@@ -87,25 +90,45 @@ function CopySourceButton({source, symbolicatedSourcePromise}: Props) {
 
 function FormattedSourceString({source, symbolicatedSourcePromise}: Props) {
   const symbolicatedSource = React.use(symbolicatedSourcePromise);
-  if (symbolicatedSource == null) {
-    const {sourceURL, line} = source;
 
-    return (
-      <div
-        className={styles.SourceOneLiner}
-        data-testname="InspectedElementView-FormattedSourceString">
-        {formatSourceForDisplay(sourceURL, line)}
-      </div>
-    );
-  }
+  const {canViewElementSourceFunction, viewElementSourceFunction} = useContext(
+    ViewElementSourceContext,
+  );
+
+  // In some cases (e.g. FB internal usage) the standalone shell might not be able to view the source.
+  // To detect this case, we defer to an injected helper function (if present).
+  const linkIsEnabled =
+    viewElementSourceFunction != null &&
+    source != null &&
+    (canViewElementSourceFunction == null ||
+      canViewElementSourceFunction(source, symbolicatedSource));
+
+  const viewSource = useCallback(() => {
+    if (viewElementSourceFunction != null && source != null) {
+      viewElementSourceFunction(source, symbolicatedSource);
+    }
+  }, [source, symbolicatedSource]);
 
-  const {sourceURL, line} = symbolicatedSource;
+  let sourceURL, line;
+  if (symbolicatedSource == null) {
+    sourceURL = source.sourceURL;
+    line = source.line;
+  } else {
+    sourceURL = symbolicatedSource.sourceURL;
+    line = symbolicatedSource.line;
+  }
 
   return (
     <div
       className={styles.SourceOneLiner}
       data-testname="InspectedElementView-FormattedSourceString">
-      {formatSourceForDisplay(sourceURL, line)}
+      {linkIsEnabled ? (
+        <span className={styles.Link} onClick={viewSource}>
+          {formatSourceForDisplay(sourceURL, line)}
+        </span>
+      ) : (
+        formatSourceForDisplay(sourceURL, line)
+      )}
     </div>
   );
 }