[DevTools] Stop using native `title` for buttons/icons (#34379)
Sebastian "Sebbie" Silbermann committed
Sep 11, 2025 at 18:49 UTC
67415c8c4a3380ec96f710bbffc3d215076360f0
10 files changed
+43
-47
packages/react-devtools-shared/src/devtools/views/Components/Badge.js
+11
-2
@@ -14,8 +14,17 @@ import styles from './Badge.css';
14
type Props = {
15
className?: string,
16
children: React$Node,
17
+ ...
18
};
19
19
-export default function Badge({className = '', children}: Props): React.Node {
20
- return <div className={`${styles.Badge} ${className}`}>{children}</div>;
20
+export default function Badge({
21
+ className = '',
22
+ children,
23
+ ...props
24
+}: Props): React.Node {
25
+ return (
26
+ <div {...props} className={`${styles.Badge} ${className}`}>
27
+ {children}
28
+ </div>
29
+ );
30
}
packages/react-devtools-shared/src/devtools/views/Components/Element.js
+11
-9
@@ -24,6 +24,7 @@ import type {Element as ElementType} from 'react-devtools-shared/src/frontend/ty
24
import styles from './Element.css';
25
import Icon from '../Icon';
26
import {useChangeOwnerAction} from './OwnersListContext';
27
+import Tooltip from './reach-ui/tooltip';
28
29
type Props = {
30
data: ItemData,
@@ -231,15 +232,16 @@ export default function Element({data, index, style}: Props): React.Node {
232
/>
233
)}
234
{showStrictModeBadge && (
234
- <Icon
235
- className={
236
- isSelected && treeFocused
237
- ? styles.StrictModeContrast
238
- : styles.StrictMode
239
- }
240
- title="This component is not running in StrictMode."
241
- type="strict-mode-non-compliant"
242
- />
235
+ <Tooltip label="This component is not running in StrictMode.">
236
+ <Icon
237
+ className={
238
+ isSelected && treeFocused
239
+ ? styles.StrictModeContrast
240
+ : styles.StrictMode
241
+ }
242
+ type="strict-mode-non-compliant"
243
+ />
244
+ </Tooltip>
245
)}
246
</div>
247
</div>
packages/react-devtools-shared/src/devtools/views/Components/ForgetBadge.css
-8
@@ -11,11 +11,3 @@
11
position: absolute;
12
right: 0.25em;
13
}
14
-
15
-.ForgetToggle {
16
- display: flex;
17
-}
18
-
19
-.ForgetToggle > span { /* targets .ToggleContent */
20
- padding: 0;
21
-}
packages/react-devtools-shared/src/devtools/views/Components/ForgetBadge.js
+3
-4
@@ -11,7 +11,7 @@ import * as React from 'react';
11
12
import Badge from './Badge';
13
import IndexableDisplayName from './IndexableDisplayName';
14
-import Toggle from '../Toggle';
14
+import Tooltip from './reach-ui/tooltip';
15
16
import styles from './ForgetBadge.css';
17
@@ -40,12 +40,11 @@ export default function ForgetBadge(props: Props): React.Node {
40
'Memo'
41
);
42
43
- const onChange = () => {};
43
const title =
44
'✨ This component has been auto-memoized by the React Compiler.';
45
return (
47
- <Toggle onChange={onChange} className={styles.ForgetToggle} title={title}>
46
+ <Tooltip label={title}>
47
<Badge className={`${styles.Root} ${className}`}>{innerView}</Badge>
49
- </Toggle>
48
+ </Tooltip>
49
);
50
}
packages/react-devtools-shared/src/devtools/views/Components/InspectedElement.js
+10
-8
@@ -29,6 +29,7 @@ import InspectedElementViewSourceButton from './InspectedElementViewSourceButton
29
import useEditorURL from '../useEditorURL';
30
31
import styles from './InspectedElement.css';
32
+import Tooltip from './reach-ui/tooltip';
33
34
export type Props = {};
35
@@ -192,14 +193,15 @@ export default function InspectedElementWrapper(_: Props): React.Node {
193
let strictModeBadge = null;
194
if (element.isStrictModeNonCompliant) {
195
strictModeBadge = (
195
- <a
196
- className={styles.StrictModeNonCompliant}
197
- href="https://react.dev/reference/react/StrictMode"
198
- rel="noopener noreferrer"
199
- target="_blank"
200
- title="This component is not running in StrictMode. Click to learn more.">
201
- <Icon type="strict-mode-non-compliant" />
202
- </a>
196
+ <Tooltip label="This component is not running in StrictMode. Click to learn more.">
197
+ <a
198
+ className={styles.StrictModeNonCompliant}
199
+ href="https://react.dev/reference/react/StrictMode"
200
+ rel="noopener noreferrer"
201
+ target="_blank">
202
+ <Icon type="strict-mode-non-compliant" />
203
+ </a>
204
+ </Tooltip>
205
);
206
}
207
packages/react-devtools-shared/src/devtools/views/Components/NativeTagBadge.css
-8
@@ -1,11 +1,3 @@
1
-.Toggle {
2
- display: flex;
3
-}
4
-
5
-.Toggle > span { /* targets .ToggleContent */
6
- padding: 0;
7
-}
8
-
1
.Badge {
2
cursor: help;
3
}
packages/react-devtools-shared/src/devtools/views/Components/NativeTagBadge.js
+3
-4
@@ -10,7 +10,7 @@
10
import * as React from 'react';
11
12
import Badge from './Badge';
13
-import Toggle from '../Toggle';
13
+import Tooltip from './reach-ui/tooltip';
14
15
import styles from './NativeTagBadge.css';
16
@@ -18,14 +18,13 @@ type Props = {
18
nativeTag: number,
19
};
20
21
-const noop = () => {};
21
const title =
22
'Unique identifier for the corresponding native component. React Native only.';
23
24
export default function NativeTagBadge({nativeTag}: Props): React.Node {
25
return (
27
- <Toggle onChange={noop} className={styles.Toggle} title={title}>
26
+ <Tooltip label={title}>
27
<Badge className={styles.Badge}>Tag {nativeTag}</Badge>
29
- </Toggle>
28
+ </Tooltip>
29
);
30
}
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/ReportNewIssue.js
+1
-2
@@ -63,8 +63,7 @@ export default function ReportNewIssue({
63
className={styles.ReportLink}
64
href={bugURL}
65
rel="noopener noreferrer"
66
- target="_blank"
67
- title="Report bug">
66
+ target="_blank">
67
Report this issue
68
</a>
69
<div className={styles.ReproSteps}>
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/WorkplaceGroup.js
+1
-2
@@ -25,8 +25,7 @@ export default function WorkplaceGroup(): React.Node {
25
className={styles.ReportLink}
26
href={REACT_DEVTOOLS_WORKPLACE_URL}
27
rel="noopener noreferrer"
28
- target="_blank"
29
- title="Report bug">
28
+ target="_blank">
29
Report this on Workplace
30
</a>
31
<div className={styles.FacebookOnly}>(Facebook employees only.)</div>
packages/react-devtools-shared/src/devtools/views/Icon.js
+3
@@ -33,12 +33,14 @@ type Props = {
33
className?: string,
34
title?: string,
35
type: IconType,
36
+ ...
37
};
38
39
export default function Icon({
40
className = '',
41
title = '',
42
type,
43
+ ...props
44
}: Props): React.Node {
45
let pathData = null;
46
let viewBox = '0 0 24 24';
@@ -102,6 +104,7 @@ export default function Icon({
104
105
return (
106
<svg
107
+ {...props}
108
xmlns="http://www.w3.org/2000/svg"
109
className={`${styles.Icon} ${className}`}
110
width="24"