Skip to content

Commit 6b7281e

Browse files
kerollozbvaughn
andauthored
[DevTools] Add shortcut keys for tab switching (#18248)
* [DevTools] Add shortcut keys for tab switching * Use LocalStorage to remember most recently selected tab Resolves #18227 and #18226 Co-authored-by: Brian Vaughn <[email protected]>
1 parent 5152c4a commit 6b7281e

File tree

1 file changed

+45
-5
lines changed
  • packages/react-devtools-shared/src/devtools/views

1 file changed

+45
-5
lines changed

packages/react-devtools-shared/src/devtools/views/DevTools.js

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import '@reach/menu-button/styles.css';
1313
import '@reach/tooltip/styles.css';
1414

1515
import * as React from 'react';
16-
import {useEffect, useMemo, useState} from 'react';
16+
import {useEffect, useMemo, useRef} from 'react';
1717
import Store from '../store';
1818
import {BridgeContext, ContextMenuContext, StoreContext} from './context';
1919
import Components from './Components/Components';
@@ -27,6 +27,7 @@ import {ModalDialogContextController} from './ModalDialog';
2727
import ReactLogo from './ReactLogo';
2828
import UnsupportedVersionDialog from './UnsupportedVersionDialog';
2929
import WarnIfLegacyBackendDetected from './WarnIfLegacyBackendDetected';
30+
import {useLocalStorage} from './hooks';
3031

3132
import styles from './DevTools.css';
3233

@@ -106,9 +107,13 @@ export default function DevTools({
106107
viewAttributeSourceFunction,
107108
viewElementSourceFunction,
108109
}: Props) {
109-
const [tab, setTab] = useState(defaultTab);
110-
if (overrideTab != null && overrideTab !== tab) {
111-
setTab(overrideTab);
110+
let [tab, setTab] = useLocalStorage<TabID>(
111+
'React::DevTools::defaultTab',
112+
defaultTab,
113+
);
114+
115+
if (overrideTab != null) {
116+
tab = overrideTab;
112117
}
113118

114119
const viewElementSource = useMemo(
@@ -127,6 +132,41 @@ export default function DevTools({
127132
[enabledInspectedElementContextMenu, viewAttributeSourceFunction],
128133
);
129134

135+
const devToolsRef = useRef<HTMLElement | null>(null);
136+
137+
useEffect(() => {
138+
if (!showTabBar) {
139+
return;
140+
}
141+
142+
const div = devToolsRef.current;
143+
if (div === null) {
144+
return;
145+
}
146+
147+
const ownerWindow = div.ownerDocument.defaultView;
148+
const handleKeyDown = (event: KeyboardEvent) => {
149+
if (event.ctrlKey || event.metaKey) {
150+
switch (event.key) {
151+
case '1':
152+
setTab(tabs[0].id);
153+
event.preventDefault();
154+
event.stopPropagation();
155+
break;
156+
case '2':
157+
setTab(tabs[1].id);
158+
event.preventDefault();
159+
event.stopPropagation();
160+
break;
161+
}
162+
}
163+
};
164+
ownerWindow.addEventListener('keydown', handleKeyDown);
165+
return () => {
166+
ownerWindow.removeEventListener('keydown', handleKeyDown);
167+
};
168+
}, [showTabBar]);
169+
130170
useEffect(() => {
131171
return () => {
132172
try {
@@ -149,7 +189,7 @@ export default function DevTools({
149189
<ViewElementSourceContext.Provider value={viewElementSource}>
150190
<TreeContextController>
151191
<ProfilerContextController>
152-
<div className={styles.DevTools}>
192+
<div className={styles.DevTools} ref={devToolsRef}>
153193
{showTabBar && (
154194
<div className={styles.TabBar}>
155195
<ReactLogo />

0 commit comments

Comments
 (0)