@atlaskit/side-navigation 3.5.4 → 3.6.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,20 @@
1
1
  # @atlaskit/side-navigation
2
2
 
3
+ ## 3.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#160699](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/160699)
8
+ [`a4cb190f3a282`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/a4cb190f3a282) -
9
+ Side navigation, keyboard focus should appear on first interactive element which is `Go back`
10
+ button and when `Go back` control is activated, focus should appear on the triggered element.
11
+
12
+ ## 3.5.5
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies
17
+
3
18
  ## 3.5.4
4
19
 
5
20
  ### Patch Changes
@@ -5,8 +5,7 @@
5
5
  "target": "es5",
6
6
  "composite": true,
7
7
  "outDir": "../dist",
8
- "rootDir": "../",
9
- "baseUrl": "../"
8
+ "rootDir": "../"
10
9
  },
11
10
  "include": [
12
11
  "../src/**/*.ts",
@@ -30,6 +29,9 @@
30
29
  {
31
30
  "path": "../../motion/afm-cc/tsconfig.json"
32
31
  },
32
+ {
33
+ "path": "../../../platform/feature-flags/afm-cc/tsconfig.json"
34
+ },
33
35
  {
34
36
  "path": "../../primitives/afm-cc/tsconfig.json"
35
37
  },
@@ -1,42 +1,42 @@
1
1
  {
2
- "extends": "../../../../tsconfig.entry-points.jira.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "target": "es5",
6
- "outDir": "../../../../../tsDist/@atlaskit__side-navigation/app",
7
- "composite": true,
8
- "rootDir": "../"
9
- },
10
- "include": [
11
- "../src/**/*.ts",
12
- "../src/**/*.tsx"
13
- ],
14
- "exclude": [
15
- "../src/**/__tests__/*",
16
- "../src/**/*.test.*",
17
- "../src/**/test.*"
18
- ],
19
- "references": [
20
- {
21
- "path": "../../ds-lib/afm-jira/tsconfig.json"
22
- },
23
- {
24
- "path": "../../icon/afm-jira/tsconfig.json"
25
- },
26
- {
27
- "path": "../../menu/afm-jira/tsconfig.json"
28
- },
29
- {
30
- "path": "../../motion/afm-jira/tsconfig.json"
31
- },
32
- {
33
- "path": "../../primitives/afm-jira/tsconfig.json"
34
- },
35
- {
36
- "path": "../../theme/afm-jira/tsconfig.json"
37
- },
38
- {
39
- "path": "../../tokens/afm-jira/tsconfig.json"
40
- }
41
- ]
42
- }
2
+ "extends": "../../../../tsconfig.entry-points.jira.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "target": "es5",
6
+ "outDir": "../../../../../tsDist/@atlaskit__side-navigation/app",
7
+ "rootDir": "../",
8
+ "composite": true
9
+ },
10
+ "include": [
11
+ "../src/**/*.ts",
12
+ "../src/**/*.tsx"
13
+ ],
14
+ "exclude": [
15
+ "../src/**/__tests__/*",
16
+ "../src/**/*.test.*",
17
+ "../src/**/test.*"
18
+ ],
19
+ "references": [
20
+ {
21
+ "path": "../../ds-lib/afm-jira/tsconfig.json"
22
+ },
23
+ {
24
+ "path": "../../icon/afm-jira/tsconfig.json"
25
+ },
26
+ {
27
+ "path": "../../menu/afm-jira/tsconfig.json"
28
+ },
29
+ {
30
+ "path": "../../motion/afm-jira/tsconfig.json"
31
+ },
32
+ {
33
+ "path": "../../primitives/afm-jira/tsconfig.json"
34
+ },
35
+ {
36
+ "path": "../../theme/afm-jira/tsconfig.json"
37
+ },
38
+ {
39
+ "path": "../../tokens/afm-jira/tsconfig.json"
40
+ }
41
+ ]
42
+ }
@@ -1,42 +1,45 @@
1
1
  {
2
- "extends": "../../../../tsconfig.entry-points.post-office.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "target": "es5",
6
- "outDir": "../../../../../tsDist/@atlaskit__side-navigation/app",
7
- "composite": true,
8
- "rootDir": "../"
9
- },
10
- "include": [
11
- "../src/**/*.ts",
12
- "../src/**/*.tsx"
13
- ],
14
- "exclude": [
15
- "../src/**/__tests__/*",
16
- "../src/**/*.test.*",
17
- "../src/**/test.*"
18
- ],
19
- "references": [
20
- {
21
- "path": "../../ds-lib/afm-post-office/tsconfig.json"
22
- },
23
- {
24
- "path": "../../icon/afm-post-office/tsconfig.json"
25
- },
26
- {
27
- "path": "../../menu/afm-post-office/tsconfig.json"
28
- },
29
- {
30
- "path": "../../motion/afm-post-office/tsconfig.json"
31
- },
32
- {
33
- "path": "../../primitives/afm-post-office/tsconfig.json"
34
- },
35
- {
36
- "path": "../../theme/afm-post-office/tsconfig.json"
37
- },
38
- {
39
- "path": "../../tokens/afm-post-office/tsconfig.json"
40
- }
41
- ]
42
- }
2
+ "extends": "../../../../tsconfig.entry-points.post-office.json",
3
+ "compilerOptions": {
4
+ "declaration": true,
5
+ "target": "es5",
6
+ "outDir": "../../../../../tsDist/@atlaskit__side-navigation/app",
7
+ "rootDir": "../",
8
+ "composite": true
9
+ },
10
+ "include": [
11
+ "../src/**/*.ts",
12
+ "../src/**/*.tsx"
13
+ ],
14
+ "exclude": [
15
+ "../src/**/__tests__/*",
16
+ "../src/**/*.test.*",
17
+ "../src/**/test.*"
18
+ ],
19
+ "references": [
20
+ {
21
+ "path": "../../ds-lib/afm-post-office/tsconfig.json"
22
+ },
23
+ {
24
+ "path": "../../icon/afm-post-office/tsconfig.json"
25
+ },
26
+ {
27
+ "path": "../../menu/afm-post-office/tsconfig.json"
28
+ },
29
+ {
30
+ "path": "../../motion/afm-post-office/tsconfig.json"
31
+ },
32
+ {
33
+ "path": "../../../platform/feature-flags/afm-post-office/tsconfig.json"
34
+ },
35
+ {
36
+ "path": "../../primitives/afm-post-office/tsconfig.json"
37
+ },
38
+ {
39
+ "path": "../../theme/afm-post-office/tsconfig.json"
40
+ },
41
+ {
42
+ "path": "../../tokens/afm-post-office/tsconfig.json"
43
+ }
44
+ ]
45
+ }
@@ -1,20 +1,24 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
8
  exports.default = exports.ROOT_ID = void 0;
