@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 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
@@ -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.8.4"
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 lastState = (0, _react.useRef)(state);
123
- var lastDelay = (0, _react.useRef)(delay);
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
- lastHandlers.current.onHideHandler();
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
- lastHandlers.current.onHideHandler();
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 showTooltip = (0, _react.useCallback)(function (source) {
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
- // Tell the tooltip to keep showing
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: lastDelay.current,
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
- lastHandlers.current.onShowHandler();
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
- showTooltip(source);
318
- }, [position, showTooltip]);
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
- showTooltip({
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
- }, [showTooltip]);
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' && lastState.current === 'fade-out' && apiRef.current) {
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 shouldRenderTooltipContainer = state !== 'hide' && Boolean(content);
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: shouldRenderTooltipContainer
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 tooltipId = (0, _useUniqueId.default)('tooltip', shouldRenderTooltipContainer);
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
- // If there is no container element, we should exit early, because that
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 (shouldRenderTooltipContainer) {
421
- target.setAttribute('aria-describedby', tooltipId);
422
- } else {
423
- target.removeAttribute('aria-describedby');
443
+ if (!target || !tooltipIdForHiddenContent) {
444
+ return;
424
445
  }
425
- }, [shouldRenderTooltipContainer, tooltipId]);
426
- var hiddenContent = /*#__PURE__*/_react.default.createElement("span", {
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: tooltipId
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': tooltipId,
462
+ 'aria-describedby': tooltipIdForHiddenContent,
438
463
  ref: setDirectRef
439
- })), shouldRenderTooltipContainer && hiddenContent) : /*#__PURE__*/_react.default.createElement(CastTargetContainer, (0, _extends2.default)({}, tooltipTriggerProps, {
464
+ })), hiddenContent) : /*#__PURE__*/_react.default.createElement(CastTargetContainer, (0, _extends2.default)({}, tooltipTriggerProps, {
440
465
  ref: setImplicitRefFromChildren,
441
466
  role: "presentation"
442
- }), children, shouldRenderTooltipContainer && hiddenContent), shouldRenderTooltipContainer ? /*#__PURE__*/_react.default.createElement(_portal.default, {
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,
@@ -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.8.4"
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 lastState = useRef(state);
96
- const lastDelay = useRef(delay);
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
- lastHandlers.current.onHideHandler();
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
- lastHandlers.current.onHideHandler();
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 showTooltip = useCallback(source => {
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
- // Tell the tooltip to keep showing
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: lastDelay.current,
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
- lastHandlers.current.onShowHandler();
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: 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
- showTooltip(source);
294
- }, [position, showTooltip]);
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
- showTooltip({
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
- }, [showTooltip]);
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' && lastState.current === 'fade-out' && apiRef.current) {
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 shouldRenderTooltipContainer = state !== 'hide' && Boolean(content);
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: shouldRenderTooltipContainer
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 tooltipId = useUniqueId('tooltip', shouldRenderTooltipContainer);
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
- // If there is no container element, we should exit early, because that
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 (shouldRenderTooltipContainer) {
397
- target.setAttribute('aria-describedby', tooltipId);
398
- } else {
399
- target.removeAttribute('aria-describedby');
418
+ if (!target || !tooltipIdForHiddenContent) {
419
+ return;
400
420
  }
401
- }, [shouldRenderTooltipContainer, tooltipId]);
402
- const hiddenContent = /*#__PURE__*/React.createElement("span", {
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: tooltipId
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': tooltipId,
436
+ 'aria-describedby': tooltipIdForHiddenContent,
415
437
  ref: setDirectRef
416
- }), shouldRenderTooltipContainer && hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
438
+ }), hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
417
439
  ref: setImplicitRefFromChildren,
418
440
  role: "presentation"
419
- }), children, shouldRenderTooltipContainer && hiddenContent), shouldRenderTooltipContainer ? /*#__PURE__*/React.createElement(Portal, {
441
+ }), children, hiddenContent), shouldRenderTooltipPopup ? /*#__PURE__*/React.createElement(Portal, {
420
442
  zIndex: tooltipZIndex
421
443
  }, /*#__PURE__*/React.createElement(Popper, {
422
444
  placement: tooltipPosition,
@@ -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.8.4"
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 lastState = useRef(state);
113
- var lastDelay = useRef(delay);
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
- lastHandlers.current.onHideHandler();
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
- lastHandlers.current.onHideHandler();
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 showTooltip = useCallback(function (source) {
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
- // Tell the tooltip to keep showing
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: lastDelay.current,
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
- lastHandlers.current.onShowHandler();
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
- showTooltip(source);
308
- }, [position, showTooltip]);
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
- showTooltip({
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
- }, [showTooltip]);
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' && lastState.current === 'fade-out' && apiRef.current) {
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 shouldRenderTooltipContainer = state !== 'hide' && Boolean(content);
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: shouldRenderTooltipContainer
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 tooltipId = useUniqueId('tooltip', shouldRenderTooltipContainer);
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
- // If there is no container element, we should exit early, because that
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 (shouldRenderTooltipContainer) {
411
- target.setAttribute('aria-describedby', tooltipId);
412
- } else {
413
- target.removeAttribute('aria-describedby');
433
+ if (!target || !tooltipIdForHiddenContent) {
434
+ return;
414
435
  }
415
- }, [shouldRenderTooltipContainer, tooltipId]);
416
- var hiddenContent = /*#__PURE__*/React.createElement("span", {
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: tooltipId
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': tooltipId,
452
+ 'aria-describedby': tooltipIdForHiddenContent,
428
453
  ref: setDirectRef
429
- })), shouldRenderTooltipContainer && hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
454
+ })), hiddenContent) : /*#__PURE__*/React.createElement(CastTargetContainer, _extends({}, tooltipTriggerProps, {
430
455
  ref: setImplicitRefFromChildren,
431
456
  role: "presentation"
432
- }), children, shouldRenderTooltipContainer && hiddenContent), shouldRenderTooltipContainer ? /*#__PURE__*/React.createElement(Portal, {
457
+ }), children, hiddenContent), shouldRenderTooltipPopup ? /*#__PURE__*/React.createElement(Portal, {
433
458
  zIndex: tooltipZIndex
434
459
  }, /*#__PURE__*/React.createElement(Popper, {
435
460
  placement: tooltipPosition,
@@ -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.
@@ -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.8.4",
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.1.0",
44
- "@atlaskit/layering": "^0.6.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.0.0",
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
- "@atlaskit/button": "^20.2.0",
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",