From eaa62612e7a921fb453b7c6faf68e875dde1bdc0 Mon Sep 17 00:00:00 2001 From: emyarod Date: Tue, 18 May 2021 13:09:07 -0500 Subject: [PATCH 1/3] fix(Tooltip): prevent focus hijacking with focusable children --- .../react/src/components/Tooltip/Tooltip.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/packages/react/src/components/Tooltip/Tooltip.js b/packages/react/src/components/Tooltip/Tooltip.js index 05bba777e82b..352ad5aa8be7 100644 --- a/packages/react/src/components/Tooltip/Tooltip.js +++ b/packages/react/src/components/Tooltip/Tooltip.js @@ -21,10 +21,6 @@ import FloatingMenu, { import ClickListener from '../../internal/ClickListener'; import mergeRefs from '../../tools/mergeRefs'; import { keys, matches as keyDownMatch } from '../../internal/keyboard'; -import { - selectorFocusable, - selectorTabbable, -} from '../../internal/keyboard/navigation'; import isRequiredOneOf from '../../prop-types/isRequiredOneOf'; import requiredIfValueExists from '../../prop-types/requiredIfValueExists'; import { useControlledStateWithValue } from '../../internal/FeatureFlags'; @@ -303,19 +299,6 @@ class Tooltip extends Component { } if (!open && tooltipBody && tooltipBody.id === this._tooltipId) { this._tooltipDismissed = true; - const primaryFocusNode = tooltipBody.querySelector( - this.props.selectorPrimaryFocus || null - ); - const tabbableNode = tooltipBody.querySelector(selectorTabbable); - const focusableNode = tooltipBody.querySelector(selectorFocusable); - const focusTarget = - primaryFocusNode || // User defined focusable node - tabbableNode || // First sequentially focusable node - focusableNode || // First programmatic focusable node - tooltipBody; - if (focusTarget !== tooltipBody) { - this._triggerRef?.current.focus(); - } } }); }; From ed67a467230904d45ef84d137543a4c55d353688 Mon Sep 17 00:00:00 2001 From: emyarod Date: Tue, 18 May 2021 14:18:17 -0500 Subject: [PATCH 2/3] fix(Tooltip): restore focus to trigger element only occurs if focus is not applied to another element after blur --- packages/react/src/components/Tooltip/Tooltip.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react/src/components/Tooltip/Tooltip.js b/packages/react/src/components/Tooltip/Tooltip.js index 352ad5aa8be7..28ada1f33ba7 100644 --- a/packages/react/src/components/Tooltip/Tooltip.js +++ b/packages/react/src/components/Tooltip/Tooltip.js @@ -299,6 +299,10 @@ class Tooltip extends Component { } if (!open && tooltipBody && tooltipBody.id === this._tooltipId) { this._tooltipDismissed = true; + const currentActiveNode = event?.relatedTarget; + if (!currentActiveNode && document.activeElement === document.body) { + this._triggerRef?.current.focus(); + } } }); }; From 1644a75a62186f4aa90959102d87e5722a38c9fa Mon Sep 17 00:00:00 2001 From: emyarod Date: Tue, 18 May 2021 14:18:46 -0500 Subject: [PATCH 3/3] docs(Tooltip): add temporary test story --- .../src/components/Tooltip/Tooltip-story.js | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/packages/react/src/components/Tooltip/Tooltip-story.js b/packages/react/src/components/Tooltip/Tooltip-story.js index 03e25e764ca9..5801e74235e5 100644 --- a/packages/react/src/components/Tooltip/Tooltip-story.js +++ b/packages/react/src/components/Tooltip/Tooltip-story.js @@ -17,6 +17,7 @@ import { import Tooltip from '../Tooltip'; import { Tooltip as OGTooltip } from './Tooltip'; import Button from '../Button'; +import TextInput from '../TextInput'; import { OverflowMenuVertical16 } from '@carbon/icons-react'; import mdx from './Tooltip.mdx'; @@ -271,3 +272,118 @@ OnlyCustomIcon.parameters = { export const UncontrolledTooltip = () => ; UncontrolledTooltip.storyName = 'uncontrolled tooltip'; + +export const App = () => ( +
+ + example1 +
+ } + align="start" + direction="bottom" + showIcon={false}> +
+
+
+ +
+                This is the first message.
+              
+
+
+
+
+ + + example2 + + } + align="start" + direction="bottom" + showIcon={false}> +
+
+ +
+              This is the second message.
+            
+
+
+
+
+ +); + +export const App2 = () => { + const getTooltip = (id, label, includeId, withButton) => ( + +

+ This is some tooltip text. This box shows the maximum amount of text + that should appear inside. If more room is needed please use a modal + instead. +

+
+ {withButton && ( + + Learn More + + )} + {withButton && } +
+
+ ); + const getTextInput = (id, label, includeId, withButton) => ( + + ); + + return ( +
+ {getTextInput('bad-text-input-1', 'Text input (tooltip with id) 1', true)} + {getTextInput( + 'bad-text-input-2', + 'Text input (tooltip with id) 2', + true, + true + )} + {getTextInput( + 'bad-text-input-3', + 'Text input (tooltip with id) 3', + true, + true + )} + {getTextInput( + 'good-text-input-1', + 'Text input (tooltip with no id) 1', + false + )} + {getTextInput( + 'good-text-input-2', + 'Text input (tooltip with no id) 2', + false, + true + )} + {getTextInput( + 'good-text-input-3', + 'Text input (tooltip with no id) 3', + false, + true + )} +
+ ); +};