diff --git a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css index d1bb28f19706..eaf5ac4a33a3 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.css @@ -82,7 +82,6 @@ .Owner { border-radius: 0.25rem; padding: 0.125rem 0.25rem; - cursor: pointer; background: none; border: none; display: block; @@ -107,12 +106,23 @@ } .OwnerButton { + cursor: pointer; + width: 100%; + padding: 0; +} + +.OwnerContent { display: flex; align-items: center; - margin-left: 0.5rem; - padding: 0; + padding-left: 1rem; + width: 100%; + border-radius: 0.25rem; +} + +.OwnerContent:hover { + background-color: var(--color-background-hover); } .ContextMenuIcon { margin-right: 0.5rem; -} \ No newline at end of file +} diff --git a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js index f65b8e0a777e..5424d35039cb 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/SelectedElement.js @@ -26,6 +26,7 @@ import ViewElementSourceContext from './ViewElementSourceContext'; import NativeStyleEditor from './NativeStyleEditor'; import Toggle from '../Toggle'; import Badge from './Badge'; +import {useHighlightNativeElement} from '../hooks'; import { ComponentFilterElementType, ElementTypeClass, @@ -522,6 +523,10 @@ function OwnerView({ type, }: OwnerViewProps) { const dispatch = useContext(TreeDispatcherContext); + const { + highlightNativeElement, + clearHighlightNativeElement, + } = useHighlightNativeElement(); const handleClick = useCallback( () => @@ -532,18 +537,26 @@ function OwnerView({ [dispatch, id], ); + const onMouseEnter = () => highlightNativeElement(id); + + const onMouseLeave = clearHighlightNativeElement; + return ( ); } diff --git a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js index 43114cd4d965..dc0d5bb3dd63 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/Tree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/Tree.js @@ -30,6 +30,7 @@ import SearchInput from './SearchInput'; import SettingsModalContextToggle from 'react-devtools-shared/src/devtools/views/Settings/SettingsModalContextToggle'; import SelectedTreeHighlight from './SelectedTreeHighlight'; import TreeFocusedContext from './TreeFocusedContext'; +import {useHighlightNativeElement} from '../hooks'; import styles from './Tree.css'; @@ -61,6 +62,10 @@ export default function Tree(props: Props) { const [isNavigatingWithKeyboard, setIsNavigatingWithKeyboard] = useState( false, ); + const { + highlightNativeElement, + clearHighlightNativeElement, + } = useHighlightNativeElement(); const treeRef = useRef(null); const focusTargetRef = useRef(null); @@ -205,24 +210,6 @@ export default function Tree(props: Props) { [dispatch, selectedElementID], ); - const highlightNativeElement = useCallback( - (id: number) => { - const element = store.getElementByID(id); - const rendererID = store.getRendererIDForElement(id); - if (element !== null && rendererID !== null) { - bridge.send('highlightNativeElement', { - displayName: element.displayName, - hideAfterTimeout: false, - id, - openNativeElementsPanel: false, - rendererID, - scrollIntoView: false, - }); - } - }, - [store, bridge], - ); - // If we switch the selected element while using the keyboard, // start highlighting it in the DOM instead of the last hovered node. const searchRef = useRef({searchIndex, searchResults}); @@ -240,7 +227,7 @@ export default function Tree(props: Props) { if (selectedElementID !== null) { highlightNativeElement(selectedElementID); } else { - bridge.send('clearNativeElementHighlight'); + clearHighlightNativeElement(); } } }, [ @@ -270,9 +257,7 @@ export default function Tree(props: Props) { setIsNavigatingWithKeyboard(false); }, []); - const handleMouseLeave = useCallback(() => { - bridge.send('clearNativeElementHighlight'); - }, [bridge]); + const handleMouseLeave = clearHighlightNativeElement; // Let react-window know to re-render any time the underlying tree data changes. // This includes the owner context, since it controls a filtered view of the tree. diff --git a/packages/react-devtools-shared/src/devtools/views/hooks.js b/packages/react-devtools-shared/src/devtools/views/hooks.js index cace5451df58..3af0ceaeb29a 100644 --- a/packages/react-devtools-shared/src/devtools/views/hooks.js +++ b/packages/react-devtools-shared/src/devtools/views/hooks.js @@ -14,11 +14,13 @@ import { useLayoutEffect, useReducer, useState, + useContext, } from 'react'; import { localStorageGetItem, localStorageSetItem, } from 'react-devtools-shared/src/storage'; +import {StoreContext, BridgeContext} from './context'; import {sanitizeForParse, smartParse, smartStringify} from '../utils'; type ACTION_RESET = {| @@ -301,3 +303,35 @@ export function useSubscription({ return state.value; } + +export function useHighlightNativeElement() { + const bridge = useContext(BridgeContext); + const store = useContext(StoreContext); + + const highlightNativeElement = useCallback( + (id: number) => { + const element = store.getElementByID(id); + const rendererID = store.getRendererIDForElement(id); + if (element !== null && rendererID !== null) { + bridge.send('highlightNativeElement', { + displayName: element.displayName, + hideAfterTimeout: false, + id, + openNativeElementsPanel: false, + rendererID, + scrollIntoView: false, + }); + } + }, + [store, bridge], + ); + + const clearHighlightNativeElement = useCallback(() => { + bridge.send('clearNativeElementHighlight'); + }, [bridge]); + + return { + highlightNativeElement, + clearHighlightNativeElement, + }; +}