8
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
- var _react = require("react");
11
+ var _react = _interopRequireWildcard(require("react"));
11
12
  var _react2 = require("@emotion/react");
12
13
  var _motion = require("@atlaskit/motion");
14
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
13
15
  var _Item = require("../Item");
14
16
  var _NestingItem = _interopRequireDefault(require("../NestingItem"));
15
17
  var _hooks = require("../utils/hooks");
16
18
  var _context = require("./context");
17
19
  var _nestingMotion = require("./nesting-motion");
20
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
21
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
18
22
  /**
19
23
  * @jsxRuntime classic
20
24
  * @jsx jsx
@@ -55,7 +59,10 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
55
59
  onChange = props.onChange,
56
60
  onUnknownNest = props.onUnknownNest,
57
61
  stack = props.stack,
58
- showTopScrollIndicator = props.showTopScrollIndicator;
62
+ showTopScrollIndicator = props.showTopScrollIndicator,
63
+ _props$isDefaultFocus = props.isDefaultFocusControl,
64
+ isDefaultFocusControl = _props$isDefaultFocus === void 0 ? true : _props$isDefaultFocus;
65
+ var goBackButtonRef = (0, _react.useRef)(null);
59
66
  var _useState = (0, _react.useState)(stack || initialStack || []),
60
67
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
61
68
  committedStack = _useState2[0],
@@ -67,6 +74,15 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
67
74
  transition = _useState4[0],
68
75
  setTransition = _useState4[1];
69
76
  var backTestId = testId && "".concat(testId, "--go-back-item");
77
+ var _useState5 = (0, _react.useState)(''),
78
+ _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
79
+ activeParentId = _useState6[0],
80
+ setActiveParentId = _useState6[1];
81
+ var _useState7 = (0, _react.useState)(false),
82
+ _useState8 = (0, _slicedToArray2.default)(_useState7, 2),
83
+ focusGoBackButton = _useState8[0],
84
+ setFocusGoBackButton = _useState8[1];
85
+ var shouldFocus = isDefaultFocusControl && (0, _platformFeatureFlags.fg)('platform-side-navigation-keyboard-focus');
70
86
  var renderGoBackItem = overrides && overrides.GoBackItem && overrides.GoBackItem.render ? overrides.GoBackItem.render : function (props) {
71
87
  return (0, _react2.jsx)(_Item.GoBackItem, props, "Go back");
72
88
  };
@@ -74,11 +90,11 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
74
90
  childIdsRef = _useChildIds.childIdsRef;
75
91
  var onNestHandler = (0, _react.useCallback)(function (layerId) {
76
92
  onChange && onChange(committedStack.concat(layerId));
93
+ setFocusGoBackButton(true);
77
94
  if (controlledStack) {
78
95
  // We are in controlled mode - ignore the steps.
79
96
  return;
80
97
  }
81
-
82
98
  // We need to split the state update into to parts.
83
99
  // First: Updating the direction of the motions.
84
100
  // Second: Actually updating the stack (which will cause elements to enter & leave).
@@ -92,6 +108,8 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
92
108
  }, [controlledStack, onChange, committedStack]);
93
109
  var onUnNestHandler = (0, _react.useCallback)(function () {
94
110
  onChange && onChange(committedStack.slice(0, committedStack.length - 1));
111
+ setActiveParentId(currentStackId);
112
+ setFocusGoBackButton(false);
95
113
  if (controlledStack) {
96
114
  // We are in controlled mode - ignore the steps.
97
115
  return;
@@ -107,7 +125,7 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
107
125
  return newStack;
108
126
  });
109
127
  });
110
- }, [controlledStack, onChange, committedStack]);
128
+ }, [controlledStack, onChange, committedStack, setActiveParentId, currentStackId]);
111
129
  (0, _react.useEffect)(function () {
112
130
  if (!controlledStack) {
113
131
  // We aren't in controlled mode - bail out.
@@ -132,7 +150,8 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
132
150
  }, [committedStack, controlledStack]);
133
151
  var backButton = renderGoBackItem({
134
152
  onClick: onUnNestHandler,
135
- testId: backTestId
153
+ testId: backTestId,
154
+ ref: shouldFocus ? goBackButtonRef : null
136
155
  });
137
156
  var context = (0, _react.useMemo)(function () {
138
157
  return {
@@ -143,9 +162,13 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
143
162
  onUnNest: onUnNestHandler,
144
163
  parentId: ROOT_ID,
145
164
  childIds: childIdsRef,
146
- forceShowTopScrollIndicator: showTopScrollIndicator
165
+ forceShowTopScrollIndicator: showTopScrollIndicator,
166
+ activeParentId: activeParentId,
167
+ goBackButtonRef: goBackButtonRef,
168
+ isDefaultFocusControl: isDefaultFocusControl,
169
+ focusGoBackButton: focusGoBackButton
147
170
  };
148
- }, [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator]);
171
+ }, [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
149
172
  var manageFocus = function manageFocus(event) {
150
173
  var triggeredByKeyboard = event.nativeEvent.detail === 0;
151
174
  if (triggeredByKeyboard) {
@@ -14,6 +14,7 @@ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/h
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
  var _react2 = require("@emotion/react");
16
16
  var _arrowRightArrowRightCircle = _interopRequireDefault(require("@atlaskit/icon/core/migration/arrow-right--arrow-right-circle"));
17
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
18
  var _primitives = require("@atlaskit/primitives");
18
19
  var _colors = require("@atlaskit/theme/colors");
19
20
  var _styles = require("../../common/styles");
@@ -61,15 +62,45 @@ var NestingItem = function NestingItem(props) {
61
62
  contextualBackButton = _useNestedContext.backButton,
62
63
  stack = _useNestedContext.stack,
63
64
  childIds = _useNestedContext.childIds,
64
- forceShowTopScrollIndicator = _useNestedContext.forceShowTopScrollIndicator;
65
+ forceShowTopScrollIndicator = _useNestedContext.forceShowTopScrollIndicator,
66
+ activeParentId = _useNestedContext.activeParentId,
67
+ goBackButtonRef = _useNestedContext.goBackButtonRef,
68
+ isDefaultFocusControl = _useNestedContext.isDefaultFocusControl,
69
+ focusGoBackButton = _useNestedContext.focusGoBackButton;
65
70
  var mergedStyles = (0, _styles.overrideStyleFunction)(_styles2.nestingItemStyle, cssFn);
66
71
  var _useState = (0, _react.useState)(false),
67
72
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
68
73
  isInteracted = _useState2[0],
69
74
  setIsInteracted = _useState2[1];
75
+ var parentItemRef = (0, _react.useRef)(null);
76
+
77
+ // To avoid error we need to make sure that the component is wrapped in ForwardRef
78
+ var isForwardRefCheck = function isForwardRefCheck(component) {
79
+ var _component$prototype;
80
+ if (component !== null && component !== void 0 && (_component$prototype = component.prototype) !== null && _component$prototype !== void 0 && _component$prototype.isReactComponent) {
81
+ return false;
82
+ }
83
+ return (component === null || component === void 0 ? void 0 : component.$$typeof) === Symbol.for('react.forward_ref');
84
+ };
85
+ var shouldFocus = isDefaultFocusControl && (0, _platformFeatureFlags.fg)('platform-side-navigation-keyboard-focus');
86
+ var backButtonRef = shouldFocus ? goBackButtonRef : null;
87
+ var activeParentRef = shouldFocus ? parentItemRef : null;
88
+ (0, _react.useEffect)(function () {
89
+ if (shouldFocus) {
90
+ if (activeParentId === id) {
91
+ var _parentItemRef$curren;
92
+ parentItemRef === null || parentItemRef === void 0 || (_parentItemRef$curren = parentItemRef.current) === null || _parentItemRef$curren === void 0 || _parentItemRef$curren.focus();
93
+ }
94
+ if (focusGoBackButton) {
95
+ var _goBackButtonRef$curr;
96
+ goBackButtonRef === null || goBackButtonRef === void 0 || (_goBackButtonRef$curr = goBackButtonRef.current) === null || _goBackButtonRef$curr === void 0 || _goBackButtonRef$curr.focus();
97
+ }
98
+ }
99
+ }, [activeParentId, id, goBackButtonRef, focusGoBackButton, isDefaultFocusControl, shouldFocus]);
70
100
  var backButton = props.overrides && props.overrides.GoBackItem && props.overrides.GoBackItem.render && props.overrides.GoBackItem.render({
71
101
  onClick: onUnNest,
72
- testId: testId && "".concat(testId, "--go-back-item")
102
+ testId: testId && "".concat(testId, "--go-back-item"),
103
+ ref: backButtonRef
73
104
  }) || contextualBackButton;
74
105
  var context = (0, _react.useMemo)(function () {
75
106
  return {
@@ -80,9 +111,13 @@ var NestingItem = function NestingItem(props) {
80
111
  backButton: backButton,
81
112
  parentId: id,
82
113
  childIds: childIds,
83
- forceShowTopScrollIndicator: forceShowTopScrollIndicator
114
+ forceShowTopScrollIndicator: forceShowTopScrollIndicator,
115
+ activeParentId: activeParentId,
116
+ goBackButtonRef: goBackButtonRef,
117
+ isDefaultFocusControl: isDefaultFocusControl,
118
+ focusGoBackButton: focusGoBackButton
84
119
  };
85
- }, [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator]);
120
+ }, [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
86
121
  (0, _hooks.useChildIdsEffect)(childIds, id);
87
122
  var isNormalClick = function isNormalClick(e) {
88
123
  return !(e.button || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
@@ -144,11 +179,15 @@ var NestingItem = function NestingItem(props) {
144
179
  cssFn: mergedStyles
145
180
  });
146
181
  if (component) {
147
- return (0, _react2.jsx)(_index.CustomItem, (0, _extends2.default)({}, componentProps, {
182
+ return (0, _react2.jsx)(_index.CustomItem, (0, _extends2.default)({
183
+ ref: isForwardRefCheck(component) ? parentItemRef : null
184
+ }, componentProps, {
148
185
  //@ts-expect-error TODO Fix legit TypeScript 3.9.6 improved inference error
149
186
  component: component
150
187
  }));
151
188
  }
152
- return (0, _react2.jsx)(_index.ButtonItem, componentProps);
189
+ return (0, _react2.jsx)(_index.ButtonItem, (0, _extends2.default)({
190
+ ref: activeParentRef
191
+ }, componentProps));
153
192
  };
154
193
  var _default = exports.default = NestingItem;
@@ -3,11 +3,12 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  * @jsxRuntime classic
4
4
  * @jsx jsx
5
5
  */
