@carbon-labs/react-ui-shell 0.41.0 → 0.43.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/es/components/SideNav.d.ts +3 -0
- package/es/components/SideNav.js +39 -10
- package/es/components/SideNavMenu.d.ts +19 -0
- package/es/components/SideNavMenu.js +127 -20
- package/es/node_modules/@carbon/icons-react/es/generated/bucket-0.js +2956 -0
- package/lib/components/SideNav.d.ts +3 -0
- package/lib/components/SideNav.js +39 -10
- package/lib/components/SideNavMenu.d.ts +19 -0
- package/lib/components/SideNavMenu.js +123 -16
- package/lib/node_modules/@carbon/icons-react/es/generated/bucket-0.js +3082 -0
- package/package.json +2 -2
- package/scss/styles/_side-nav.scss +89 -0
|
@@ -21,6 +21,7 @@ export interface SideNavProps extends ComponentProps<'nav'>, TranslateWithId<Tra
|
|
|
21
21
|
defaultExpanded?: boolean;
|
|
22
22
|
isChildOfHeader?: boolean;
|
|
23
23
|
onToggle?: (event: FocusEvent<HTMLElement> | KeyboardEvent<HTMLElement> | boolean, value: boolean) => void;
|
|
24
|
+
hideRailBreakpointDown?: 'sm' | 'md' | 'lg' | 'xlg' | 'max';
|
|
24
25
|
href?: string;
|
|
25
26
|
isFixedNav?: boolean;
|
|
26
27
|
isRail?: boolean;
|
|
@@ -42,6 +43,8 @@ interface SideNavContextData {
|
|
|
42
43
|
navType?: SIDE_NAV_TYPE;
|
|
43
44
|
isTreeview?: boolean;
|
|
44
45
|
setIsTreeview?: (value: boolean) => void;
|
|
46
|
+
currentPrimaryMenu?: string;
|
|
47
|
+
setCurrentPrimaryMenu?: (value: string) => void;
|
|
45
48
|
}
|
|
46
49
|
export declare const SideNavContext: React.Context<SideNavContextData>;
|
|
47
50
|
export declare const SideNav: React.ForwardRefExoticComponent<Omit<SideNavProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
|
@@ -50,6 +50,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
50
50
|
children,
|
|
51
51
|
onToggle,
|
|
52
52
|
className: customClassName,
|
|
53
|
+
hideRailBreakpointDown,
|
|
53
54
|
href,
|
|
54
55
|
isFixedNav = false,
|
|
55
56
|
isRail,
|
|
@@ -76,6 +77,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
76
77
|
const expanded = controlled ? expandedProp : expandedState;
|
|
77
78
|
const sideNavRef = React.useRef(null);
|
|
78
79
|
const navRef = useMergedRefs.useMergedRefs([sideNavRef, ref]);
|
|
80
|
+
const [currentPrimaryMenu, setCurrentPrimaryMenu] = React.useState();
|
|
79
81
|
const sideNavToggleText = expandedState ? t('collapse.sidenav') : t('expand.sidenav');
|
|
80
82
|
const handleToggle = function (event) {
|
|
81
83
|
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : !expanded;
|
|
@@ -97,6 +99,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
97
99
|
[`${prefix}--side-nav`]: true,
|
|
98
100
|
[`${prefix}--side-nav--expanded`]: expanded || expandedViaHoverState,
|
|
99
101
|
[`${prefix}--side-nav--collapsed`]: !expanded && isFixedNav,
|
|
102
|
+
[`${prefix}--side-nav--hide-rail-breakpoint-down-${hideRailBreakpointDown}`]: hideRailBreakpointDown,
|
|
100
103
|
[`${prefix}--side-nav--rail`]: isRail,
|
|
101
104
|
[`${prefix}--side-nav--panel`]: navType === SIDE_NAV_TYPE.PANEL,
|
|
102
105
|
[`${prefix}--side-nav--ux`]: isChildOfHeader,
|
|
@@ -149,11 +152,22 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
149
152
|
resetNodeTabIndices();
|
|
150
153
|
}
|
|
151
154
|
}, [prefix, internalIsTreeview]);
|
|
155
|
+
const smMediaQuery = `(min-width: ${index$1.breakpoints.sm.width})`;
|
|
156
|
+
const isSm = useMatchMedia.useMatchMedia(smMediaQuery);
|
|
152
157
|
React.useEffect(() => {
|
|
153
158
|
if (sideNavRef.current) {
|
|
159
|
+
const backButton = sideNavRef?.current.querySelector(`.${prefix}--side-nav__back-button`);
|
|
154
160
|
const firstElement = sideNavRef?.current?.querySelector('a, button');
|
|
155
|
-
if (
|
|
156
|
-
|
|
161
|
+
if (navType == SIDE_NAV_TYPE.PANEL || expanded) {
|
|
162
|
+
if (isSm && backButton) {
|
|
163
|
+
backButton.tabIndex = 0;
|
|
164
|
+
const firstElementAfterBack = backButton.nextElementSibling?.querySelector('a, button');
|
|
165
|
+
if (firstElementAfterBack) {
|
|
166
|
+
firstElementAfterBack.tabIndex = 0;
|
|
167
|
+
}
|
|
168
|
+
} else if (firstElement) {
|
|
169
|
+
firstElement.tabIndex = 0;
|
|
170
|
+
}
|
|
157
171
|
}
|
|
158
172
|
}
|
|
159
173
|
}, [expanded]);
|
|
@@ -221,15 +235,17 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
221
235
|
let nextFocusNode = null;
|
|
222
236
|
if (match.match(event, keys.ArrowUp)) {
|
|
223
237
|
const parentNode = parentSideNavMenu(treeWalker.currentNode);
|
|
224
|
-
let previousSideNavMenu =
|
|
225
|
-
|
|
238
|
+
let previousSideNavMenu = treeWalker.currentNode?.previousSibling;
|
|
226
239
|
// skip the divider
|
|
227
240
|
if (previousSideNavMenu?.classList.contains(`${prefix}--side-nav__divider`)) {
|
|
228
241
|
previousSideNavMenu = previousSideNavMenu?.previousElementSibling;
|
|
229
242
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
243
|
+
if (previousSideNavMenu?.classList.contains(`${prefix}--side-nav__item--primary`)) {
|
|
244
|
+
nextFocusNode = previousSideNavMenu;
|
|
245
|
+
} else if (treeWalker.currentNode.classList.contains(`${prefix}--side-nav__item--primary`)) {
|
|
246
|
+
nextFocusNode = treeWalker.currentNode.previousSibling;
|
|
247
|
+
} // when previous sibling is open, go to its last item
|
|
248
|
+
else if (previousSideNavMenu?.getAttribute('aria-expanded') == 'true') {
|
|
233
249
|
const allItems = previousSideNavMenu.querySelectorAll(`.${prefix}--side-nav__item`);
|
|
234
250
|
const lastMenu = allItems[allItems.length - 1];
|
|
235
251
|
if (lastMenu && lastMenu.getAttribute('aria-expanded') == 'false') {
|
|
@@ -241,7 +257,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
241
257
|
nextFocusNode = treeWalker.previousSibling();
|
|
242
258
|
|
|
243
259
|
// first item in the menu, go back up to SideNavMenu button
|
|
244
|
-
if (nextFocusNode == null) {
|
|
260
|
+
if (nextFocusNode == null && !parentNode.classList.contains(`${prefix}--side-nav__item--primary`)) {
|
|
245
261
|
nextFocusNode = parentNode;
|
|
246
262
|
}
|
|
247
263
|
}
|
|
@@ -253,6 +269,11 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
253
269
|
const parent = parentSideNavMenu(treeWalker.currentNode);
|
|
254
270
|
nextFocusNode = parent?.nextElementSibling;
|
|
255
271
|
}
|
|
272
|
+
} else if (treeWalker.currentNode.classList.contains(`${prefix}--side-nav__item--primary`)) {
|
|
273
|
+
nextFocusNode = treeWalker.currentNode.nextSibling;
|
|
274
|
+
if (nextFocusNode?.classList.contains(`${prefix}--side-nav__divider`)) {
|
|
275
|
+
nextFocusNode = nextFocusNode.nextSibling;
|
|
276
|
+
}
|
|
256
277
|
} else {
|
|
257
278
|
nextFocusNode = treeWalker.nextNode();
|
|
258
279
|
}
|
|
@@ -327,7 +348,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
327
348
|
function resetNodeTabIndices() {
|
|
328
349
|
const items = sideNavRef?.current?.querySelectorAll('[tabIndex="0"]') ?? [];
|
|
329
350
|
items.forEach(item => {
|
|
330
|
-
if (item.classList.contains(`${prefix}--side-nav__toggle`)) {
|
|
351
|
+
if (item.classList.contains(`${prefix}--side-nav__toggle`) || item.classList.contains(`${prefix}--side-nav__back-button`)) {
|
|
331
352
|
return;
|
|
332
353
|
}
|
|
333
354
|
item.tabIndex = -1;
|
|
@@ -358,7 +379,9 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
358
379
|
isRail,
|
|
359
380
|
navType,
|
|
360
381
|
isTreeview: internalIsTreeview,
|
|
361
|
-
setIsTreeview
|
|
382
|
+
setIsTreeview,
|
|
383
|
+
currentPrimaryMenu,
|
|
384
|
+
setCurrentPrimaryMenu
|
|
362
385
|
}
|
|
363
386
|
}, isFixedNav || hideOverlay ? null :
|
|
364
387
|
/*#__PURE__*/
|
|
@@ -412,6 +435,12 @@ SideNav.propTypes = {
|
|
|
412
435
|
* If `true`, the overlay will be hidden. Defaults to `false`.
|
|
413
436
|
*/
|
|
414
437
|
hideOverlay: PropTypes.bool,
|
|
438
|
+
/**
|
|
439
|
+
* Specify the breakpoint at which the SideNav will be hidden.
|
|
440
|
+
* Can be one of `sm`, `md`, `lg`, `xlg`, or `max`.
|
|
441
|
+
* Only applies when `isRail` is `true`.
|
|
442
|
+
*/
|
|
443
|
+
hideRailBreakpointDown: PropTypes.oneOf(['sm', 'md', 'lg', 'xlg', 'max']),
|
|
415
444
|
/**
|
|
416
445
|
* Provide the `href` to the id of the element on your package that is the
|
|
417
446
|
* main content.
|
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
export interface SideNavMenuProps {
|
|
9
|
+
/**
|
|
10
|
+
* Title for back button in sm screen
|
|
11
|
+
*/
|
|
12
|
+
backButtonTitle?: string;
|
|
13
|
+
/**
|
|
14
|
+
* A custom icon to render on the back button in sm screen
|
|
15
|
+
* default is ArrowLeft
|
|
16
|
+
*/
|
|
17
|
+
backButtonRenderIcon?: React.ComponentType;
|
|
9
18
|
/**
|
|
10
19
|
* An optional CSS class to apply to the component.
|
|
11
20
|
*/
|
|
@@ -23,6 +32,10 @@ export interface SideNavMenuProps {
|
|
|
23
32
|
* SideNavMenu depth to determine spacing
|
|
24
33
|
*/
|
|
25
34
|
depth?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Provide a unique id
|
|
37
|
+
*/
|
|
38
|
+
id?: string;
|
|
26
39
|
/**
|
|
27
40
|
* Indicates whether the SideNavMenu is active.
|
|
28
41
|
*/
|
|
@@ -44,6 +57,12 @@ export interface SideNavMenuProps {
|
|
|
44
57
|
* Indicates if the side navigation container is expanded or collapsed.
|
|
45
58
|
*/
|
|
46
59
|
isSideNavExpanded?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Specifies if this is the primary SideNav.
|
|
62
|
+
* If true, child components will open to the right,
|
|
63
|
+
* creating the double-wide navigation layout
|
|
64
|
+
*/
|
|
65
|
+
primary?: boolean;
|
|
47
66
|
/**
|
|
48
67
|
* The boolean to show the flyout menu has been selected.
|
|
49
68
|
*/
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
'use strict';
|
|
9
9
|
|
|
10
|
+
var index$1 = require('../node_modules/@carbon/layout/es/index.js');
|
|
10
11
|
var index = require('../_virtual/index.js');
|
|
11
12
|
var PropTypes = require('prop-types');
|
|
12
13
|
var React = require('react');
|
|
13
14
|
var _utils = require('./_utils.js');
|
|
15
|
+
var useId = require('../internal/useId.js');
|
|
14
16
|
var react = require('@carbon/react');
|
|
15
17
|
var keys = require('../internal/keyboard/keys.js');
|
|
16
18
|
var match = require('../internal/keyboard/match.js');
|
|
@@ -19,21 +21,31 @@ var SideNav = require('./SideNav.js');
|
|
|
19
21
|
var useMergedRefs = require('../internal/useMergedRefs.js');
|
|
20
22
|
var SharkFinIcon = require('./SharkFinIcon.js');
|
|
21
23
|
var SideNavFlyoutMenu = require('./SideNavFlyoutMenu.js');
|
|
24
|
+
var SideNavItems = require('./SideNavItems.js');
|
|
25
|
+
var useMatchMedia = require('../internal/useMatchMedia.js');
|
|
26
|
+
var bucket0 = require('../node_modules/@carbon/icons-react/es/generated/bucket-0.js');
|
|
22
27
|
var bucket3 = require('../node_modules/@carbon/icons-react/es/generated/bucket-3.js');
|
|
23
28
|
|
|
24
|
-
var _SharkFinIcon, _ChevronDown;
|
|
29
|
+
var _ArrowLeft, _SharkFinIcon, _ChevronRight, _ChevronDown;
|
|
30
|
+
const smMediaQuery = `(max-width: ${index$1.breakpoints.md.width})`;
|
|
25
31
|
const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref) {
|
|
26
32
|
let {
|
|
33
|
+
backButtonRenderIcon = () => _ArrowLeft || (_ArrowLeft = /*#__PURE__*/React.createElement(bucket0.ArrowLeft, {
|
|
34
|
+
size: 16
|
|
35
|
+
})),
|
|
36
|
+
backButtonTitle = 'My products',
|
|
27
37
|
className: customClassName,
|
|
28
38
|
children,
|
|
29
39
|
defaultExpanded = false,
|
|
30
40
|
depth: propDepth,
|
|
41
|
+
id,
|
|
31
42
|
isActive = false,
|
|
32
43
|
large = false,
|
|
33
44
|
renderIcon: IconElement,
|
|
34
45
|
isSideNavExpanded,
|
|
35
46
|
title,
|
|
36
|
-
onMenuToggle
|
|
47
|
+
onMenuToggle,
|
|
48
|
+
primary
|
|
37
49
|
} = _ref;
|
|
38
50
|
const depth = propDepth;
|
|
39
51
|
const {
|
|
@@ -48,10 +60,19 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
48
60
|
const [isExpanded, setIsExpanded] = React.useState(defaultExpanded);
|
|
49
61
|
const [active, setActive] = React.useState(isActive);
|
|
50
62
|
const firstLink = React.useRef(null);
|
|
63
|
+
const backButtonRef = React.useRef(null);
|
|
64
|
+
const uid = useId.useId('side-nav-menu');
|
|
65
|
+
const uniqueId = id || uid;
|
|
51
66
|
const [prevExpanded, setPrevExpanded] = React.useState(defaultExpanded);
|
|
67
|
+
const [isSecondaryOpen, setSecondaryOpen] = React.useState(defaultExpanded);
|
|
68
|
+
const {
|
|
69
|
+
currentPrimaryMenu,
|
|
70
|
+
setCurrentPrimaryMenu
|
|
71
|
+
} = React.useContext(SideNav.SideNavContext);
|
|
52
72
|
const className = index.default({
|
|
53
73
|
[`${prefix}--side-nav__item`]: true,
|
|
54
|
-
[`${prefix}--side-nav__item--
|
|
74
|
+
[`${prefix}--side-nav__item--primary`]: primary,
|
|
75
|
+
[`${prefix}--side-nav__item--active`]: !primary && (active || hasActiveDescendant(children) && !isExpanded),
|
|
55
76
|
[`${prefix}--side-nav__item--icon`]: IconElement,
|
|
56
77
|
[`${prefix}--side-nav__item--large`]: large,
|
|
57
78
|
[customClassName]: !!customClassName
|
|
@@ -60,6 +81,10 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
60
81
|
[`${prefix}--side-nav__submenu`]: true,
|
|
61
82
|
[`${prefix}--side-nav__submenu--active`]: active || hasActiveDescendant(children) && isExpanded
|
|
62
83
|
});
|
|
84
|
+
const primaryClassNames = index.default({
|
|
85
|
+
[`${prefix}--side-nav__menu-secondary-wrapper`]: true,
|
|
86
|
+
[`${prefix}--side-nav__menu-secondary-wrapper-expanded`]: isSideNavExpanded && isSecondaryOpen && currentPrimaryMenu === uniqueId
|
|
87
|
+
});
|
|
63
88
|
const buttonRef = React.useRef(null);
|
|
64
89
|
const listRef = React.useRef(null);
|
|
65
90
|
const menuRef = useMergedRefs.useMergedRefs([buttonRef, ref]);
|
|
@@ -170,10 +195,11 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
170
195
|
if (onMenuToggle) {
|
|
171
196
|
onMenuToggle();
|
|
172
197
|
}
|
|
173
|
-
|
|
174
|
-
|
|
198
|
+
if (!primary && isExpanded) {
|
|
199
|
+
setIsExpanded(false);
|
|
200
|
+
}
|
|
175
201
|
// go to previous level's side nav menu button
|
|
176
|
-
} else {
|
|
202
|
+
} else if (!isSm) {
|
|
177
203
|
// since we're in a menu, it finds its own <li>, we go up one more
|
|
178
204
|
const previousMenu = parentSideNavMenu(parent);
|
|
179
205
|
const button = previousMenu.querySelector('button');
|
|
@@ -183,33 +209,74 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
183
209
|
|
|
184
210
|
// go to side nav menu button
|
|
185
211
|
} else if (parent) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
212
|
+
if (parent.hasAttribute('aria-expanded')) {
|
|
213
|
+
const button = parent.querySelector('button');
|
|
214
|
+
if (button) {
|
|
215
|
+
button.tabIndex = 0;
|
|
216
|
+
button.focus();
|
|
217
|
+
}
|
|
218
|
+
} else if (!isSm) {
|
|
219
|
+
const previousMenu = parentSideNavMenu(parent);
|
|
220
|
+
const button = previousMenu.querySelector('button');
|
|
221
|
+
button.tabIndex = 0;
|
|
222
|
+
button?.focus();
|
|
223
|
+
}
|
|
189
224
|
}
|
|
190
225
|
}
|
|
191
226
|
if (match.match(event, keys.ArrowRight)) {
|
|
227
|
+
setIsExpanded(true);
|
|
228
|
+
if (primary && node.hasAttribute('aria-expanded')) {
|
|
229
|
+
event.preventDefault();
|
|
230
|
+
}
|
|
192
231
|
event.stopPropagation();
|
|
193
232
|
|
|
194
233
|
// expand menu when sidenav is expanded
|
|
195
234
|
if (isMenu && sideNavExpanded) {
|
|
196
|
-
setIsExpanded(true);
|
|
197
235
|
if (onMenuToggle) {
|
|
198
236
|
onMenuToggle();
|
|
199
237
|
}
|
|
200
238
|
|
|
201
239
|
// if already expanded, focus on first element
|
|
202
|
-
if (isExpanded == 'true') {
|
|
203
|
-
|
|
240
|
+
if (isExpanded == 'true' || isSm) {
|
|
241
|
+
const nextNode = node.nextElementSibling?.querySelector('a, button');
|
|
204
242
|
if (nextNode) {
|
|
205
243
|
nextNode.tabIndex = 0;
|
|
206
244
|
nextNode.focus();
|
|
207
245
|
}
|
|
246
|
+
if (isSm) {
|
|
247
|
+
const nextNodeAfterBackButton = nextNode.nextElementSibling?.querySelector('a, button');
|
|
248
|
+
if (nextNodeAfterBackButton) {
|
|
249
|
+
nextNodeAfterBackButton.tabIndex = 0;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
208
252
|
}
|
|
209
253
|
}
|
|
210
254
|
}
|
|
211
255
|
}
|
|
212
256
|
}
|
|
257
|
+
function handleOnBackButtonClick(event) {
|
|
258
|
+
const node = event.target;
|
|
259
|
+
const parent = parentSideNavMenu(node);
|
|
260
|
+
const button = parent.querySelector('button');
|
|
261
|
+
if (button) {
|
|
262
|
+
button.tabIndex = 0;
|
|
263
|
+
button.focus();
|
|
264
|
+
}
|
|
265
|
+
setIsExpanded(false);
|
|
266
|
+
}
|
|
267
|
+
React.useEffect(() => {
|
|
268
|
+
if (isExpanded && primary && setCurrentPrimaryMenu) {
|
|
269
|
+
setCurrentPrimaryMenu(uniqueId);
|
|
270
|
+
}
|
|
271
|
+
setSecondaryOpen(isExpanded);
|
|
272
|
+
}, [isExpanded]);
|
|
273
|
+
React.useEffect(() => {
|
|
274
|
+
if (currentPrimaryMenu !== uniqueId) {
|
|
275
|
+
setIsExpanded(false);
|
|
276
|
+
} else {
|
|
277
|
+
setIsExpanded(true);
|
|
278
|
+
}
|
|
279
|
+
}, [currentPrimaryMenu]);
|
|
213
280
|
|
|
214
281
|
// save expanded state before SideNav collapse
|
|
215
282
|
const [lastExpandedState, setLastExpandedState] = React.useState(isExpanded);
|
|
@@ -224,6 +291,14 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
224
291
|
}
|
|
225
292
|
}, [sideNavExpanded]);
|
|
226
293
|
const [openPopover, setOpenPopover] = React.useState(false);
|
|
294
|
+
const isSm = useMatchMedia.useMatchMedia(smMediaQuery);
|
|
295
|
+
|
|
296
|
+
// keeps the secondary open when moving from small to large breakpoints
|
|
297
|
+
React.useEffect(() => {
|
|
298
|
+
if (!isSm && uniqueId === currentPrimaryMenu) {
|
|
299
|
+
setIsExpanded(true);
|
|
300
|
+
}
|
|
301
|
+
}, [isSm]);
|
|
227
302
|
const content =
|
|
228
303
|
/*#__PURE__*/
|
|
229
304
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
@@ -232,7 +307,8 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
232
307
|
"aria-expanded": isExpanded,
|
|
233
308
|
className: className,
|
|
234
309
|
ref: listRef,
|
|
235
|
-
onKeyDown: handleKeyDown
|
|
310
|
+
onKeyDown: handleKeyDown,
|
|
311
|
+
id: uniqueId
|
|
236
312
|
}, /*#__PURE__*/React.createElement("button", {
|
|
237
313
|
"aria-expanded": isExpanded,
|
|
238
314
|
className: buttonClassName,
|
|
@@ -245,10 +321,13 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
245
321
|
if (navType == SideNav.SIDE_NAV_TYPE.PANEL && !isExpanded && firstLink.current && !sideNavExpanded) {
|
|
246
322
|
setOpenPopover(!openPopover);
|
|
247
323
|
// window.location.href = firstLink.current;
|
|
248
|
-
} else {
|
|
324
|
+
} else if (isSm || !primary || currentPrimaryMenu !== uniqueId) {
|
|
249
325
|
setIsExpanded(!isExpanded);
|
|
250
326
|
setLastExpandedState(!isExpanded);
|
|
251
327
|
}
|
|
328
|
+
if (isSm && backButtonRef.current) {
|
|
329
|
+
backButtonRef.current.focus();
|
|
330
|
+
}
|
|
252
331
|
},
|
|
253
332
|
ref: menuRef,
|
|
254
333
|
type: "button",
|
|
@@ -262,9 +341,24 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
262
341
|
}, title), /*#__PURE__*/React.createElement(react.SideNavIcon, {
|
|
263
342
|
className: `${prefix}--side-nav__submenu-chevron`,
|
|
264
343
|
small: true
|
|
265
|
-
},
|
|
344
|
+
}, primary ? _ChevronRight || (_ChevronRight = /*#__PURE__*/React.createElement(bucket3.ChevronRight, {
|
|
266
345
|
size: 20
|
|
267
|
-
}))
|
|
346
|
+
})) : _ChevronDown || (_ChevronDown = /*#__PURE__*/React.createElement(bucket3.ChevronDown, {
|
|
347
|
+
size: 20
|
|
348
|
+
})))), primary && /*#__PURE__*/React.createElement("div", {
|
|
349
|
+
className: primaryClassNames
|
|
350
|
+
}, /*#__PURE__*/React.createElement(SideNavItems.SideNavItems, {
|
|
351
|
+
accessibilityLabel: {
|
|
352
|
+
'aria-label': `${title} submenu`
|
|
353
|
+
}
|
|
354
|
+
}, isSm && /*#__PURE__*/React.createElement(react.Button, {
|
|
355
|
+
ref: backButtonRef,
|
|
356
|
+
kind: "ghost",
|
|
357
|
+
size: "md",
|
|
358
|
+
onClick: handleOnBackButtonClick,
|
|
359
|
+
className: `${prefix}--side-nav__back-button`,
|
|
360
|
+
renderIcon: backButtonRenderIcon
|
|
361
|
+
}, backButtonTitle), childrenToRender)), /*#__PURE__*/React.createElement("ul", {
|
|
268
362
|
className: `${prefix}--side-nav__menu`,
|
|
269
363
|
role: "group"
|
|
270
364
|
}, childrenToRender));
|
|
@@ -277,6 +371,15 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
|
|
|
277
371
|
});
|
|
278
372
|
SideNavMenu.displayName = 'SideNavMenu';
|
|
279
373
|
SideNavMenu.propTypes = {
|
|
374
|
+
/**
|
|
375
|
+
* A custom icon to render on the back button in sm screen
|
|
376
|
+
*/
|
|
377
|
+
// @ts-expect-error - PropTypes are unable to cover this case.
|
|
378
|
+
backButtonRenderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
|
379
|
+
/**
|
|
380
|
+
* Title for back button in sm screen
|
|
381
|
+
*/
|
|
382
|
+
backButtonTitle: PropTypes.string,
|
|
280
383
|
/**
|
|
281
384
|
* Provide <SideNavMenuItem>'s inside of the `SideNavMenu`
|
|
282
385
|
*/
|
|
@@ -295,6 +398,10 @@ SideNavMenu.propTypes = {
|
|
|
295
398
|
* SideNavMenu depth to determine spacing
|
|
296
399
|
*/
|
|
297
400
|
depth: PropTypes.number,
|
|
401
|
+
/**
|
|
402
|
+
* Provide a unique id
|
|
403
|
+
*/
|
|
404
|
+
id: PropTypes.string,
|
|
298
405
|
/**
|
|
299
406
|
* Specify whether the `SideNavMenu` is "active". `SideNavMenu` should be
|
|
300
407
|
* considered active if one of its menu items are a link for the current
|