@atlaskit/tooltip 18.8.4 → 18.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/cjs/tooltip.js +73 -48
- package/dist/es2019/tooltip.js +71 -49
- package/dist/esm/tooltip.js +73 -48
- package/dist/types/tooltip.d.ts +1 -1
- package/dist/types/types.d.ts +24 -0
- package/dist/types-ts4.5/tooltip.d.ts +1 -1
- package/dist/types-ts4.5/types.d.ts +24 -0
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atlaskit/tooltip
|
|
2
2
|
|
|
3
|
+
## 18.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`be6f923511512`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/be6f923511512) - -
|
|
8
|
+
Added new prop: `canAppear`, which can be used to _conditionally_ show tooltips.
|
|
9
|
+
- Added new prop: `isScreenReaderAnnouncementDisabled` which can be used to disable hidden text
|
|
10
|
+
for tooltips. This is useful when the Tooltip `content` matches the Tooltip trigger content as
|
|
11
|
+
hidden text is not required.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
17
|
+
## 18.8.5
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies
|
|
22
|
+
|
|
3
23
|
## 18.8.4
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/cjs/tooltip.js
CHANGED
|
@@ -14,6 +14,7 @@ var _bindEventListener = require("bind-event-listener");
|
|
|
14
14
|
var _analyticsNext = require("@atlaskit/analytics-next");
|
|
15
15
|
var _noop = _interopRequireDefault(require("@atlaskit/ds-lib/noop"));
|
|
16
16
|
var _useCloseOnEscapePress = _interopRequireDefault(require("@atlaskit/ds-lib/use-close-on-escape-press"));
|
|
17
|
+
var _useStableRef = _interopRequireDefault(require("@atlaskit/ds-lib/use-stable-ref"));
|
|
17
18
|
var _openLayerObserver = require("@atlaskit/layering/experimental/open-layer-observer");
|
|
18
19
|
var _motion = require("@atlaskit/motion");
|
|
19
20
|
var _durations = require("@atlaskit/motion/durations");
|
|
@@ -33,7 +34,7 @@ var tooltipZIndex = _constants.layers.tooltip();
|
|
|
33
34
|
var analyticsAttributes = {
|
|
34
35
|
componentName: 'tooltip',
|
|
35
36
|
packageName: "@atlaskit/tooltip",
|
|
36
|
-
packageVersion: "18.
|
|
37
|
+
packageVersion: "18.9.0"
|
|
37
38
|
};
|
|
38
39
|
|
|
39
40
|
// Inverts motion direction
|
|
@@ -78,6 +79,7 @@ function Tooltip(_ref) {
|
|
|
78
79
|
onShow = _ref$onShow === void 0 ? _noop.default : _ref$onShow,
|
|
79
80
|
_ref$onHide = _ref.onHide,
|
|
80
81
|
onHide = _ref$onHide === void 0 ? _noop.default : _ref$onHide,
|
|
82
|
+
canAppear = _ref.canAppear,
|
|
81
83
|
_ref$hideTooltipOnCli = _ref.hideTooltipOnClick,
|
|
82
84
|
hideTooltipOnClick = _ref$hideTooltipOnCli === void 0 ? false : _ref$hideTooltipOnCli,
|
|
83
85
|
_ref$hideTooltipOnMou = _ref.hideTooltipOnMouseDown,
|
|
@@ -86,7 +88,9 @@ function Tooltip(_ref) {
|
|
|
86
88
|
_ref$strategy = _ref.strategy,
|
|
87
89
|
strategy = _ref$strategy === void 0 ? 'fixed' : _ref$strategy,
|
|
88
90
|
_ref$ignoreTooltipPoi = _ref.ignoreTooltipPointerEvents,
|
|
89
|
-
ignoreTooltipPointerEvents = _ref$ignoreTooltipPoi === void 0 ? false : _ref$ignoreTooltipPoi
|
|
91
|
+
ignoreTooltipPointerEvents = _ref$ignoreTooltipPoi === void 0 ? false : _ref$ignoreTooltipPoi,
|
|
92
|
+
_ref$isScreenReaderAn = _ref.isScreenReaderAnnouncementDisabled,
|
|
93
|
+
isScreenReaderAnnouncementDisabled = _ref$isScreenReaderAn === void 0 ? false : _ref$isScreenReaderAn;
|
|
90
94
|
var tooltipPosition = position === 'mouse' ? mousePosition : position;
|
|
91
95
|
var onShowHandler = (0, _analyticsNext.usePlatformLeafSyntheticEventHandler)(_objectSpread({
|
|
92
96
|
fn: onShow,
|
|
@@ -119,21 +123,14 @@ function Tooltip(_ref) {
|
|
|
119
123
|
}, []);
|
|
120
124
|
|
|
121
125
|
// Putting a few things into refs so that we don't have to break memoization
|
|
122
|
-
var
|
|
123
|
-
var
|
|
124
|
-
var lastHandlers = (0, _react.useRef)({
|
|
126
|
+
var stableState = (0, _useStableRef.default)(state);
|
|
127
|
+
var stableProps = (0, _useStableRef.default)({
|
|
125
128
|
onShowHandler: onShowHandler,
|
|
126
|
-
onHideHandler: onHideHandler
|
|
129
|
+
onHideHandler: onHideHandler,
|
|
130
|
+
delay: delay,
|
|
131
|
+
canAppear: canAppear
|
|
127
132
|
});
|
|
128
133
|
var hasCalledShowHandler = (0, _react.useRef)(false);
|
|
129
|
-
(0, _react.useEffect)(function () {
|
|
130
|
-
lastState.current = state;
|
|
131
|
-
lastDelay.current = delay;
|
|
132
|
-
lastHandlers.current = {
|
|
133
|
-
onShowHandler: onShowHandler,
|
|
134
|
-
onHideHandler: onHideHandler
|
|
135
|
-
};
|
|
136
|
-
}, [delay, onHideHandler, onShowHandler, state]);
|
|
137
134
|
var start = (0, _react.useCallback)(function (api) {
|
|
138
135
|
// @ts-ignore
|
|
139
136
|
apiRef.current = api;
|
|
@@ -145,7 +142,7 @@ function Tooltip(_ref) {
|
|
|
145
142
|
}
|
|
146
143
|
// Only call onHideHandler if we have called onShowHandler
|
|
147
144
|
if (hasCalledShowHandler.current) {
|
|
148
|
-
|
|
145
|
+
stableProps.current.onHideHandler();
|
|
149
146
|
}
|
|
150
147
|
// @ts-ignore
|
|
151
148
|
apiRef.current = null;
|
|
@@ -153,7 +150,7 @@ function Tooltip(_ref) {
|
|
|
153
150
|
hasCalledShowHandler.current = false;
|
|
154
151
|
// just in case
|
|
155
152
|
setState('hide');
|
|
156
|
-
}, []);
|
|
153
|
+
}, [stableProps]);
|
|
157
154
|
var abort = (0, _react.useCallback)(function () {
|
|
158
155
|
if (!apiRef.current) {
|
|
159
156
|
return;
|
|
@@ -161,11 +158,11 @@ function Tooltip(_ref) {
|
|
|
161
158
|
apiRef.current.abort();
|
|
162
159
|
// Only call onHideHandler if we have called onShowHandler
|
|
163
160
|
if (hasCalledShowHandler.current) {
|
|
164
|
-
|
|
161
|
+
stableProps.current.onHideHandler();
|
|
165
162
|
}
|
|
166
163
|
// @ts-ignore
|
|
167
164
|
apiRef.current = null;
|
|
168
|
-
}, []);
|
|
165
|
+
}, [stableProps]);
|
|
169
166
|
(0, _react.useEffect)(function mount() {
|
|
170
167
|
return function unmount() {
|
|
171
168
|
if (apiRef.current) {
|
|
@@ -196,7 +193,8 @@ function Tooltip(_ref) {
|
|
|
196
193
|
}
|
|
197
194
|
});
|
|
198
195
|
}, []);
|
|
199
|
-
var
|
|
196
|
+
var tryShowTooltip = (0, _react.useCallback)(function (source) {
|
|
197
|
+
var _stableProps$current$, _stableProps$current;
|
|
200
198
|
/**
|
|
201
199
|
* Prevent tooltips from being shown during a drag. This can occur with
|
|
202
200
|
* the native drag and drop API, where some pointer events can fire
|
|
@@ -205,24 +203,45 @@ function Tooltip(_ref) {
|
|
|
205
203
|
if (isDraggingRef.current) {
|
|
206
204
|
return;
|
|
207
205
|
}
|
|
206
|
+
|
|
207
|
+
// Another tooltip is has been active but we still have the old `api`
|
|
208
|
+
// around. We need to finish up the last usage.
|
|
209
|
+
// Note: just being safe - this should not happen
|
|
208
210
|
if (apiRef.current && !apiRef.current.isActive()) {
|
|
209
211
|
abort();
|
|
210
212
|
}
|
|
211
213
|
|
|
212
|
-
//
|
|
214
|
+
// This tooltip is already active, we can exit
|
|
213
215
|
if (apiRef.current && apiRef.current.isActive()) {
|
|
214
216
|
apiRef.current.keep();
|
|
215
217
|
return;
|
|
216
218
|
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Check if tooltip is allowed to show.
|
|
222
|
+
*
|
|
223
|
+
* Once a tooltip has started, or has scheduled to start
|
|
224
|
+
* we won't be checking `canAppear` again.
|
|
225
|
+
*
|
|
226
|
+
* - We don't want tooltips to disappear once they are shown
|
|
227
|
+
* - For consistency, we start after a single positive `canAppear`.
|
|
228
|
+
* Otherwise the amount of times we ask consumers would depend on
|
|
229
|
+
* how many times we get a "mousemove", which _could_ lead to situations
|
|
230
|
+
* where moving the mouse could result in a different outcome to if
|
|
231
|
+
* the mouse was not moved.
|
|
232
|
+
*/
|
|
233
|
+
if (stableProps.current.canAppear && !((_stableProps$current$ = (_stableProps$current = stableProps.current).canAppear) !== null && _stableProps$current$ !== void 0 && _stableProps$current$.call(_stableProps$current))) {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
217
236
|
var entry = {
|
|
218
237
|
source: source,
|
|
219
|
-
delay:
|
|
238
|
+
delay: stableProps.current.delay,
|
|
220
239
|
show: function show(_ref3) {
|
|
221
240
|
var isImmediate = _ref3.isImmediate;
|
|
222
241
|
// Call the onShow handler if it hasn't been called yet
|
|
223
242
|
if (!hasCalledShowHandler.current) {
|
|
224
243
|
hasCalledShowHandler.current = true;
|
|
225
|
-
|
|
244
|
+
stableProps.current.onShowHandler();
|
|
226
245
|
}
|
|
227
246
|
setState(isImmediate ? 'show-immediate' : 'fade-in');
|
|
228
247
|
},
|
|
@@ -238,7 +257,7 @@ function Tooltip(_ref) {
|
|
|
238
257
|
};
|
|
239
258
|
var api = (0, _tooltipManager.show)(entry);
|
|
240
259
|
start(api);
|
|
241
|
-
}, [abort, done, start]);
|
|
260
|
+
}, [stableProps, abort, done, start]);
|
|
242
261
|
var hideTooltipOnEsc = (0, _react.useCallback)(function () {
|
|
243
262
|
var _apiRef$current2;
|
|
244
263
|
(_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 || _apiRef$current2.requestHide({
|
|
@@ -314,8 +333,8 @@ function Tooltip(_ref) {
|
|
|
314
333
|
} : {
|
|
315
334
|
type: 'keyboard'
|
|
316
335
|
};
|
|
317
|
-
|
|
318
|
-
}, [position,
|
|
336
|
+
tryShowTooltip(source);
|
|
337
|
+
}, [position, tryShowTooltip]);
|
|
319
338
|
|
|
320
339
|
// Ideally we would be using onMouseEnter here, but
|
|
321
340
|
// because we are binding the event to the target parent
|
|
@@ -355,10 +374,12 @@ function Tooltip(_ref) {
|
|
|
355
374
|
}
|
|
356
375
|
}, []);
|
|
357
376
|
var onFocus = (0, _react.useCallback)(function () {
|
|
358
|
-
|
|
377
|
+
// TODO: this does not play well with `hideTooltipOnMouseDown`
|
|
378
|
+
// as "focus" will occur after the "mousedown".
|
|
379
|
+
tryShowTooltip({
|
|
359
380
|
type: 'keyboard'
|
|
360
381
|
});
|
|
361
|
-
}, [
|
|
382
|
+
}, [tryShowTooltip]);
|
|
362
383
|
var onBlur = (0, _react.useCallback)(function () {
|
|
363
384
|
if (apiRef.current) {
|
|
364
385
|
apiRef.current.requestHide({
|
|
@@ -368,18 +389,19 @@ function Tooltip(_ref) {
|
|
|
368
389
|
}, []);
|
|
369
390
|
var onAnimationFinished = (0, _react.useCallback)(function (transition) {
|
|
370
391
|
// Using lastState here because motion is not picking up the latest value
|
|
371
|
-
if (transition === 'exiting' &&
|
|
392
|
+
if (transition === 'exiting' && stableState.current === 'fade-out' && apiRef.current) {
|
|
372
393
|
// @ts-ignore: refs are writeable
|
|
373
394
|
apiRef.current.finishHideAnimation();
|
|
374
395
|
}
|
|
375
|
-
}, []);
|
|
396
|
+
}, [stableState]);
|
|
376
397
|
|
|
377
398
|
// Doing a cast because typescript is struggling to narrow the type
|
|
378
399
|
var CastTargetContainer = TargetContainer;
|
|
379
|
-
var
|
|
400
|
+
var shouldRenderTooltipPopup = state !== 'hide' && Boolean(content);
|
|
401
|
+
var shouldRenderHiddenContent = !isScreenReaderAnnouncementDisabled && shouldRenderTooltipPopup;
|
|
380
402
|
var shouldRenderTooltipChildren = state !== 'hide' && state !== 'fade-out';
|
|
381
403
|
(0, _openLayerObserver.useNotifyOpenLayerObserver)({
|
|
382
|
-
isOpen:
|
|
404
|
+
isOpen: shouldRenderTooltipPopup
|
|
383
405
|
});
|
|
384
406
|
var getReferenceElement = function getReferenceElement() {
|
|
385
407
|
var _apiRef$current4;
|
|
@@ -389,7 +411,7 @@ function Tooltip(_ref) {
|
|
|
389
411
|
}
|
|
390
412
|
return targetRef.current || undefined;
|
|
391
413
|
};
|
|
392
|
-
var
|
|
414
|
+
var tooltipIdForHiddenContent = (0, _useUniqueId.default)('tooltip', shouldRenderHiddenContent);
|
|
393
415
|
var tooltipTriggerProps = {
|
|
394
416
|
onMouseOver: onMouseOver,
|
|
395
417
|
onMouseOut: onMouseOut,
|
|
@@ -408,38 +430,41 @@ function Tooltip(_ref) {
|
|
|
408
430
|
|
|
409
431
|
// This useEffect is purely for managing the aria attribute when using the
|
|
410
432
|
// wrapped children approach.
|
|
433
|
+
var isChildrenAFunction = typeof children === 'function';
|
|
411
434
|
(0, _react.useEffect)(function () {
|
|
412
|
-
|
|
413
|
-
// means they are using the render prop API, and that is implemented in a
|
|
414
|
-
// different way. If there is no target element yet or tooltipId, we also
|
|
415
|
-
// shouldn't do anything because there is nothing to operate on or with.
|
|
416
|
-
if (!containerRef.current || !targetRef.current || !tooltipId) {
|
|
435
|
+
if (isChildrenAFunction) {
|
|
417
436
|
return;
|
|
418
437
|
}
|
|
438
|
+
|
|
439
|
+
// If `children` is _not_ a function, we are stepping outside of the public
|
|
440
|
+
// API to add a `aria-describedby` attribute.
|
|
441
|
+
|
|
419
442
|
var target = targetRef.current;
|
|
420
|
-
if (
|
|
421
|
-
|
|
422
|
-
} else {
|
|
423
|
-
target.removeAttribute('aria-describedby');
|
|
443
|
+
if (!target || !tooltipIdForHiddenContent) {
|
|
444
|
+
return;
|
|
424
445
|
}
|
|
425
|
-
|
|
426
|
-
|
|
446
|
+
target.setAttribute('aria-describedby', tooltipIdForHiddenContent);
|
|
447
|
+
return function () {
|
|
448
|
+
return target.removeAttribute('aria-describedby');
|
|
449
|
+
};
|
|
450
|
+
}, [isChildrenAFunction, tooltipIdForHiddenContent]);
|
|
451
|
+
var hiddenContent = shouldRenderHiddenContent ? /*#__PURE__*/_react.default.createElement("span", {
|
|
427
452
|
"data-testid": testId ? "".concat(testId, "-hidden") : undefined,
|
|
428
453
|
hidden: true,
|
|
429
|
-
id:
|
|
430
|
-
}, typeof content === 'function' ? content({}) : content);
|
|
454
|
+
id: tooltipIdForHiddenContent
|
|
455
|
+
}, typeof content === 'function' ? content({}) : content) : null;
|
|
431
456
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, typeof children === 'function' ?
|
|
432
457
|
/*#__PURE__*/
|
|
433
458
|
// once we deprecate the wrapped approach, we can put the aria
|
|
434
459
|
// attribute back into the tooltipTriggerProps and make it required
|
|
435
460
|
// instead of optional in `types`
|
|
436
461
|
_react.default.createElement(_react.default.Fragment, null, children(_objectSpread(_objectSpread({}, tooltipTriggerProps), {}, {
|
|
437
|
-
'aria-describedby':
|
|
462
|
+
'aria-describedby': tooltipIdForHiddenContent,
|
|
438
463
|
ref: setDirectRef
|
|
439
|
-
})),
|
|
464
|
+
})), hiddenContent) : /*#__PURE__*/_react.default.createElement(CastTargetContainer, (0, _extends2.default)({}, tooltipTriggerProps, {
|
|
440
465
|
ref: setImplicitRefFromChildren,
|
|
441
466
|
role: "presentation"
|
|
442
|
-
}), children,
|
|
467
|
+
}), children, hiddenContent), shouldRenderTooltipPopup ? /*#__PURE__*/_react.default.createElement(_portal.default, {
|
|
443
468
|
zIndex: tooltipZIndex
|
|
444
469
|
}, /*#__PURE__*/_react.default.createElement(_popper.Popper, {
|
|
445
470
|
placement: tooltipPosition,
|
package/dist/es2019/tooltip.js
CHANGED
|
@@ -4,6 +4,7 @@ import { bind } from 'bind-event-listener';
|
|
|
4
4
|
import { usePlatformLeafSyntheticEventHandler } from '@atlaskit/analytics-next';
|
|
5
5
|
import noop from '@atlaskit/ds-lib/noop';
|
|
6
6
|
import useCloseOnEscapePress from '@atlaskit/ds-lib/use-close-on-escape-press';
|
|
7
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
7
8
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
8
9
|
import { ExitingPersistence, FadeIn } from '@atlaskit/motion';
|
|
9
10
|
import { mediumDurationMs } from '@atlaskit/motion/durations';
|
|
@@ -19,7 +20,7 @@ const tooltipZIndex = layers.tooltip();
|
|
|
19
20
|
const analyticsAttributes = {
|
|
20
21
|
componentName: 'tooltip',
|
|
21
22
|
packageName: "@atlaskit/tooltip",
|
|
22
|
-
packageVersion: "18.
|
|
23
|
+
packageVersion: "18.9.0"
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
// Inverts motion direction
|
|
@@ -55,11 +56,13 @@ function Tooltip({
|
|
|
55
56
|
delay = 300,
|
|
56
57
|
onShow = noop,
|
|
57
58
|
onHide = noop,
|
|
59
|
+
canAppear,
|
|
58
60
|
hideTooltipOnClick = false,
|
|
59
61
|
hideTooltipOnMouseDown = false,
|
|
60
62
|
analyticsContext,
|
|
61
63
|
strategy = 'fixed',
|
|
62
|
-
ignoreTooltipPointerEvents = false
|
|
64
|
+
ignoreTooltipPointerEvents = false,
|
|
65
|
+
isScreenReaderAnnouncementDisabled = false
|
|
63
66
|
}) {
|
|
64
67
|
const tooltipPosition = position === 'mouse' ? mousePosition : position;
|
|
65
68
|
const onShowHandler = usePlatformLeafSyntheticEventHandler({
|
|
@@ -92,21 +95,14 @@ function Tooltip({
|
|
|
92
95
|
}, []);
|
|
93
96
|
|
|
94
97
|
// Putting a few things into refs so that we don't have to break memoization
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const lastHandlers = useRef({
|
|
98
|
+
const stableState = useStableRef(state);
|
|
99
|
+
const stableProps = useStableRef({
|
|
98
100
|
onShowHandler,
|
|
99
|
-
onHideHandler
|
|
101
|
+
onHideHandler,
|
|
102
|
+
delay,
|
|
103
|
+
canAppear
|
|
100
104
|
});
|
|
101
105
|
const hasCalledShowHandler = useRef(false);
|
|
102
|
-
useEffect(() => {
|
|
103
|
-
lastState.current = state;
|
|
104
|
-
lastDelay.current = delay;
|
|
105
|
-
lastHandlers.current = {
|
|
106
|
-
onShowHandler,
|
|
107
|
-
onHideHandler
|
|
108
|
-
};
|
|
109
|
-
}, [delay, onHideHandler, onShowHandler, state]);
|
|
110
106
|
const start = useCallback(api => {
|
|
111
107
|
// @ts-ignore
|
|
112
108
|
apiRef.current = api;
|
|
@@ -118,7 +114,7 @@ function Tooltip({
|
|
|
118
114
|
}
|
|
119
115
|
// Only call onHideHandler if we have called onShowHandler
|
|
120
116
|
if (hasCalledShowHandler.current) {
|
|
121
|
-
|
|
117
|
+
stableProps.current.onHideHandler();
|
|
122
118
|
}
|
|
123
119
|
// @ts-ignore
|
|
124
120
|
apiRef.current = null;
|
|
@@ -126,7 +122,7 @@ function Tooltip({
|
|
|
126
122
|
hasCalledShowHandler.current = false;
|
|
127
123
|
// just in case
|
|
128
124
|
setState('hide');
|
|
129
|
-
}, []);
|
|
125
|
+
}, [stableProps]);
|
|
130
126
|
const abort = useCallback(() => {
|
|
131
127
|
if (!apiRef.current) {
|
|
132
128
|
return;
|
|
@@ -134,11 +130,11 @@ function Tooltip({
|
|
|
134
130
|
apiRef.current.abort();
|
|
135
131
|
// Only call onHideHandler if we have called onShowHandler
|
|
136
132
|
if (hasCalledShowHandler.current) {
|
|
137
|
-
|
|
133
|
+
stableProps.current.onHideHandler();
|
|
138
134
|
}
|
|
139
135
|
// @ts-ignore
|
|
140
136
|
apiRef.current = null;
|
|
141
|
-
}, []);
|
|
137
|
+
}, [stableProps]);
|
|
142
138
|
useEffect(function mount() {
|
|
143
139
|
return function unmount() {
|
|
144
140
|
if (apiRef.current) {
|
|
@@ -170,7 +166,8 @@ function Tooltip({
|
|
|
170
166
|
}
|
|
171
167
|
});
|
|
172
168
|
}, []);
|
|
173
|
-
const
|
|
169
|
+
const tryShowTooltip = useCallback(source => {
|
|
170
|
+
var _stableProps$current$, _stableProps$current;
|
|
174
171
|
/**
|
|
175
172
|
* Prevent tooltips from being shown during a drag. This can occur with
|
|
176
173
|
* the native drag and drop API, where some pointer events can fire
|
|
@@ -179,25 +176,46 @@ function Tooltip({
|
|
|
179
176
|
if (isDraggingRef.current) {
|
|
180
177
|
return;
|
|
181
178
|
}
|
|
179
|
+
|
|
180
|
+
// Another tooltip is has been active but we still have the old `api`
|
|
181
|
+
// around. We need to finish up the last usage.
|
|
182
|
+
// Note: just being safe - this should not happen
|
|
182
183
|
if (apiRef.current && !apiRef.current.isActive()) {
|
|
183
184
|
abort();
|
|
184
185
|
}
|
|
185
186
|
|
|
186
|
-
//
|
|
187
|
+
// This tooltip is already active, we can exit
|
|
187
188
|
if (apiRef.current && apiRef.current.isActive()) {
|
|
188
189
|
apiRef.current.keep();
|
|
189
190
|
return;
|
|
190
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Check if tooltip is allowed to show.
|
|
195
|
+
*
|
|
196
|
+
* Once a tooltip has started, or has scheduled to start
|
|
197
|
+
* we won't be checking `canAppear` again.
|
|
198
|
+
*
|
|
199
|
+
* - We don't want tooltips to disappear once they are shown
|
|
200
|
+
* - For consistency, we start after a single positive `canAppear`.
|
|
201
|
+
* Otherwise the amount of times we ask consumers would depend on
|
|
202
|
+
* how many times we get a "mousemove", which _could_ lead to situations
|
|
203
|
+
* where moving the mouse could result in a different outcome to if
|
|
204
|
+
* the mouse was not moved.
|
|
205
|
+
*/
|
|
206
|
+
if (stableProps.current.canAppear && !((_stableProps$current$ = (_stableProps$current = stableProps.current).canAppear) !== null && _stableProps$current$ !== void 0 && _stableProps$current$.call(_stableProps$current))) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
191
209
|
const entry = {
|
|
192
210
|
source,
|
|
193
|
-
delay:
|
|
211
|
+
delay: stableProps.current.delay,
|
|
194
212
|
show: ({
|
|
195
213
|
isImmediate
|
|
196
214
|
}) => {
|
|
197
215
|
// Call the onShow handler if it hasn't been called yet
|
|
198
216
|
if (!hasCalledShowHandler.current) {
|
|
199
217
|
hasCalledShowHandler.current = true;
|
|
200
|
-
|
|
218
|
+
stableProps.current.onShowHandler();
|
|
201
219
|
}
|
|
202
220
|
setState(isImmediate ? 'show-immediate' : 'fade-in');
|
|
203
221
|
},
|
|
@@ -210,11 +228,11 @@ function Tooltip({
|
|
|
210
228
|
setState('before-fade-out');
|
|
211
229
|
}
|
|
212
230
|
},
|
|
213
|
-
done
|
|
231
|
+
done
|
|
214
232
|
};
|
|
215
233
|
const api = show(entry);
|
|
216
234
|
start(api);
|
|
217
|
-
}, [abort, done, start]);
|
|
235
|
+
}, [stableProps, abort, done, start]);
|
|
218
236
|
const hideTooltipOnEsc = useCallback(() => {
|
|
219
237
|
var _apiRef$current2;
|
|
220
238
|
(_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.requestHide({
|
|
@@ -290,8 +308,8 @@ function Tooltip({
|
|
|
290
308
|
} : {
|
|
291
309
|
type: 'keyboard'
|
|
292
310
|
};
|
|
293
|
-
|
|
294
|
-
}, [position,
|
|
311
|
+
tryShowTooltip(source);
|
|
312
|
+
}, [position, tryShowTooltip]);
|
|
295
313
|
|
|
296
314
|
// Ideally we would be using onMouseEnter here, but
|
|
297
315
|
// because we are binding the event to the target parent
|
|
@@ -331,10 +349,12 @@ function Tooltip({
|
|
|
331
349
|
}
|
|
332
350
|
}, []);
|
|
333
351
|
const onFocus = useCallback(() => {
|
|
334
|
-
|
|
352
|
+
// TODO: this does not play well with `hideTooltipOnMouseDown`
|
|
353
|
+
// as "focus" will occur after the "mousedown".
|
|
354
|
+
tryShowTooltip({
|
|
335
355
|
type: 'keyboard'
|
|
336
356
|
});
|
|
337
|
-
}, [
|
|
357
|
+
}, [tryShowTooltip]);
|
|
338
358
|
const onBlur = useCallback(() => {
|
|
339
359
|
if (apiRef.current) {
|
|
340
360
|
apiRef.current.requestHide({
|
|
@@ -344,18 +364,19 @@ function Tooltip({
|
|
|
344
364
|
}, []);
|
|
345
365
|
const onAnimationFinished = useCallback(transition => {
|
|
346
366
|
// Using lastState here because motion is not picking up the latest value
|
|
347
|
-
if (transition === 'exiting' &&
|
|
367
|
+
if (transition === 'exiting' && stableState.current === 'fade-out' && apiRef.current) {
|
|
348
368
|
// @ts-ignore: refs are writeable
|
|
349
369
|
apiRef.current.finishHideAnimation();
|
|
350
370
|
}
|
|
351
|
-
}, []);
|
|
371
|
+
}, [stableState]);
|
|
352
372
|
|
|
353
373
|
// Doing a cast because typescript is struggling to narrow the type
|
|
354
374
|
const CastTargetContainer = TargetContainer;
|
|
355
|
-
const
|
|
375
|
+
const shouldRenderTooltipPopup = state !== 'hide' && Boolean(content);
|
|
376
|
+
const shouldRenderHiddenContent = !isScreenReaderAnnouncementDisabled && shouldRenderTooltipPopup;
|
|
356
377
|
const shouldRenderTooltipChildren = state !== 'hide' && state !== 'fade-out';
|
|
357
378
|
useNotifyOpenLayerObserver({
|
|
358
|
-
isOpen:
|
|
379
|
+
isOpen: shouldRenderTooltipPopup
|
|
359
380
|
});
|
|
360
381
|
const getReferenceElement = () => {
|
|
361
382
|
var _apiRef$current4;
|
|
@@ -365,7 +386,7 @@ function Tooltip({
|
|
|
365
386
|
}
|
|
366
387
|
return targetRef.current || undefined;
|
|
367
388
|
};
|
|
368
|
-
const
|
|
389
|
+
const tooltipIdForHiddenContent = useUniqueId('tooltip', shouldRenderHiddenContent);
|
|
369
390
|
const tooltipTriggerProps = {
|
|
370
391
|
onMouseOver,
|
|
371
392
|
onMouseOut,
|
|
@@ -384,26 +405,27 @@ function Tooltip({
|
|
|
384
405
|
|
|
385
406
|
// This useEffect is purely for managing the aria attribute when using the
|
|
386
407
|
// wrapped children approach.
|
|
408
|
+
const isChildrenAFunction = typeof children === 'function';
|
|
387
409
|
useEffect(() => {
|
|
388
|
-
|
|
389
|
-
// means they are using the render prop API, and that is implemented in a
|
|
390
|
-
// different way. If there is no target element yet or tooltipId, we also
|
|
391
|
-
// shouldn't do anything because there is nothing to operate on or with.
|
|
392
|
-
if (!containerRef.current || !targetRef.current || !tooltipId) {
|
|
410
|
+
if (isChildrenAFunction) {
|
|
393
411
|
return;
|
|
394
412
|
}
|
|
413
|
+
|
|
414
|
+
// If `children` is _not_ a function, we are stepping outside of the public
|
|
415
|
+
// API to add a `aria-describedby` attribute.
|
|
416
|
+
|
|
395
417
|
const target = targetRef.current;
|
|
396
|
-
if (
|
|
397
|
-
|
|
398
|
-
} else {
|
|
399
|
-
target.removeAttribute('aria-describedby');
|
|
418
|
+
if (!target || !tooltipIdForHiddenContent) {
|
|
419
|
+
return;
|
|
400
420
|
}
|
|
401
|
-
|
|
402
|
-
|
|
421
|
+
target.setAttribute('aria-describedby', tooltipIdForHiddenContent);
|
|
422
|
+
return () => target.removeAttribute('aria-describedby');
|
|
423
|
+
}, [isChildrenAFunction, tooltipIdForHiddenContent]);
|
|
424
|
+
const hiddenContent = shouldRenderHiddenContent ? /*#__PURE__*/React.createElement("span", {
|
|
403
425
|
"data-testid": testId ? `${testId}-hidden` : undefined,
|
|
404
426
|
hidden: true,
|
|
405
|
-
id:
|
|
406
|
-
}, typeof content === 'function' ? content({}) : content);
|
|
427
|
+
id: tooltipIdForHiddenContent
|
|
428
|
+
}, typeof content === 'function' ? content({}) : content) : null;
|
|
407
429
|
return /*#__PURE__*/React.createElement(React.Fragment, null, typeof children === 'function' ?
|
|
408
430
|
/*#__PURE__*/
|
|
409
431
|
// once we deprecate the wrapped approach, we can put the aria
|
|
@@ -411,12 +433,12 @@ function Tooltip({
|
|
|
411
433
|
// instead of optional in `types`
|
|
412
434
|
React.createElement(React.Fragment, null, children({
|
|
413
435
|
...tooltipTriggerProps,
|
|
414
|
-
'aria-describedby':
|
|
436
|
+
'aria-describedby': tooltipIdForHiddenContent,
|
|
415
437
|
ref: setDirectRef
|
|
416
|
-
}),
|
|
438
|
+
}), hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
|
|
417
439
|
ref: setImplicitRefFromChildren,
|
|
418
440
|
role: "presentation"
|
|
419
|
-
}), children,
|
|
441
|
+
}), children, hiddenContent), shouldRenderTooltipPopup ? /*#__PURE__*/React.createElement(Portal, {
|
|
420
442
|
zIndex: tooltipZIndex
|
|
421
443
|
}, /*#__PURE__*/React.createElement(Popper, {
|
|
422
444
|
placement: tooltipPosition,
|
package/dist/esm/tooltip.js
CHANGED
|
@@ -8,6 +8,7 @@ import { bind } from 'bind-event-listener';
|
|
|
8
8
|
import { usePlatformLeafSyntheticEventHandler } from '@atlaskit/analytics-next';
|
|
9
9
|
import noop from '@atlaskit/ds-lib/noop';
|
|
10
10
|
import useCloseOnEscapePress from '@atlaskit/ds-lib/use-close-on-escape-press';
|
|
11
|
+
import useStableRef from '@atlaskit/ds-lib/use-stable-ref';
|
|
11
12
|
import { useNotifyOpenLayerObserver } from '@atlaskit/layering/experimental/open-layer-observer';
|
|
12
13
|
import { ExitingPersistence, FadeIn } from '@atlaskit/motion';
|
|
13
14
|
import { mediumDurationMs } from '@atlaskit/motion/durations';
|
|
@@ -23,7 +24,7 @@ var tooltipZIndex = layers.tooltip();
|
|
|
23
24
|
var analyticsAttributes = {
|
|
24
25
|
componentName: 'tooltip',
|
|
25
26
|
packageName: "@atlaskit/tooltip",
|
|
26
|
-
packageVersion: "18.
|
|
27
|
+
packageVersion: "18.9.0"
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
// Inverts motion direction
|
|
@@ -68,6 +69,7 @@ function Tooltip(_ref) {
|
|
|
68
69
|
onShow = _ref$onShow === void 0 ? noop : _ref$onShow,
|
|
69
70
|
_ref$onHide = _ref.onHide,
|
|
70
71
|
onHide = _ref$onHide === void 0 ? noop : _ref$onHide,
|
|
72
|
+
canAppear = _ref.canAppear,
|
|
71
73
|
_ref$hideTooltipOnCli = _ref.hideTooltipOnClick,
|
|
72
74
|
hideTooltipOnClick = _ref$hideTooltipOnCli === void 0 ? false : _ref$hideTooltipOnCli,
|
|
73
75
|
_ref$hideTooltipOnMou = _ref.hideTooltipOnMouseDown,
|
|
@@ -76,7 +78,9 @@ function Tooltip(_ref) {
|
|
|
76
78
|
_ref$strategy = _ref.strategy,
|
|
77
79
|
strategy = _ref$strategy === void 0 ? 'fixed' : _ref$strategy,
|
|
78
80
|
_ref$ignoreTooltipPoi = _ref.ignoreTooltipPointerEvents,
|
|
79
|
-
ignoreTooltipPointerEvents = _ref$ignoreTooltipPoi === void 0 ? false : _ref$ignoreTooltipPoi
|
|
81
|
+
ignoreTooltipPointerEvents = _ref$ignoreTooltipPoi === void 0 ? false : _ref$ignoreTooltipPoi,
|
|
82
|
+
_ref$isScreenReaderAn = _ref.isScreenReaderAnnouncementDisabled,
|
|
83
|
+
isScreenReaderAnnouncementDisabled = _ref$isScreenReaderAn === void 0 ? false : _ref$isScreenReaderAn;
|
|
80
84
|
var tooltipPosition = position === 'mouse' ? mousePosition : position;
|
|
81
85
|
var onShowHandler = usePlatformLeafSyntheticEventHandler(_objectSpread({
|
|
82
86
|
fn: onShow,
|
|
@@ -109,21 +113,14 @@ function Tooltip(_ref) {
|
|
|
109
113
|
}, []);
|
|
110
114
|
|
|
111
115
|
// Putting a few things into refs so that we don't have to break memoization
|
|
112
|
-
var
|
|
113
|
-
var
|
|
114
|
-
var lastHandlers = useRef({
|
|
116
|
+
var stableState = useStableRef(state);
|
|
117
|
+
var stableProps = useStableRef({
|
|
115
118
|
onShowHandler: onShowHandler,
|
|
116
|
-
onHideHandler: onHideHandler
|
|
119
|
+
onHideHandler: onHideHandler,
|
|
120
|
+
delay: delay,
|
|
121
|
+
canAppear: canAppear
|
|
117
122
|
});
|
|
118
123
|
var hasCalledShowHandler = useRef(false);
|
|
119
|
-
useEffect(function () {
|
|
120
|
-
lastState.current = state;
|
|
121
|
-
lastDelay.current = delay;
|
|
122
|
-
lastHandlers.current = {
|
|
123
|
-
onShowHandler: onShowHandler,
|
|
124
|
-
onHideHandler: onHideHandler
|
|
125
|
-
};
|
|
126
|
-
}, [delay, onHideHandler, onShowHandler, state]);
|
|
127
124
|
var start = useCallback(function (api) {
|
|
128
125
|
// @ts-ignore
|
|
129
126
|
apiRef.current = api;
|
|
@@ -135,7 +132,7 @@ function Tooltip(_ref) {
|
|
|
135
132
|
}
|
|
136
133
|
// Only call onHideHandler if we have called onShowHandler
|
|
137
134
|
if (hasCalledShowHandler.current) {
|
|
138
|
-
|
|
135
|
+
stableProps.current.onHideHandler();
|
|
139
136
|
}
|
|
140
137
|
// @ts-ignore
|
|
141
138
|
apiRef.current = null;
|
|
@@ -143,7 +140,7 @@ function Tooltip(_ref) {
|
|
|
143
140
|
hasCalledShowHandler.current = false;
|
|
144
141
|
// just in case
|
|
145
142
|
setState('hide');
|
|
146
|
-
}, []);
|
|
143
|
+
}, [stableProps]);
|
|
147
144
|
var abort = useCallback(function () {
|
|
148
145
|
if (!apiRef.current) {
|
|
149
146
|
return;
|
|
@@ -151,11 +148,11 @@ function Tooltip(_ref) {
|
|
|
151
148
|
apiRef.current.abort();
|
|
152
149
|
// Only call onHideHandler if we have called onShowHandler
|
|
153
150
|
if (hasCalledShowHandler.current) {
|
|
154
|
-
|
|
151
|
+
stableProps.current.onHideHandler();
|
|
155
152
|
}
|
|
156
153
|
// @ts-ignore
|
|
157
154
|
apiRef.current = null;
|
|
158
|
-
}, []);
|
|
155
|
+
}, [stableProps]);
|
|
159
156
|
useEffect(function mount() {
|
|
160
157
|
return function unmount() {
|
|
161
158
|
if (apiRef.current) {
|
|
@@ -186,7 +183,8 @@ function Tooltip(_ref) {
|
|
|
186
183
|
}
|
|
187
184
|
});
|
|
188
185
|
}, []);
|
|
189
|
-
var
|
|
186
|
+
var tryShowTooltip = useCallback(function (source) {
|
|
187
|
+
var _stableProps$current$, _stableProps$current;
|
|
190
188
|
/**
|
|
191
189
|
* Prevent tooltips from being shown during a drag. This can occur with
|
|
192
190
|
* the native drag and drop API, where some pointer events can fire
|
|
@@ -195,24 +193,45 @@ function Tooltip(_ref) {
|
|
|
195
193
|
if (isDraggingRef.current) {
|
|
196
194
|
return;
|
|
197
195
|
}
|
|
196
|
+
|
|
197
|
+
// Another tooltip is has been active but we still have the old `api`
|
|
198
|
+
// around. We need to finish up the last usage.
|
|
199
|
+
// Note: just being safe - this should not happen
|
|
198
200
|
if (apiRef.current && !apiRef.current.isActive()) {
|
|
199
201
|
abort();
|
|
200
202
|
}
|
|
201
203
|
|
|
202
|
-
//
|
|
204
|
+
// This tooltip is already active, we can exit
|
|
203
205
|
if (apiRef.current && apiRef.current.isActive()) {
|
|
204
206
|
apiRef.current.keep();
|
|
205
207
|
return;
|
|
206
208
|
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Check if tooltip is allowed to show.
|
|
212
|
+
*
|
|
213
|
+
* Once a tooltip has started, or has scheduled to start
|
|
214
|
+
* we won't be checking `canAppear` again.
|
|
215
|
+
*
|
|
216
|
+
* - We don't want tooltips to disappear once they are shown
|
|
217
|
+
* - For consistency, we start after a single positive `canAppear`.
|
|
218
|
+
* Otherwise the amount of times we ask consumers would depend on
|
|
219
|
+
* how many times we get a "mousemove", which _could_ lead to situations
|
|
220
|
+
* where moving the mouse could result in a different outcome to if
|
|
221
|
+
* the mouse was not moved.
|
|
222
|
+
*/
|
|
223
|
+
if (stableProps.current.canAppear && !((_stableProps$current$ = (_stableProps$current = stableProps.current).canAppear) !== null && _stableProps$current$ !== void 0 && _stableProps$current$.call(_stableProps$current))) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
207
226
|
var entry = {
|
|
208
227
|
source: source,
|
|
209
|
-
delay:
|
|
228
|
+
delay: stableProps.current.delay,
|
|
210
229
|
show: function show(_ref3) {
|
|
211
230
|
var isImmediate = _ref3.isImmediate;
|
|
212
231
|
// Call the onShow handler if it hasn't been called yet
|
|
213
232
|
if (!hasCalledShowHandler.current) {
|
|
214
233
|
hasCalledShowHandler.current = true;
|
|
215
|
-
|
|
234
|
+
stableProps.current.onShowHandler();
|
|
216
235
|
}
|
|
217
236
|
setState(isImmediate ? 'show-immediate' : 'fade-in');
|
|
218
237
|
},
|
|
@@ -228,7 +247,7 @@ function Tooltip(_ref) {
|
|
|
228
247
|
};
|
|
229
248
|
var api = show(entry);
|
|
230
249
|
start(api);
|
|
231
|
-
}, [abort, done, start]);
|
|
250
|
+
}, [stableProps, abort, done, start]);
|
|
232
251
|
var hideTooltipOnEsc = useCallback(function () {
|
|
233
252
|
var _apiRef$current2;
|
|
234
253
|
(_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 || _apiRef$current2.requestHide({
|
|
@@ -304,8 +323,8 @@ function Tooltip(_ref) {
|
|
|
304
323
|
} : {
|
|
305
324
|
type: 'keyboard'
|
|
306
325
|
};
|
|
307
|
-
|
|
308
|
-
}, [position,
|
|
326
|
+
tryShowTooltip(source);
|
|
327
|
+
}, [position, tryShowTooltip]);
|
|
309
328
|
|
|
310
329
|
// Ideally we would be using onMouseEnter here, but
|
|
311
330
|
// because we are binding the event to the target parent
|
|
@@ -345,10 +364,12 @@ function Tooltip(_ref) {
|
|
|
345
364
|
}
|
|
346
365
|
}, []);
|
|
347
366
|
var onFocus = useCallback(function () {
|
|
348
|
-
|
|
367
|
+
// TODO: this does not play well with `hideTooltipOnMouseDown`
|
|
368
|
+
// as "focus" will occur after the "mousedown".
|
|
369
|
+
tryShowTooltip({
|
|
349
370
|
type: 'keyboard'
|
|
350
371
|
});
|
|
351
|
-
}, [
|
|
372
|
+
}, [tryShowTooltip]);
|
|
352
373
|
var onBlur = useCallback(function () {
|
|
353
374
|
if (apiRef.current) {
|
|
354
375
|
apiRef.current.requestHide({
|
|
@@ -358,18 +379,19 @@ function Tooltip(_ref) {
|
|
|
358
379
|
}, []);
|
|
359
380
|
var onAnimationFinished = useCallback(function (transition) {
|
|
360
381
|
// Using lastState here because motion is not picking up the latest value
|
|
361
|
-
if (transition === 'exiting' &&
|
|
382
|
+
if (transition === 'exiting' && stableState.current === 'fade-out' && apiRef.current) {
|
|
362
383
|
// @ts-ignore: refs are writeable
|
|
363
384
|
apiRef.current.finishHideAnimation();
|
|
364
385
|
}
|
|
365
|
-
}, []);
|
|
386
|
+
}, [stableState]);
|
|
366
387
|
|
|
367
388
|
// Doing a cast because typescript is struggling to narrow the type
|
|
368
389
|
var CastTargetContainer = TargetContainer;
|
|
369
|
-
var
|
|
390
|
+
var shouldRenderTooltipPopup = state !== 'hide' && Boolean(content);
|
|
391
|
+
var shouldRenderHiddenContent = !isScreenReaderAnnouncementDisabled && shouldRenderTooltipPopup;
|
|
370
392
|
var shouldRenderTooltipChildren = state !== 'hide' && state !== 'fade-out';
|
|
371
393
|
useNotifyOpenLayerObserver({
|
|
372
|
-
isOpen:
|
|
394
|
+
isOpen: shouldRenderTooltipPopup
|
|
373
395
|
});
|
|
374
396
|
var getReferenceElement = function getReferenceElement() {
|
|
375
397
|
var _apiRef$current4;
|
|
@@ -379,7 +401,7 @@ function Tooltip(_ref) {
|
|
|
379
401
|
}
|
|
380
402
|
return targetRef.current || undefined;
|
|
381
403
|
};
|
|
382
|
-
var
|
|
404
|
+
var tooltipIdForHiddenContent = useUniqueId('tooltip', shouldRenderHiddenContent);
|
|
383
405
|
var tooltipTriggerProps = {
|
|
384
406
|
onMouseOver: onMouseOver,
|
|
385
407
|
onMouseOut: onMouseOut,
|
|
@@ -398,38 +420,41 @@ function Tooltip(_ref) {
|
|
|
398
420
|
|
|
399
421
|
// This useEffect is purely for managing the aria attribute when using the
|
|
400
422
|
// wrapped children approach.
|
|
423
|
+
var isChildrenAFunction = typeof children === 'function';
|
|
401
424
|
useEffect(function () {
|
|
402
|
-
|
|
403
|
-
// means they are using the render prop API, and that is implemented in a
|
|
404
|
-
// different way. If there is no target element yet or tooltipId, we also
|
|
405
|
-
// shouldn't do anything because there is nothing to operate on or with.
|
|
406
|
-
if (!containerRef.current || !targetRef.current || !tooltipId) {
|
|
425
|
+
if (isChildrenAFunction) {
|
|
407
426
|
return;
|
|
408
427
|
}
|
|
428
|
+
|
|
429
|
+
// If `children` is _not_ a function, we are stepping outside of the public
|
|
430
|
+
// API to add a `aria-describedby` attribute.
|
|
431
|
+
|
|
409
432
|
var target = targetRef.current;
|
|
410
|
-
if (
|
|
411
|
-
|
|
412
|
-
} else {
|
|
413
|
-
target.removeAttribute('aria-describedby');
|
|
433
|
+
if (!target || !tooltipIdForHiddenContent) {
|
|
434
|
+
return;
|
|
414
435
|
}
|
|
415
|
-
|
|
416
|
-
|
|
436
|
+
target.setAttribute('aria-describedby', tooltipIdForHiddenContent);
|
|
437
|
+
return function () {
|
|
438
|
+
return target.removeAttribute('aria-describedby');
|
|
439
|
+
};
|
|
440
|
+
}, [isChildrenAFunction, tooltipIdForHiddenContent]);
|
|
441
|
+
var hiddenContent = shouldRenderHiddenContent ? /*#__PURE__*/React.createElement("span", {
|
|
417
442
|
"data-testid": testId ? "".concat(testId, "-hidden") : undefined,
|
|
418
443
|
hidden: true,
|
|
419
|
-
id:
|
|
420
|
-
}, typeof content === 'function' ? content({}) : content);
|
|
444
|
+
id: tooltipIdForHiddenContent
|
|
445
|
+
}, typeof content === 'function' ? content({}) : content) : null;
|
|
421
446
|
return /*#__PURE__*/React.createElement(React.Fragment, null, typeof children === 'function' ?
|
|
422
447
|
/*#__PURE__*/
|
|
423
448
|
// once we deprecate the wrapped approach, we can put the aria
|
|
424
449
|
// attribute back into the tooltipTriggerProps and make it required
|
|
425
450
|
// instead of optional in `types`
|
|
426
451
|
React.createElement(React.Fragment, null, children(_objectSpread(_objectSpread({}, tooltipTriggerProps), {}, {
|
|
427
|
-
'aria-describedby':
|
|
452
|
+
'aria-describedby': tooltipIdForHiddenContent,
|
|
428
453
|
ref: setDirectRef
|
|
429
|
-
})),
|
|
454
|
+
})), hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
|
|
430
455
|
ref: setImplicitRefFromChildren,
|
|
431
456
|
role: "presentation"
|
|
432
|
-
}), children,
|
|
457
|
+
}), children, hiddenContent), shouldRenderTooltipPopup ? /*#__PURE__*/React.createElement(Portal, {
|
|
433
458
|
zIndex: tooltipZIndex
|
|
434
459
|
}, /*#__PURE__*/React.createElement(Popper, {
|
|
435
460
|
placement: tooltipPosition,
|
package/dist/types/tooltip.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type TooltipProps } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* A tooltip is a floating, non-actionable label used to explain a user interface element or feature.
|
|
7
7
|
*/
|
|
8
|
-
declare function Tooltip({ children, position, mousePosition, content, truncate, component: Container, tag: TargetContainer, testId, delay, onShow, onHide, hideTooltipOnClick, hideTooltipOnMouseDown, analyticsContext, strategy, ignoreTooltipPointerEvents, }: TooltipProps): JSX.Element;
|
|
8
|
+
declare function Tooltip({ children, position, mousePosition, content, truncate, component: Container, tag: TargetContainer, testId, delay, onShow, onHide, canAppear, hideTooltipOnClick, hideTooltipOnMouseDown, analyticsContext, strategy, ignoreTooltipPointerEvents, isScreenReaderAnnouncementDisabled, }: TooltipProps): JSX.Element;
|
|
9
9
|
declare namespace Tooltip {
|
|
10
10
|
var displayName: string;
|
|
11
11
|
}
|
package/dist/types/types.d.ts
CHANGED
|
@@ -22,6 +22,11 @@ export interface TooltipProps {
|
|
|
22
22
|
* 2. Function which returns a `ReactNode`
|
|
23
23
|
* The benefit of the second approach is that it allows you to consume the `update` render prop.
|
|
24
24
|
* This `update` function can be called to manually recalculate the position of the tooltip.
|
|
25
|
+
*
|
|
26
|
+
* This content will be rendered into two places:
|
|
27
|
+
* 1. Into the tooltip
|
|
28
|
+
* 2. Into a hidden element for screen readers (unless `isScreenReaderAnnouncementDisabled` is set to `true`)
|
|
29
|
+
*
|
|
25
30
|
*/
|
|
26
31
|
content: ReactNode | (({ update }: {
|
|
27
32
|
update?: () => void;
|
|
@@ -55,6 +60,25 @@ export interface TooltipProps {
|
|
|
55
60
|
* When interacting with the target element using a keyboard, it will use this position against the target element instead.
|
|
56
61
|
*/
|
|
57
62
|
mousePosition?: PositionTypeBase;
|
|
63
|
+
/**
|
|
64
|
+
* Whether or not the tooltip can be displayed. Once a tooltip
|
|
65
|
+
* is scheduled to be displayed, or is already displayed, it will
|
|
66
|
+
* continue to be shown.
|
|
67
|
+
*
|
|
68
|
+
* @description
|
|
69
|
+
*
|
|
70
|
+
* `canAppear()` is called in response to user events, and
|
|
71
|
+
* not during the rendering of components.
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
canAppear?: () => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* By default tooltip content will be duplicated into a hidden element so
|
|
77
|
+
* it can be read out by a screen reader. Sometimes this is not ideal as
|
|
78
|
+
* it can result in the same content be announced twice. For those situations,
|
|
79
|
+
* you can leverage this prop to disable the duplicate hidden text.
|
|
80
|
+
*/
|
|
81
|
+
isScreenReaderAnnouncementDisabled?: boolean;
|
|
58
82
|
/**
|
|
59
83
|
* Function to be called when the tooltip will be shown. It's called when the
|
|
60
84
|
* tooltip begins to animate in.
|
|
@@ -5,7 +5,7 @@ import { type TooltipProps } from './types';
|
|
|
5
5
|
*
|
|
6
6
|
* A tooltip is a floating, non-actionable label used to explain a user interface element or feature.
|
|
7
7
|
*/
|
|
8
|
-
declare function Tooltip({ children, position, mousePosition, content, truncate, component: Container, tag: TargetContainer, testId, delay, onShow, onHide, hideTooltipOnClick, hideTooltipOnMouseDown, analyticsContext, strategy, ignoreTooltipPointerEvents, }: TooltipProps): JSX.Element;
|
|
8
|
+
declare function Tooltip({ children, position, mousePosition, content, truncate, component: Container, tag: TargetContainer, testId, delay, onShow, onHide, canAppear, hideTooltipOnClick, hideTooltipOnMouseDown, analyticsContext, strategy, ignoreTooltipPointerEvents, isScreenReaderAnnouncementDisabled, }: TooltipProps): JSX.Element;
|
|
9
9
|
declare namespace Tooltip {
|
|
10
10
|
var displayName: string;
|
|
11
11
|
}
|
|
@@ -22,6 +22,11 @@ export interface TooltipProps {
|
|
|
22
22
|
* 2. Function which returns a `ReactNode`
|
|
23
23
|
* The benefit of the second approach is that it allows you to consume the `update` render prop.
|
|
24
24
|
* This `update` function can be called to manually recalculate the position of the tooltip.
|
|
25
|
+
*
|
|
26
|
+
* This content will be rendered into two places:
|
|
27
|
+
* 1. Into the tooltip
|
|
28
|
+
* 2. Into a hidden element for screen readers (unless `isScreenReaderAnnouncementDisabled` is set to `true`)
|
|
29
|
+
*
|
|
25
30
|
*/
|
|
26
31
|
content: ReactNode | (({ update }: {
|
|
27
32
|
update?: () => void;
|
|
@@ -55,6 +60,25 @@ export interface TooltipProps {
|
|
|
55
60
|
* When interacting with the target element using a keyboard, it will use this position against the target element instead.
|
|
56
61
|
*/
|
|
57
62
|
mousePosition?: PositionTypeBase;
|
|
63
|
+
/**
|
|
64
|
+
* Whether or not the tooltip can be displayed. Once a tooltip
|
|
65
|
+
* is scheduled to be displayed, or is already displayed, it will
|
|
66
|
+
* continue to be shown.
|
|
67
|
+
*
|
|
68
|
+
* @description
|
|
69
|
+
*
|
|
70
|
+
* `canAppear()` is called in response to user events, and
|
|
71
|
+
* not during the rendering of components.
|
|
72
|
+
*
|
|
73
|
+
*/
|
|
74
|
+
canAppear?: () => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* By default tooltip content will be duplicated into a hidden element so
|
|
77
|
+
* it can be read out by a screen reader. Sometimes this is not ideal as
|
|
78
|
+
* it can result in the same content be announced twice. For those situations,
|
|
79
|
+
* you can leverage this prop to disable the duplicate hidden text.
|
|
80
|
+
*/
|
|
81
|
+
isScreenReaderAnnouncementDisabled?: boolean;
|
|
58
82
|
/**
|
|
59
83
|
* Function to be called when the tooltip will be shown. It's called when the
|
|
60
84
|
* tooltip begins to animate in.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/tooltip",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.9.0",
|
|
4
4
|
"description": "A tooltip is a floating, non-actionable label used to explain a user interface element or feature.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -40,13 +40,13 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@atlaskit/analytics-next": "^10.1.0",
|
|
43
|
-
"@atlaskit/ds-lib": "^3.
|
|
44
|
-
"@atlaskit/layering": "^0.
|
|
43
|
+
"@atlaskit/ds-lib": "^3.2.0",
|
|
44
|
+
"@atlaskit/layering": "^0.7.0",
|
|
45
45
|
"@atlaskit/motion": "^1.9.0",
|
|
46
46
|
"@atlaskit/popper": "^6.3.0",
|
|
47
47
|
"@atlaskit/portal": "^4.9.0",
|
|
48
48
|
"@atlaskit/theme": "^14.0.0",
|
|
49
|
-
"@atlaskit/tokens": "^2.
|
|
49
|
+
"@atlaskit/tokens": "^2.2.0",
|
|
50
50
|
"@babel/runtime": "^7.0.0",
|
|
51
51
|
"@emotion/react": "^11.7.1",
|
|
52
52
|
"bind-event-listener": "^3.0.0"
|
|
@@ -57,7 +57,8 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@af/accessibility-testing": "*",
|
|
60
|
-
"@
|
|
60
|
+
"@af/integration-testing": "*",
|
|
61
|
+
"@atlaskit/button": "^20.3.0",
|
|
61
62
|
"@atlaskit/ssr": "*",
|
|
62
63
|
"@atlaskit/visual-regression": "*",
|
|
63
64
|
"@emotion/styled": "^11.0.0",
|