6
- import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
6
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
7
 
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
9
9
  import { css, jsx } from '@emotion/react';
10
10
  import { ExitingPersistence } from '@atlaskit/motion';
11
+ import { fg } from '@atlaskit/platform-feature-flags';
11
12
  import { GoBackItem as GoBackButton } from '../Item';
12
13
  import { default as NestingItem } from '../NestingItem';
13
14
  import { useChildIds } from '../utils/hooks';
@@ -47,24 +48,29 @@ const NestableNavigationContent = props => {
47
48
  onChange,
48
49
  onUnknownNest,
49
50
  stack,
50
- showTopScrollIndicator
51
+ showTopScrollIndicator,
52
+ isDefaultFocusControl = true
51
53
  } = props;
54
+ const goBackButtonRef = useRef(null);
52
55
  const [committedStack, setCommittedStack] = useState(stack || initialStack || []);
53
56
  const controlledStack = stack || undefined;
54
57
  const currentStackId = committedStack[committedStack.length - 1] || ROOT_ID;
55
58
  const [transition, setTransition] = useState('nesting');
56
59
  const backTestId = testId && `${testId}--go-back-item`;
60
+ const [activeParentId, setActiveParentId] = useState('');
61
+ const [focusGoBackButton, setFocusGoBackButton] = useState(false);
62
+ const shouldFocus = isDefaultFocusControl && fg('platform-side-navigation-keyboard-focus');
57
63
  const renderGoBackItem = overrides && overrides.GoBackItem && overrides.GoBackItem.render ? overrides.GoBackItem.render : props => jsx(GoBackButton, props, "Go back");
