@samitouri / QOS-React-2 / commits / f14a2fd05c

Use @reach tooltips for TabBar, cleanup supports-profiling subscription

Brian Vaughn committed May 22, 2019 at 18:44 UTC f14a2fd05cfb2d7fc140f1f59e1fd580c25b6a27
3 files changed +66 -64
src/devtools/store.js
+2 -1
@@ -865,8 +865,9 @@ export default class Store extends EventEmitter {
865 if (hasOwnerMetadata) {
866 this._hasOwnerMetadata = true;
867 }
868 - if (supportsProfiling) {
868 + if (!this._supportsProfiling && supportsProfiling) {
869 this._supportsProfiling = true;
870 + this.emit('supportsProfiling');
871 }
872 }
873 );
src/devtools/views/DevTools.js
+16 -28
@@ -5,7 +5,7 @@
5 import '@reach/menu-button/styles.css';
6 import '@reach/tooltip/styles.css';
7
8 -import React, { useEffect, useState } from 'react';
8 +import React, { useMemo, useState } from 'react';
9 import Store from '../store';
10 import { BridgeContext, StoreContext } from './context';
11 import Components from './Components/Components';
@@ -18,6 +18,7 @@ import ViewElementSourceContext from './Components/ViewElementSourceContext';
18 import { ProfilerContextController } from './Profiler/ProfilerContext';
19 import { ModalDialogContextController } from './ModalDialog';
20 import ReactLogo from './ReactLogo';
21 +import { useSubscription } from './hooks';
22
23 import styles from './DevTools.css';
24
@@ -71,8 +72,7 @@ const settingsTab = {
72 title: 'React Settings',
73 };
74
74 -const tabsWithProfiler = [componentsTab, profilerTab, settingsTab];
75 -const tabsWithoutProfiler = [componentsTab, settingsTab];
75 +const tabs = [componentsTab, profilerTab, settingsTab];
76
77 export default function DevTools({
78 bridge,
@@ -92,27 +92,19 @@ export default function DevTools({
92 setTab(overrideTab);
93 }
94
95 - const [supportsProfiling, setSupportsProfiling] = useState(
96 - store.supportsProfiling
95 + const supportsProfilingSubscription = useMemo(
96 + () => ({
97 + getCurrentValue: () => store.supportsProfiling,
98 + subscribe: (callback: Function) => {
99 + store.addListener('supportsProfiling', callback);
100 + return () => store.removeListener('supportsProfiling', callback);
101 + },
102 + }),
103 + [store]
104 + );
105 + const supportsProfiling = useSubscription<boolean, Store>(
106 + supportsProfilingSubscription
107 );
98 -
99 - // Show/hide the "Profiler" button depending on if profiling is supported.
100 - useEffect(() => {
101 - if (supportsProfiling !== store.supportsProfiling) {
102 - setSupportsProfiling(store.supportsProfiling);
103 - }
104 -
105 - const handleRoots = () => {
106 - if (supportsProfiling !== store.supportsProfiling) {
107 - setSupportsProfiling(store.supportsProfiling);
108 - }
109 - };
110 -
111 - store.addListener('roots', handleRoots);
112 - return () => {
113 - store.removeListener('roots', handleRoots);
114 - };
115 - }, [store, supportsProfiling]);
108
109 return (
110 <BridgeContext.Provider value={bridge}>
@@ -140,11 +132,7 @@ export default function DevTools({
132 id="DevTools"
133 selectTab={setTab}
134 size="large"
143 - tabs={
144 - supportsProfiling
145 - ? tabsWithProfiler
146 - : tabsWithoutProfiler
147 - }
135 + tabs={tabs}
136 />
137 </div>
138 )}
src/devtools/views/TabBar.js
+48 -35
@@ -2,9 +2,11 @@
2
3 import classNames from 'classnames';
4 import React, { Fragment, useCallback } from 'react';
5 +import Tooltip from '@reach/tooltip';
6 import Icon from './Icon';
7
8 import styles from './TabBar.css';
9 +import tooltipStyles from './Tooltip.css';
10
11 import type { IconType } from './Icon';
12
@@ -59,42 +61,53 @@ export default function TabBar({
61
62 return (
63 <Fragment>
62 - {tabs.map(({ icon, id, label, title }) => (
63 - <label
64 - className={classNames(
65 - tabClassName,
66 - disabled ? styles.TabDisabled : styles.Tab,
67 - !disabled && currentTab === id ? styles.TabCurrent : null
68 - )}
69 - key={id}
70 - onKeyDown={handleKeyDown}
71 - onMouseDown={() => selectTab(id)}
72 - title={title || label}
73 - >
74 - <input
75 - type="radio"
76 - className={styles.Input}
77 - checked={currentTab === id}
78 - disabled={disabled}
79 - name={groupName}
80 - value={id}
81 - onChange={onChange}
82 - />
83 - <Icon
84 - className={`${disabled ? styles.IconDisabled : ''} ${
85 - size === 'large' ? styles.IconSizeLarge : styles.IconSizeSmall
86 - }`}
87 - type={icon}
88 - />
89 - <span
90 - className={
91 - size === 'large' ? styles.TabLabelLarge : styles.TabLabelSmall
92 - }
64 + {tabs.map(({ icon, id, label, title }) => {
65 + let button = (
66 + <label
67 + className={classNames(
68 + tabClassName,
69 + disabled ? styles.TabDisabled : styles.Tab,
70 + !disabled && currentTab === id ? styles.TabCurrent : null
71 + )}
72 + key={id}
73 + onKeyDown={handleKeyDown}
74 + onMouseDown={() => selectTab(id)}
75 >
94 - {label}
95 - </span>
96 - </label>
97 - ))}
76 + <input
77 + type="radio"
78 + className={styles.Input}
79 + checked={currentTab === id}
80 + disabled={disabled}
81 + name={groupName}
82 + value={id}
83 + onChange={onChange}
84 + />
85 + <Icon
86 + className={`${disabled ? styles.IconDisabled : ''} ${
87 + size === 'large' ? styles.IconSizeLarge : styles.IconSizeSmall
88 + }`}
89 + type={icon}
90 + />
91 + <span
92 + className={
93 + size === 'large' ? styles.TabLabelLarge : styles.TabLabelSmall
94 + }
95 + >
96 + {label}
97 + </span>
98 + </label>
99 + );
100 +
101 + if (title) {
102 + button = (
103 + <Tooltip className={tooltipStyles.Tooltip} label={title}>
104 + {button}
105 + </Tooltip>
106 + );
107 + }
108 +
109 + return button;
110 + })}
111 </Fragment>
112 );
113 }