Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function setReactSelectionFromBrowser(bridge) {
return;
}

// Remember to sync the selection next time we show Components tab.
// Remember to sync the selection next time we show inspected element
bridge.send('syncSelectionFromBuiltinElementsPanel');
}
},
Expand Down
49 changes: 49 additions & 0 deletions packages/react-devtools-extensions/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ function createBridgeAndStore() {
bridge,
browserTheme: getBrowserTheme(),
componentsPortalContainer,
inspectedElementPortalContainer,
profilerPortalContainer,
editorPortalContainer,
currentSelectedSource,
Expand Down Expand Up @@ -278,6 +279,51 @@ function createComponentsPanel() {
);
}

function createElementsInspectPanel() {
if (inspectedElementPortalContainer) {
// Panel is created and user opened it at least once
ensureInitialHTMLIsCleared(inspectedElementPortalContainer);
render();

return;
}

if (inspectedElementPane) {
// Panel is created, but wasn't opened yet, so no document is present for it
return;
}

const elementsPanel = chrome.devtools.panels.elements;
if (__IS_FIREFOX__ || !elementsPanel || !elementsPanel.createSidebarPane) {
// Firefox will not pass the window to the onShown listener despite setPage
// being called.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=2010549

// May not be supported in some browsers.
// See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/panels/ElementsPanel/createSidebarPane#browser_compatibility
return;
}

elementsPanel.createSidebarPane('React Element ⚛', createdPane => {
inspectedElementPane = createdPane;

createdPane.setPage('panel.html');
createdPane.setHeight('75px');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it used as a min-height or how does this work? Might be worth double-checking the case when an element has a long list of props or hooks.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was copied from the added sources pane. Though it's not supported in Firefox: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools/panels/ExtensionSidebarPane#browser_compatibility

I follow-up on this since whatever change we make, should affect all ExtensionSidebarPane.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually will do this now since I can't test Firefox otherwise.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do in a follow-up since Firefox support is blocked by https://bugzilla.mozilla.org/show_bug.cgi?id=2010549


createdPane.onShown.addListener(portal => {
inspectedElementPortalContainer = portal.container;
if (inspectedElementPortalContainer != null && render) {
ensureInitialHTMLIsCleared(inspectedElementPortalContainer);

render();
portal.injectStyles(cloneStyleTags);

logEvent({event_name: 'selected-inspected-element-pane'});
}
});
});
}

function createProfilerPanel() {
if (profilerPortalContainer) {
// Panel is created and user opened it at least once
Expand Down Expand Up @@ -508,6 +554,7 @@ function mountReactDevTools() {
createComponentsPanel();
createProfilerPanel();
createSourcesEditorPanel();
createElementsInspectPanel();
// Suspense Tab is created via the hook
// TODO(enableSuspenseTab): Create eagerly once Suspense tab is stable
}
Expand Down Expand Up @@ -556,10 +603,12 @@ let componentsPanel = null;
let profilerPanel = null;
let suspensePanel = null;
let editorPane = null;
let inspectedElementPane = null;
let componentsPortalContainer = null;
let profilerPortalContainer = null;
let suspensePortalContainer = null;
let editorPortalContainer = null;
let inspectedElementPortalContainer = null;

let mostRecentOverrideTab = null;
let render = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,11 @@
padding: 0.25rem;
color: var(--color-console-error-icon);
}

.VRule {
height: 20px;
width: 1px;
flex: 0 0 1px;
margin: 0 0.5rem;
background-color: var(--color-border);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ import useEditorURL from '../useEditorURL';
import styles from './InspectedElement.css';
import Tooltip from './reach-ui/tooltip';

export type Props = {};
export type Props = {
actionButtons?: React.Node,
};

// TODO Make edits and deletes also use transition API!

const noSourcePromise = Promise.resolve(null);

export default function InspectedElementWrapper(_: Props): React.Node {
export default function InspectedElementWrapper({
actionButtons,
}: Props): React.Node {
const {inspectedElementID} = useContext(TreeStateContext);
const bridge = useContext(BridgeContext);
const store = useContext(StoreContext);
Expand Down Expand Up @@ -305,6 +309,13 @@ export default function InspectedElementWrapper(_: Props): React.Node {
symbolicatedSourcePromise={symbolicatedSourcePromise}
/>
)}

{actionButtons && (
<>
<div className={styles.VRule} />
{actionButtons}
</>
)}
</div>

{inspectedElement === null && (
Expand Down
11 changes: 11 additions & 0 deletions packages/react-devtools-shared/src/devtools/views/DevTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Profiler from './Profiler/Profiler';
import SuspenseTab from './SuspenseTab/SuspenseTab';
import TabBar from './TabBar';
import EditorPane from './Editor/EditorPane';
import InspectedElementPane from './InspectedElement/InspectedElementPane';
import {SettingsContextController} from './Settings/SettingsContext';
import {TreeContextController} from './Components/TreeContext';
import ViewElementSourceContext from './Components/ViewElementSourceContext';
Expand Down Expand Up @@ -100,6 +101,7 @@ export type Props = {
// The root <DevTools> app is rendered in the top-level extension window,
// but individual tabs (e.g. Components, Profiling) can be rendered into portals within their browser panels.
componentsPortalContainer?: Element,
inspectedElementPortalContainer?: Element,
profilerPortalContainer?: Element,
suspensePortalContainer?: Element,
editorPortalContainer?: Element,
Expand Down Expand Up @@ -155,6 +157,7 @@ export default function DevTools({
canViewElementSourceFunction,
componentsPortalContainer,
editorPortalContainer,
inspectedElementPortalContainer,
profilerPortalContainer,
suspensePortalContainer,
currentSelectedSource,
Expand Down Expand Up @@ -379,6 +382,14 @@ export default function DevTools({
portalContainer={editorPortalContainer}
/>
) : null}
{inspectedElementPortalContainer ? (
<InspectedElementPane
selectedSource={currentSelectedSource}
portalContainer={
inspectedElementPortalContainer
}
/>
) : null}
</ThemeProvider>
</SuspenseTreeContextController>
</InspectedElementContextController>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.InspectedElementPane, .InspectedElementPane * {
box-sizing: border-box;
-webkit-font-smoothing: var(--font-smoothing);
}

.InspectedElementPane {
position: relative;
width: 100%;
height: 100%;
display: flex;
flex-direction: row;
background-color: var(--color-background);
color: var(--color-text);
font-family: var(--font-family-sans);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import * as React from 'react';
import {useContext} from 'react';

import portaledContent from 'react-devtools-shared/src/devtools/views/portaledContent';
import {OptionsContext} from 'react-devtools-shared/src/devtools/views/context';
import InspectedElement from 'react-devtools-shared/src/devtools/views/Components/InspectedElement';
import SettingsModal from 'react-devtools-shared/src/devtools/views/Settings/SettingsModal';
import SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle';
import {SettingsModalContextController} from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContext';
import styles from './InspectedElementPane.css';

function InspectedElementPane() {
const {hideSettings} = useContext(OptionsContext);
return (
<SettingsModalContextController>
<div className={styles.InspectedElementPane}>
<InspectedElement
actionButtons={!hideSettings && <SettingsModalContextToggle />}
/>
<SettingsModal />
</div>
</SettingsModalContextController>
);
}
export default (portaledContent(InspectedElementPane): component());
Loading