58
64
  const {
59
65
  childIdsRef
60
66
  } = useChildIds(currentStackId, committedStack, onUnknownNest);
61
67
  const onNestHandler = useCallback(layerId => {
62
68
  onChange && onChange(committedStack.concat(layerId));
69
+ setFocusGoBackButton(true);
63
70
  if (controlledStack) {
64
71
  // We are in controlled mode - ignore the steps.
65
72
  return;
66
73
  }
67
-
68
74
  // We need to split the state update into to parts.
69
75
  // First: Updating the direction of the motions.
70
76
  // Second: Actually updating the stack (which will cause elements to enter & leave).
@@ -78,6 +84,8 @@ const NestableNavigationContent = props => {
78
84
  }, [controlledStack, onChange, committedStack]);
79
85
  const onUnNestHandler = useCallback(() => {
80
86
  onChange && onChange(committedStack.slice(0, committedStack.length - 1));
87
+ setActiveParentId(currentStackId);
88
+ setFocusGoBackButton(false);
81
89
  if (controlledStack) {
82
90
  // We are in controlled mode - ignore the steps.
83
91
  return;
@@ -93,7 +101,7 @@ const NestableNavigationContent = props => {
93
101
  return newStack;
94
102
  });
95
103
  });
96
- }, [controlledStack, onChange, committedStack]);
104
+ }, [controlledStack, onChange, committedStack, setActiveParentId, currentStackId]);
97
105
  useEffect(() => {
98
106
  if (!controlledStack) {
99
107
  // We aren't in controlled mode - bail out.
@@ -118,7 +126,8 @@ const NestableNavigationContent = props => {
118
126
  }, [committedStack, controlledStack]);
119
127
  const backButton = renderGoBackItem({
120
128
  onClick: onUnNestHandler,
121
- testId: backTestId
129
+ testId: backTestId,
130
+ ref: shouldFocus ? goBackButtonRef : null
122
131
  });
123
132
  const context = useMemo(() => ({
124
133
  currentStackId,
@@ -128,8 +137,12 @@ const NestableNavigationContent = props => {
128
137
  onUnNest: onUnNestHandler,
129
138
  parentId: ROOT_ID,
130
139
  childIds: childIdsRef,
131
- forceShowTopScrollIndicator: showTopScrollIndicator
132
- }), [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator]);
140
+ forceShowTopScrollIndicator: showTopScrollIndicator,
141
+ activeParentId,
142
+ goBackButtonRef,
143
+ isDefaultFocusControl,
144
+ focusGoBackButton
145
+ }), [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
133
146
  const manageFocus = event => {
134
147
  const triggeredByKeyboard = event.nativeEvent.detail === 0;
135
148
  if (triggeredByKeyboard) {
@@ -3,11 +3,12 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  * @jsxRuntime classic
4
4
  * @jsx jsx
5
5
  */
6
- import React, { Fragment, useCallback, useMemo, useState } from 'react';
6
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
7
 
8
8
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
9
9
  import { jsx } from '@emotion/react';
10
10
  import ArrowRightIcon from '@atlaskit/icon/core/migration/arrow-right--arrow-right-circle';
11
+ import { fg } from '@atlaskit/platform-feature-flags';
11
12
  import { Box, xcss } from '@atlaskit/primitives';
12
13
  import { N10 } from '@atlaskit/theme/colors';
13
14
  import { overrideStyleFunction } from '../../common/styles';
@@ -47,13 +48,43 @@ const NestingItem = props => {
47
48
  backButton: contextualBackButton,
48
49
  stack,
49
50
  childIds,
50
- forceShowTopScrollIndicator
51
+ forceShowTopScrollIndicator,
52
+ activeParentId,
53
+ goBackButtonRef,
54
+ isDefaultFocusControl,
55
+ focusGoBackButton
51
56
  } = useNestedContext();
52
57
  const mergedStyles = overrideStyleFunction(nestingItemStyle, cssFn);
53
58
  const [isInteracted, setIsInteracted] = useState(false);
59
+ const parentItemRef = useRef(null);
60
+
61
+ // To avoid error we need to make sure that the component is wrapped in ForwardRef
62
+ const isForwardRefCheck = component => {
63
+ var _component$prototype;
64
+ if (component !== null && component !== void 0 && (_component$prototype = component.prototype) !== null && _component$prototype !== void 0 && _component$prototype.isReactComponent) {
65
+ return false;
66
+ }
67
+ return (component === null || component === void 0 ? void 0 : component.$$typeof) === Symbol.for('react.forward_ref');
68
+ };
69
+ const shouldFocus = isDefaultFocusControl && fg('platform-side-navigation-keyboard-focus');
70
+ const backButtonRef = shouldFocus ? goBackButtonRef : null;
71
+ const activeParentRef = shouldFocus ? parentItemRef : null;
72
+ useEffect(() => {
73
+ if (shouldFocus) {
74
+ if (activeParentId === id) {
75
+ var _parentItemRef$curren;
76
+ parentItemRef === null || parentItemRef === void 0 ? void 0 : (_parentItemRef$curren = parentItemRef.current) === null || _parentItemRef$curren === void 0 ? void 0 : _parentItemRef$curren.focus();
77
+ }
78
+ if (focusGoBackButton) {
79
+ var _goBackButtonRef$curr;
80
+ goBackButtonRef === null || goBackButtonRef === void 0 ? void 0 : (_goBackButtonRef$curr = goBackButtonRef.current) === null || _goBackButtonRef$curr === void 0 ? void 0 : _goBackButtonRef$curr.focus();
81
+ }
82
+ }
83
+ }, [activeParentId, id, goBackButtonRef, focusGoBackButton, isDefaultFocusControl, shouldFocus]);
54
84
  const backButton = props.overrides && props.overrides.GoBackItem && props.overrides.GoBackItem.render && props.overrides.GoBackItem.render({
55
85
  onClick: onUnNest,
56
- testId: testId && `${testId}--go-back-item`
86
+ testId: testId && `${testId}--go-back-item`,
87
+ ref: backButtonRef
57
88
  }) || contextualBackButton;
58
89
  const context = useMemo(() => ({
59
90
  stack,
@@ -63,8 +94,12 @@ const NestingItem = props => {
63
94
  backButton,
64
95
  parentId: id,
65
96
  childIds,
66
- forceShowTopScrollIndicator
67
- }), [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator]);
97
+ forceShowTopScrollIndicator,
98
+ activeParentId,
99
+ goBackButtonRef,
100
+ isDefaultFocusControl,
101
+ focusGoBackButton
102
+ }), [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
68
103
  useChildIdsEffect(childIds, id);
69
104
  const isNormalClick = e => !(e.button || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
70
105
 
@@ -124,11 +159,15 @@ const NestingItem = props => {
124
159
  cssFn: mergedStyles
125
160
  };
126
161
  if (component) {
127
- return jsx(CustomItem, _extends({}, componentProps, {
162
+ return jsx(CustomItem, _extends({
163
+ ref: isForwardRefCheck(component) ? parentItemRef : null
164
+ }, componentProps, {
128
165
  //@ts-expect-error TODO Fix legit TypeScript 3.9.6 improved inference error
129
166
  component: component
130
167
  }));
131
168
  }
132
- return jsx(ButtonItem, componentProps);
169
+ return jsx(ButtonItem, _extends({
170
+ ref: activeParentRef
171
+ }, componentProps));
133
172
  };
134
173
  export default NestingItem;
@@ -4,11 +4,12 @@ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
4
  * @jsxRuntime classic
5
5
  * @jsx jsx
6
6
  */
7
- import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
7
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
8
 
9
9
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
10
10
  import { css, jsx } from '@emotion/react';
11
11
  import { ExitingPersistence } from '@atlaskit/motion';
12
+ import { fg } from '@atlaskit/platform-feature-flags';
12
13
  import { GoBackItem as GoBackButton } from '../Item';
13
14
  import { default as NestingItem } from '../NestingItem';
14
15
  import { useChildIds } from '../utils/hooks';
@@ -47,7 +48,10 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
47
48
  onChange = props.onChange,
48
49
  onUnknownNest = props.onUnknownNest,
49
50
  stack = props.stack,
50
- showTopScrollIndicator = props.showTopScrollIndicator;
51
+ showTopScrollIndicator = props.showTopScrollIndicator,
52
+ _props$isDefaultFocus = props.isDefaultFocusControl,
53
+ isDefaultFocusControl = _props$isDefaultFocus === void 0 ? true : _props$isDefaultFocus;
54
+ var goBackButtonRef = useRef(null);
51
55
  var _useState = useState(stack || initialStack || []),
52
56
  _useState2 = _slicedToArray(_useState, 2),
53
57
  committedStack = _useState2[0],
@@ -59,6 +63,15 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
59
63
  transition = _useState4[0],
60
64
  setTransition = _useState4[1];
61
65
  var backTestId = testId && "".concat(testId, "--go-back-item");
66
+ var _useState5 = useState(''),
67
+ _useState6 = _slicedToArray(_useState5, 2),
68
+ activeParentId = _useState6[0],
69
+ setActiveParentId = _useState6[1];
70
+ var _useState7 = useState(false),
71
+ _useState8 = _slicedToArray(_useState7, 2),
72
+ focusGoBackButton = _useState8[0],
73
+ setFocusGoBackButton = _useState8[1];
74
+ var shouldFocus = isDefaultFocusControl && fg('platform-side-navigation-keyboard-focus');
62
75
  var renderGoBackItem = overrides && overrides.GoBackItem && overrides.GoBackItem.render ? overrides.GoBackItem.render : function (props) {
63
76
  return jsx(GoBackButton, props, "Go back");
64
77
  };
@@ -66,11 +79,11 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
66
79
  childIdsRef = _useChildIds.childIdsRef;
67
80
  var onNestHandler = useCallback(function (layerId) {
68
81
  onChange && onChange(committedStack.concat(layerId));
82
+ setFocusGoBackButton(true);
69
83
  if (controlledStack) {
70
84
  // We are in controlled mode - ignore the steps.
71
85
  return;
72
86
  }
73
-
74
87
  // We need to split the state update into to parts.
75
88
  // First: Updating the direction of the motions.
76
89
  // Second: Actually updating the stack (which will cause elements to enter & leave).
@@ -84,6 +97,8 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
84
97
  }, [controlledStack, onChange, committedStack]);
85
98
  var onUnNestHandler = useCallback(function () {
86
99
  onChange && onChange(committedStack.slice(0, committedStack.length - 1));
100
+ setActiveParentId(currentStackId);
101
+ setFocusGoBackButton(false);
87
102
  if (controlledStack) {
88
103
  // We are in controlled mode - ignore the steps.
89
104
  return;
@@ -99,7 +114,7 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
99
114
  return newStack;
100
115
  });
101
116
  });
102
- }, [controlledStack, onChange, committedStack]);
117
+ }, [controlledStack, onChange, committedStack, setActiveParentId, currentStackId]);
103
118
  useEffect(function () {
104
119
  if (!controlledStack) {
105
120
  // We aren't in controlled mode - bail out.
@@ -124,7 +139,8 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
124
139
  }, [committedStack, controlledStack]);
125
140
  var backButton = renderGoBackItem({
126
141
  onClick: onUnNestHandler,
127
- testId: backTestId
142
+ testId: backTestId,
143
+ ref: shouldFocus ? goBackButtonRef : null
128
144
  });
129
145
  var context = useMemo(function () {
130
146
  return {
@@ -135,9 +151,13 @@ var NestableNavigationContent = function NestableNavigationContent(props) {
135
151
  onUnNest: onUnNestHandler,
136
152
  parentId: ROOT_ID,
137
153
  childIds: childIdsRef,
138
- forceShowTopScrollIndicator: showTopScrollIndicator
154
+ forceShowTopScrollIndicator: showTopScrollIndicator,
155
+ activeParentId: activeParentId,
156
+ goBackButtonRef: goBackButtonRef,
157
+ isDefaultFocusControl: isDefaultFocusControl,
158
+ focusGoBackButton: focusGoBackButton
139
159
  };
140
- }, [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator]);
160
+ }, [currentStackId, backButton, committedStack, onNestHandler, onUnNestHandler, childIdsRef, showTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
141
161
  var manageFocus = function manageFocus(event) {
142
162
  var triggeredByKeyboard = event.nativeEvent.detail === 0;
143
163
  if (triggeredByKeyboard) {
@@ -10,11 +10,12 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
10
10
  * @jsxRuntime classic
11
11
  * @jsx jsx
12
12
  */
13
- import React, { Fragment, useCallback, useMemo, useState } from 'react';
13
+ import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
14
14
 
15
15
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
16
16
  import { jsx } from '@emotion/react';
17
17
  import ArrowRightIcon from '@atlaskit/icon/core/migration/arrow-right--arrow-right-circle';
18
+ import { fg } from '@atlaskit/platform-feature-flags';
18
19
  import { Box, xcss } from '@atlaskit/primitives';
19
20
  import { N10 } from '@atlaskit/theme/colors';
20
21
  import { overrideStyleFunction } from '../../common/styles';
@@ -52,15 +53,45 @@ var NestingItem = function NestingItem(props) {
52
53
  contextualBackButton = _useNestedContext.backButton,
53
54
  stack = _useNestedContext.stack,
54
55
  childIds = _useNestedContext.childIds,
55
- forceShowTopScrollIndicator = _useNestedContext.forceShowTopScrollIndicator;
56
+ forceShowTopScrollIndicator = _useNestedContext.forceShowTopScrollIndicator,
57
+ activeParentId = _useNestedContext.activeParentId,
58
+ goBackButtonRef = _useNestedContext.goBackButtonRef,
59
+ isDefaultFocusControl = _useNestedContext.isDefaultFocusControl,
60
+ focusGoBackButton = _useNestedContext.focusGoBackButton;
56
61
  var mergedStyles = overrideStyleFunction(nestingItemStyle, cssFn);
57
62
  var _useState = useState(false),
58
63
  _useState2 = _slicedToArray(_useState, 2),
59
64
  isInteracted = _useState2[0],
60
65
  setIsInteracted = _useState2[1];
66
+ var parentItemRef = useRef(null);
67
+
68
+ // To avoid error we need to make sure that the component is wrapped in ForwardRef
69
+ var isForwardRefCheck = function isForwardRefCheck(component) {
70
+ var _component$prototype;
71
+ if (component !== null && component !== void 0 && (_component$prototype = component.prototype) !== null && _component$prototype !== void 0 && _component$prototype.isReactComponent) {
72
+ return false;
73
+ }
74
+ return (component === null || component === void 0 ? void 0 : component.$$typeof) === Symbol.for('react.forward_ref');
75
+ };
76
+ var shouldFocus = isDefaultFocusControl && fg('platform-side-navigation-keyboard-focus');
77
+ var backButtonRef = shouldFocus ? goBackButtonRef : null;
78
+ var activeParentRef = shouldFocus ? parentItemRef : null;
79
+ useEffect(function () {
80
+ if (shouldFocus) {
81
+ if (activeParentId === id) {
82
+ var _parentItemRef$curren;
83
+ parentItemRef === null || parentItemRef === void 0 || (_parentItemRef$curren = parentItemRef.current) === null || _parentItemRef$curren === void 0 || _parentItemRef$curren.focus();
84
+ }
85
+ if (focusGoBackButton) {
86
+ var _goBackButtonRef$curr;
87
+ goBackButtonRef === null || goBackButtonRef === void 0 || (_goBackButtonRef$curr = goBackButtonRef.current) === null || _goBackButtonRef$curr === void 0 || _goBackButtonRef$curr.focus();
88
+ }
89
+ }
90
+ }, [activeParentId, id, goBackButtonRef, focusGoBackButton, isDefaultFocusControl, shouldFocus]);
61
91
  var backButton = props.overrides && props.overrides.GoBackItem && props.overrides.GoBackItem.render && props.overrides.GoBackItem.render({
62
92
  onClick: onUnNest,
63
- testId: testId && "".concat(testId, "--go-back-item")
93
+ testId: testId && "".concat(testId, "--go-back-item"),
94
+ ref: backButtonRef
64
95
  }) || contextualBackButton;
65
96
  var context = useMemo(function () {
66
97
  return {
@@ -71,9 +102,13 @@ var NestingItem = function NestingItem(props) {
71
102
  backButton: backButton,
72
103
  parentId: id,
73
104
  childIds: childIds,
74
- forceShowTopScrollIndicator: forceShowTopScrollIndicator
105
+ forceShowTopScrollIndicator: forceShowTopScrollIndicator,
106
+ activeParentId: activeParentId,
107
+ goBackButtonRef: goBackButtonRef,
108
+ isDefaultFocusControl: isDefaultFocusControl,
109
+ focusGoBackButton: focusGoBackButton
75
110
  };
76
- }, [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator]);
111
+ }, [stack, currentStackId, onNest, onUnNest, backButton, id, childIds, forceShowTopScrollIndicator, activeParentId, goBackButtonRef, isDefaultFocusControl, focusGoBackButton]);
77
112
  useChildIdsEffect(childIds, id);
78
113
  var isNormalClick = function isNormalClick(e) {
79
114
  return !(e.button || e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
@@ -135,11 +170,15 @@ var NestingItem = function NestingItem(props) {
135
170
  cssFn: mergedStyles
136
171
  });
137
172
  if (component) {
138
- return jsx(CustomItem, _extends({}, componentProps, {
173
+ return jsx(CustomItem, _extends({
174
+ ref: isForwardRefCheck(component) ? parentItemRef : null
175
+ }, componentProps, {
139
176
  //@ts-expect-error TODO Fix legit TypeScript 3.9.6 improved inference error
140
177
  component: component
141
178
  }));
142
179
  }
143
- return jsx(ButtonItem, componentProps);
180
+ return jsx(ButtonItem, _extends({
181
+ ref: activeParentRef
182
+ }, componentProps));
144
183
  };
145
184
  export default NestingItem;
@@ -11,6 +11,10 @@ export interface NestedContextValue {
11
11
  backButton?: React.ReactNode;
12
12
  childIds: MutableRefObject<Set<string>>;
13
13
  forceShowTopScrollIndicator: boolean | undefined;
14
+ activeParentId?: string;
15
+ goBackButtonRef?: React.MutableRefObject<HTMLButtonElement | null>;
16
+ isDefaultFocusControl?: boolean;
17
+ focusGoBackButton?: boolean;
14
18
  }
15
19
  /**
16
20
  * @internal
@@ -1,4 +1,8 @@
1
- /// <reference types="react" />
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import React from 'react';
2
6
  import { jsx } from '@emotion/react';
3
7
  export declare const ROOT_ID = "ATLASKIT_NESTED_ROOT";
4
8
  export interface NestableNavigationContentProps {
@@ -57,14 +61,22 @@ export interface NestableNavigationContentProps {
57
61
  * Use this to override the default back button displayed when navigation is nested.
58
62
  * You'll want to import the [go back item](/packages/navigation/docs/go-back-item) component and use it here.
59
63
  * This will be displayed for all children [nesting items](/packages/navigation/side-navigation/docs/nesting-item) unless they define their own.
64
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
60
65
  */
61
66
  GoBackItem?: {
62
67
  render?: (props: {
63
68
  onClick: () => void;
64
69
  testId?: string;
70
+ ref?: React.Ref<HTMLElement>;
65
71
  }) => React.ReactNode;
66
72
  };
67
73
  };
74
+ /**
75
+ * This property is enabled by default (set to true) and is designed to manage keyboard focus
76
+ * for the "go back" button or the last active parent within the `<NestingItem/>` component.
77
+ * It is applicable only when using our `<NestingItem/>` component.
78
+ */
79
+ isDefaultFocusControl?: boolean;
68
80
  }
69
81
  /**
70
82
  * __Nestable navigation content__
@@ -9,11 +9,13 @@ interface NestingItemOverrides extends Overrides {
9
9
  * Use this to override the back button displayed when navigation is nested.
10
10
  * You'll want to import the [go back item](/packages/navigation/side-navigation/docs/go-back-item) component and use it here.
11
11
  * This will be displayed for all children nesting item components unless they define their own.
12
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
12
13
  */
13
14
  GoBackItem?: {
14
15
  render?: (props: {
15
16
  onClick: () => void;
16
17
  testId?: string;
18
+ ref?: React.Ref<HTMLElement>;
17
19
  }) => React.ReactNode;
18
20
  };
19
21
  }
@@ -34,6 +36,7 @@ export interface NestingItemProps<TCustomComponentProps = CustomItemComponentPro
34
36
  /**
35
37
  * Used to customize the rendered component when shown as an item.
36
38
  * You can use this for example to change it to a SPA link.
39
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
37
40
  */
38
41
  component?: React.ComponentType<TCustomComponentProps>;
39
42
  /**
@@ -11,6 +11,10 @@ export interface NestedContextValue {
11
11
  backButton?: React.ReactNode;
12
12
  childIds: MutableRefObject<Set<string>>;
13
13
  forceShowTopScrollIndicator: boolean | undefined;
14
+ activeParentId?: string;
15
+ goBackButtonRef?: React.MutableRefObject<HTMLButtonElement | null>;
16
+ isDefaultFocusControl?: boolean;
17
+ focusGoBackButton?: boolean;
14
18
  }
15
19
  /**
16
20
  * @internal
@@ -1,4 +1,8 @@
1
- /// <reference types="react" />
1
+ /**
2
+ * @jsxRuntime classic
3
+ * @jsx jsx
4
+ */
5
+ import React from 'react';
2
6
  import { jsx } from '@emotion/react';
3
7
  export declare const ROOT_ID = "ATLASKIT_NESTED_ROOT";
4
8
  export interface NestableNavigationContentProps {
@@ -57,14 +61,22 @@ export interface NestableNavigationContentProps {
57
61
  * Use this to override the default back button displayed when navigation is nested.
58
62
  * You'll want to import the [go back item](/packages/navigation/docs/go-back-item) component and use it here.
59
63
  * This will be displayed for all children [nesting items](/packages/navigation/side-navigation/docs/nesting-item) unless they define their own.
64
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
60
65
  */
61
66
  GoBackItem?: {
62
67
  render?: (props: {
63
68
  onClick: () => void;
64
69
  testId?: string;
70
+ ref?: React.Ref<HTMLElement>;
65
71
  }) => React.ReactNode;
66
72
  };
67
73
  };
74
+ /**
75
+ * This property is enabled by default (set to true) and is designed to manage keyboard focus
76
+ * for the "go back" button or the last active parent within the `<NestingItem/>` component.
77
+ * It is applicable only when using our `<NestingItem/>` component.
78
+ */
79
+ isDefaultFocusControl?: boolean;
68
80
  }
69
81
  /**
70
82
  * __Nestable navigation content__
@@ -9,11 +9,13 @@ interface NestingItemOverrides extends Overrides {
9
9
  * Use this to override the back button displayed when navigation is nested.
10
10
  * You'll want to import the [go back item](/packages/navigation/side-navigation/docs/go-back-item) component and use it here.
11
11
  * This will be displayed for all children nesting item components unless they define their own.
12
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
12
13
  */
13
14
  GoBackItem?: {
14
15
  render?: (props: {
15
16
  onClick: () => void;
16
17
  testId?: string;
18
+ ref?: React.Ref<HTMLElement>;
17
19
  }) => React.ReactNode;
18
20
  };
19
21
  }
@@ -34,6 +36,7 @@ export interface NestingItemProps<TCustomComponentProps = CustomItemComponentPro
34
36
  /**
35
37
  * Used to customize the rendered component when shown as an item.
36
38
  * You can use this for example to change it to a SPA link.
39
+ * Your custom component should be wrapped with forwardRef to support assistive technologies.
37
40
  */
38
41
  component?: React.ComponentType<TCustomComponentProps>;
39
42
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/side-navigation",
3
- "version": "3.5.4",
3
+ "version": "3.6.0",
4
4
  "description": "A highly composable side navigation component that supports nested views.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -27,12 +27,13 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@atlaskit/ds-lib": "^3.1.0",
30
- "@atlaskit/icon": "^22.22.0",
30
+ "@atlaskit/icon": "^22.24.0",
31
31
  "@atlaskit/menu": "^2.13.0",
32
32
  "@atlaskit/motion": "^1.9.0",
33
- "@atlaskit/primitives": "^12.2.0",
33
+ "@atlaskit/platform-feature-flags": "^0.3.0",
34
+ "@atlaskit/primitives": "^13.0.0",
34
35
  "@atlaskit/theme": "^14.0.0",
35
- "@atlaskit/tokens": "^2.0.0",
36
+ "@atlaskit/tokens": "^2.2.0",
36
37
  "@babel/runtime": "^7.0.0",
37
38
  "@emotion/react": "^11.7.1"
38
39
  },
@@ -83,5 +84,10 @@
83
84
  ]
84
85
  }
85
86
  },
87
+ "platform-feature-flags": {
88
+ "platform-side-navigation-keyboard-focus": {
89
+ "type": "boolean"
90
+ }
91
+ },
86
92
  "homepage": "https://atlassian.design/components/side-navigation/"
87
93
  }