[DevTools] - Highlight rendered by elements on hover. (#18479)

* [DevTools] - Highlight rendered by elements on hover.

* Fixed formatting issue.

* DevTools - Extracted highlight logic to custom hook. Added highlight support for rendered by elements.

* Removed unnecessary padding style

* Removed unnecessary wrapper function.

Co-authored-by: Brian Vaughn <[email protected]>
This commit is contained in:
Hristo Kanchev
2020-04-03 10:49:49 -07:00
committed by GitHub
co-authored by Brian Vaughn
parent 5001857d6f
commit 057a0aaf4f
4 changed files with 74 additions and 32 deletions
@@ -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;
}
}
@@ -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 (
<Button
key={id}
className={styles.OwnerButton}
disabled={!isInStore}
onClick={handleClick}>
<span
className={`${styles.Owner} ${isInStore ? '' : styles.NotInStore}`}
title={displayName}>
{displayName}
onClick={handleClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}>
<span className={styles.OwnerContent}>
<span
className={`${styles.Owner} ${isInStore ? '' : styles.NotInStore}`}
title={displayName}>
{displayName}
</span>
<Badge hocDisplayNames={hocDisplayNames} type={type} />
</span>
<Badge hocDisplayNames={hocDisplayNames} type={type} />
</Button>
);
}
@@ -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<HTMLDivElement | null>(null);
const focusTargetRef = useRef<HTMLDivElement | null>(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.
@@ -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<Value>({
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,
};
}