@carbon-labs/react-ui-shell 0.82.0 → 0.84.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/HeaderOverflowPanel.d.ts +24 -0
- package/es/components/HeaderOverflowPanel.js +56 -0
- package/es/components/Profile.js +1 -1
- package/es/components/SideNav.d.ts +2 -0
- package/es/components/SideNav.js +26 -33
- package/es/components/SideNavMenu.js +17 -7
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/lib/components/HeaderOverflowPanel.d.ts +24 -0
- package/lib/components/HeaderOverflowPanel.js +58 -0
- package/lib/components/Profile.js +1 -1
- package/lib/components/SideNav.d.ts +2 -0
- package/lib/components/SideNav.js +26 -33
- package/lib/components/SideNavMenu.js +17 -7
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/package.json +2 -2
- package/scss/styles/_header-overflow-panel.scss +105 -0
- package/scss/styles/_profile.scss +11 -3
- package/scss/styles/_side-nav.scss +1 -1
- package/scss/ui-shell.scss +1 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
*
|
|
4
|
+
* Copyright IBM Corp. 2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
export interface HeaderOverflowPanelProps {
|
|
11
|
+
/**
|
|
12
|
+
* Provide an optional class to be applied to the containing node
|
|
13
|
+
*/
|
|
14
|
+
className?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Custom children to be rendered within the popover of the Overflow panel menu
|
|
17
|
+
*/
|
|
18
|
+
children?: React.ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Provide the Overflow panel's label
|
|
21
|
+
*/
|
|
22
|
+
label?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const HeaderOverflowPanel: React.ForwardRefExoticComponent<HeaderOverflowPanelProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { extends as _extends } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
+
import cx from 'classnames';
|
|
10
|
+
import PropTypes from 'prop-types';
|
|
11
|
+
import React__default from 'react';
|
|
12
|
+
import { usePrefix } from '../internal/usePrefix.js';
|
|
13
|
+
import { HeaderPopover, HeaderPopoverButton, HeaderPopoverContent } from './HeaderPopover.js';
|
|
14
|
+
import { OverflowMenuVertical } from '@carbon/icons-react';
|
|
15
|
+
import { useMatchMedia } from '../internal/useMatchMedia.js';
|
|
16
|
+
import { breakpoints } from '../node_modules/@carbon/layout/es/index.js';
|
|
17
|
+
|
|
18
|
+
var _OverflowMenuVertical;
|
|
19
|
+
const mdMediaQuery = `(max-width: ${breakpoints.md.width})`;
|
|
20
|
+
const HeaderOverflowPanel = /*#__PURE__*/React__default.forwardRef(function HeaderOverflowPanel({
|
|
21
|
+
className: customClassName,
|
|
22
|
+
children,
|
|
23
|
+
label,
|
|
24
|
+
...rest
|
|
25
|
+
}, ref) {
|
|
26
|
+
const prefix = usePrefix();
|
|
27
|
+
const className = cx({
|
|
28
|
+
[`${prefix}--header-overflow-panel`]: true,
|
|
29
|
+
[customClassName]: !!customClassName
|
|
30
|
+
});
|
|
31
|
+
const isMd = useMatchMedia(mdMediaQuery);
|
|
32
|
+
return /*#__PURE__*/React__default.createElement(HeaderPopover, _extends({
|
|
33
|
+
ref: ref,
|
|
34
|
+
align: "bottom-end",
|
|
35
|
+
className: className
|
|
36
|
+
}, rest), /*#__PURE__*/React__default.createElement(HeaderPopoverButton, {
|
|
37
|
+
align: isMd ? 'bottom-end' : 'bottom',
|
|
38
|
+
label: label
|
|
39
|
+
}, _OverflowMenuVertical || (_OverflowMenuVertical = /*#__PURE__*/React__default.createElement(OverflowMenuVertical, null))), /*#__PURE__*/React__default.createElement(HeaderPopoverContent, null, /*#__PURE__*/React__default.createElement("ul", null, children)));
|
|
40
|
+
});
|
|
41
|
+
HeaderOverflowPanel.propTypes = {
|
|
42
|
+
/**
|
|
43
|
+
* Custom children to be rendered within the popover of the Profile menu
|
|
44
|
+
*/
|
|
45
|
+
children: PropTypes.any,
|
|
46
|
+
/**
|
|
47
|
+
* Provide an optional class to be applied to the containing node
|
|
48
|
+
*/
|
|
49
|
+
className: PropTypes.string,
|
|
50
|
+
/**
|
|
51
|
+
* Provide the Overflow panel's label
|
|
52
|
+
*/
|
|
53
|
+
label: PropTypes.string
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { HeaderOverflowPanel };
|
package/es/components/Profile.js
CHANGED
|
@@ -30,7 +30,7 @@ const Profile = /*#__PURE__*/React__default.forwardRef(function Profile({
|
|
|
30
30
|
align: "bottom-end",
|
|
31
31
|
className: className
|
|
32
32
|
}, rest), /*#__PURE__*/React__default.createElement(HeaderPopoverButton, {
|
|
33
|
-
align: "bottom",
|
|
33
|
+
align: "bottom-end",
|
|
34
34
|
label: label
|
|
35
35
|
}, IconElement), /*#__PURE__*/React__default.createElement(HeaderPopoverContent, null, children));
|
|
36
36
|
});
|
|
@@ -38,6 +38,7 @@ export interface SideNavProps extends ComponentProps<'nav'>, TranslateWithId<Tra
|
|
|
38
38
|
hideOverlay?: boolean;
|
|
39
39
|
navType?: SIDE_NAV_TYPE;
|
|
40
40
|
isTreeview?: boolean;
|
|
41
|
+
headerOverflowPanel?: boolean;
|
|
41
42
|
}
|
|
42
43
|
interface SideNavContextData {
|
|
43
44
|
autoExpand?: boolean;
|
|
@@ -48,6 +49,7 @@ interface SideNavContextData {
|
|
|
48
49
|
setIsTreeview?: (value: boolean) => void;
|
|
49
50
|
currentPrimaryMenu?: string;
|
|
50
51
|
setCurrentPrimaryMenu?: (value: string) => void;
|
|
52
|
+
headerOverflowPanel?: boolean;
|
|
51
53
|
}
|
|
52
54
|
export declare const SideNavContext: React.Context<SideNavContextData>;
|
|
53
55
|
export declare const SideNav: React.ForwardRefExoticComponent<Omit<SideNavProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
package/es/components/SideNav.js
CHANGED
|
@@ -68,6 +68,7 @@ function SideNavRenderFunction({
|
|
|
68
68
|
isCollapsible = false,
|
|
69
69
|
hideOverlay = false,
|
|
70
70
|
translateWithId: t = defaultTranslateWithId,
|
|
71
|
+
headerOverflowPanel,
|
|
71
72
|
...other
|
|
72
73
|
}, ref) {
|
|
73
74
|
const [internalIsTreeview, setInternalIsTreeview] = useState(isTreeviewProp ?? false);
|
|
@@ -141,7 +142,7 @@ function SideNavRenderFunction({
|
|
|
141
142
|
const resetNodeTabIndices = useCallback(() => {
|
|
142
143
|
const items = sideNavRef?.current?.querySelectorAll('[tabIndex="0"]') ?? [];
|
|
143
144
|
items.forEach(item => {
|
|
144
|
-
if (item.classList.contains(`${prefix}--side-nav__toggle`) || item.classList.contains(`${prefix}--side-nav__back-button`) || item.closest(`.${prefix}--side-nav__slot-item`) || item.classList.contains(`${prefix}--side-nav__link`) && item.closest('ul')?.getAttribute('aria-label') === ariaLabel) {
|
|
145
|
+
if (item.classList.contains(`${prefix}--side-nav__toggle`) || item.classList.contains(`${prefix}--side-nav__back-button`) || item.closest(`.${prefix}--side-nav__slot-item`) || item.classList.contains(`${prefix}--side-nav__link`) && item.closest('ul')?.getAttribute('aria-label') === ariaLabel || item.closest(`.${prefix}--header-overflow-panel-secondary-container`)) {
|
|
145
146
|
return;
|
|
146
147
|
}
|
|
147
148
|
item.tabIndex = -1;
|
|
@@ -168,7 +169,9 @@ function SideNavRenderFunction({
|
|
|
168
169
|
}
|
|
169
170
|
}, [prefix, internalIsTreeview, resetNodeTabIndices]);
|
|
170
171
|
const smMediaQuery = `(min-width: ${breakpoints.sm.width})`;
|
|
171
|
-
const
|
|
172
|
+
const lgMediaQuery = `(min-width: ${breakpoints.lg.width})`;
|
|
173
|
+
const query = !headerOverflowPanel ? smMediaQuery : lgMediaQuery;
|
|
174
|
+
const isSm = useMatchMedia(query);
|
|
172
175
|
useEffect(() => {
|
|
173
176
|
if (sideNavRef.current) {
|
|
174
177
|
const backButton = sideNavRef?.current.querySelector(`.${prefix}--side-nav__back-button`);
|
|
@@ -379,7 +382,6 @@ function SideNavRenderFunction({
|
|
|
379
382
|
sideNavRef.current.focus();
|
|
380
383
|
}
|
|
381
384
|
});
|
|
382
|
-
const lgMediaQuery = `(min-width: ${breakpoints.lg.width})`;
|
|
383
385
|
const isLg = useMatchMedia(lgMediaQuery);
|
|
384
386
|
|
|
385
387
|
// ensure that changes are in sync with internal treeview prop
|
|
@@ -417,7 +419,8 @@ function SideNavRenderFunction({
|
|
|
417
419
|
isTreeview: internalIsTreeview,
|
|
418
420
|
setIsTreeview,
|
|
419
421
|
currentPrimaryMenu,
|
|
420
|
-
setCurrentPrimaryMenu
|
|
422
|
+
setCurrentPrimaryMenu,
|
|
423
|
+
headerOverflowPanel
|
|
421
424
|
}
|
|
422
425
|
}, isFixedNav || hideOverlay || navType === SIDE_NAV_TYPE.RAIL_PANEL ? null :
|
|
423
426
|
/*#__PURE__*/
|
|
@@ -458,84 +461,74 @@ SideNav.propTypes = {
|
|
|
458
461
|
*/
|
|
459
462
|
addMouseListeners: PropTypes.bool,
|
|
460
463
|
/**
|
|
461
|
-
* Optionally provide a custom class to apply to the
|
|
464
|
+
* Optionally provide a custom class to apply to the `<nav>` element
|
|
462
465
|
*/
|
|
463
466
|
className: PropTypes.string,
|
|
464
467
|
/**
|
|
465
|
-
*
|
|
468
|
+
* Specify whether the `SideNav` starts expanded when initially rendered. Only applies when using the `SideNav` as an uncontrolled component.
|
|
466
469
|
*/
|
|
467
470
|
defaultExpanded: PropTypes.bool,
|
|
468
471
|
/**
|
|
469
|
-
* Specify the duration in milliseconds to delay before displaying the
|
|
472
|
+
* Specify the duration in milliseconds to delay before displaying the `SideNav`.
|
|
470
473
|
*/
|
|
471
474
|
enterDelayMs: PropTypes.number,
|
|
472
475
|
/**
|
|
473
|
-
*
|
|
474
|
-
* Using this prop causes SideNav to become a controled component.
|
|
476
|
+
* Control the expanded state of the `SideNav` externally. When provided, the `SideNav` becomes a controlled component and you must handle toggle events.
|
|
475
477
|
*/
|
|
476
478
|
expanded: PropTypes.bool,
|
|
477
479
|
/**
|
|
478
|
-
*
|
|
480
|
+
* Specify whether the `SideNav` is rendered inside a `HeaderOverflowPanel`. When `true`, adjusts the responsive behavior to work correctly within the overflow menu at mobile/tablet breakpoints.
|
|
481
|
+
*/
|
|
482
|
+
headerOverflowPanel: PropTypes.bool,
|
|
483
|
+
/**
|
|
484
|
+
* If `true`, the backdrop overlay will be hidden at all breakpoints. By default, the overlay appears behind the `SideNav` on mobile and tablet (below `lg` breakpoint).
|
|
479
485
|
*/
|
|
480
486
|
hideOverlay: PropTypes.bool,
|
|
481
487
|
/**
|
|
482
|
-
* Specify the breakpoint at which the SideNav will be hidden.
|
|
483
|
-
* Can be one of `sm`, `md`, `lg`, `xlg`, or `max`.
|
|
484
|
-
* Only applies when `isRail` is `true`.
|
|
488
|
+
* Specify the breakpoint at which the `SideNav` will be hidden. Can be one of `sm`, `md`, `lg`, `xlg`, or `max`. Only applies when `isRail` is `true` or `navType` is `RAIL_PANEL`.
|
|
485
489
|
*/
|
|
486
490
|
hideRailBreakpointDown: PropTypes.oneOf(['sm', 'md', 'lg', 'xlg', 'max']),
|
|
487
491
|
/**
|
|
488
|
-
* Provide
|
|
489
|
-
* main content.
|
|
492
|
+
* Provide an `href` (typically an anchor like `#main-content`) to move focus to when closing the `SideNav` with the Escape key.
|
|
490
493
|
*/
|
|
491
494
|
href: PropTypes.string,
|
|
492
495
|
/**
|
|
493
|
-
*
|
|
496
|
+
* Specify whether the `SideNav` is the primary navigation controlled by the header. When `true`, the `SideNav` is part of the UI Shell header layout (full-width on desktop, collapses on mobile). Set to `false` for secondary navigation / rails, overflow panels, or standalone navigation that is independent of the header.
|
|
494
497
|
*/
|
|
495
498
|
isChildOfHeader: PropTypes.bool,
|
|
496
499
|
/**
|
|
497
|
-
* Specify whether the SideNav
|
|
500
|
+
* Specify whether the `SideNav` can be toggled open/closed on desktop. When `true`, the `SideNav` starts collapsed and users can expand it. Requires `isChildOfHeader` to be `true` (default).
|
|
498
501
|
*/
|
|
499
502
|
isCollapsible: PropTypes.bool,
|
|
500
503
|
/**
|
|
501
|
-
* Specify if
|
|
504
|
+
* Specify if `SideNav` is standalone.
|
|
502
505
|
*/
|
|
503
506
|
isFixedNav: PropTypes.bool,
|
|
504
507
|
/**
|
|
505
|
-
* Specify
|
|
508
|
+
* Specify whether the `SideNav` is visible by default. When `false`, applies the hidden class which sets width to 0.
|
|
506
509
|
*/
|
|
507
510
|
isPersistent: PropTypes.bool,
|
|
508
511
|
/**
|
|
509
|
-
*
|
|
512
|
+
* Specify whether to display the `SideNav` rail variant. When `true`, the `SideNav` displays as a narrow rail (48px) that expands to full-width on hover.
|
|
510
513
|
*/
|
|
511
514
|
isRail: PropTypes.bool,
|
|
512
515
|
/**
|
|
513
|
-
* An optional listener that is called when the SideNav overlay is clicked
|
|
516
|
+
* An optional listener that is called when the `SideNav` overlay is clicked.
|
|
514
517
|
*
|
|
515
518
|
* @param {object} event
|
|
516
519
|
*/
|
|
517
520
|
onOverlayClick: PropTypes.func,
|
|
518
521
|
/**
|
|
519
|
-
* An optional listener that is called a callback to collapse the SideNav
|
|
522
|
+
* An optional listener that is called as a callback to collapse the `SideNav`.
|
|
520
523
|
*/
|
|
521
|
-
|
|
522
524
|
onSideNavBlur: PropTypes.func,
|
|
523
525
|
/**
|
|
524
|
-
* An optional listener that is called when an event that would cause
|
|
525
|
-
* toggling the SideNav occurs.
|
|
526
|
+
* An optional listener that is called when an event that would cause toggling the `SideNav` occurs.
|
|
526
527
|
*
|
|
527
528
|
* @param {object} event
|
|
528
529
|
* @param {boolean} value
|
|
529
530
|
*/
|
|
530
531
|
onToggle: PropTypes.func
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Provide a custom function for translating all message ids within this
|
|
534
|
-
* component. This function will take in two arguments: the mesasge Id and the
|
|
535
|
-
* state of the component. From this, you should return a string representing
|
|
536
|
-
* the label you want displayed or read by screen readers.
|
|
537
|
-
*/
|
|
538
|
-
// translateById: PropTypes.func,
|
|
539
532
|
};
|
|
540
533
|
|
|
541
534
|
export { SIDE_NAV_TYPE, SideNav, SideNavContext, translationIds };
|
|
@@ -25,6 +25,7 @@ import { useMatchMedia } from '../internal/useMatchMedia.js';
|
|
|
25
25
|
|
|
26
26
|
var _ArrowLeft, _SharkFinIcon, _ChevronRight, _ChevronDown;
|
|
27
27
|
const smMediaQuery = `(max-width: ${breakpoints.md.width})`;
|
|
28
|
+
const mdMediaQuery = `(max-width: ${breakpoints.lg.width})`;
|
|
28
29
|
const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu({
|
|
29
30
|
backButtonRenderIcon = () => _ArrowLeft || (_ArrowLeft = /*#__PURE__*/React__default.createElement(ArrowLeft, {
|
|
30
31
|
size: 16
|
|
@@ -50,7 +51,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
50
51
|
expanded,
|
|
51
52
|
navType,
|
|
52
53
|
isRail,
|
|
53
|
-
setIsTreeview
|
|
54
|
+
setIsTreeview,
|
|
55
|
+
headerOverflowPanel
|
|
54
56
|
} = useContext(SideNavContext);
|
|
55
57
|
const sideNavExpanded = expanded;
|
|
56
58
|
const prefix = usePrefix();
|
|
@@ -97,8 +99,6 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
97
99
|
if (/*#__PURE__*/React__default.isValidElement(children)) {
|
|
98
100
|
const props = children.props;
|
|
99
101
|
if (props.isActive === true || props['aria-current']) {
|
|
100
|
-
// setActive(true);
|
|
101
|
-
|
|
102
102
|
return true;
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -138,7 +138,7 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
138
138
|
[`${prefix}--side-nav__submenu`]: true,
|
|
139
139
|
[`${prefix}--side-nav__submenu--active`]: active || hasActiveDescendant && isExpanded
|
|
140
140
|
});
|
|
141
|
-
const
|
|
141
|
+
const secondaryClassNames = cx({
|
|
142
142
|
[`${prefix}--side-nav__menu-secondary-wrapper`]: true,
|
|
143
143
|
[`${prefix}--side-nav__menu-secondary-wrapper-expanded`]: isSideNavExpanded && isSecondaryOpen && currentPrimaryMenu === uniqueId
|
|
144
144
|
});
|
|
@@ -301,7 +301,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
301
301
|
}
|
|
302
302
|
}, [sideNavExpanded]);
|
|
303
303
|
const [openPopover, setOpenPopover] = React__default.useState(false);
|
|
304
|
-
const
|
|
304
|
+
const query = !headerOverflowPanel ? smMediaQuery : mdMediaQuery;
|
|
305
|
+
const isSm = useMatchMedia(query);
|
|
305
306
|
|
|
306
307
|
// keeps the secondary open when moving from small to large breakpoints
|
|
307
308
|
useEffect(() => {
|
|
@@ -355,8 +356,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
355
356
|
})) : _ChevronDown || (_ChevronDown = /*#__PURE__*/React__default.createElement(ChevronDown, {
|
|
356
357
|
size: 20
|
|
357
358
|
})))), primary ? /*#__PURE__*/React__default.createElement(Layer, null, /*#__PURE__*/React__default.createElement("div", {
|
|
358
|
-
className:
|
|
359
|
-
}, /*#__PURE__*/React__default.createElement(SideNavItems, {
|
|
359
|
+
className: secondaryClassNames
|
|
360
|
+
}, !headerOverflowPanel ? /*#__PURE__*/React__default.createElement(SideNavItems, {
|
|
360
361
|
accessibilityLabel: {
|
|
361
362
|
'aria-label': `${title} submenu`
|
|
362
363
|
}
|
|
@@ -367,6 +368,15 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
367
368
|
onClick: handleOnBackButtonClick,
|
|
368
369
|
className: `${prefix}--side-nav__back-button`,
|
|
369
370
|
renderIcon: backButtonRenderIcon
|
|
371
|
+
}, backButtonTitle), childrenToRender) : /*#__PURE__*/React__default.createElement("div", {
|
|
372
|
+
className: `${prefix}--header-overflow-panel-secondary-container`
|
|
373
|
+
}, /*#__PURE__*/React__default.createElement(Button, {
|
|
374
|
+
ref: backButtonRef,
|
|
375
|
+
kind: "ghost",
|
|
376
|
+
size: "md",
|
|
377
|
+
onClick: handleOnBackButtonClick,
|
|
378
|
+
className: `${prefix}--side-nav__back-button`,
|
|
379
|
+
renderIcon: backButtonRenderIcon
|
|
370
380
|
}, backButtonTitle), childrenToRender))) : /*#__PURE__*/React__default.createElement("ul", {
|
|
371
381
|
className: `${prefix}--side-nav__menu`,
|
|
372
382
|
role: "group"
|
package/es/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export { SharkFinIcon } from './components/SharkFinIcon';
|
|
|
18
18
|
export { HeaderDivider } from './components/HeaderDivider';
|
|
19
19
|
export { TrialCountdown } from './components/TrialCountdown';
|
|
20
20
|
export * as Profile from './components/Profile';
|
|
21
|
+
export { HeaderOverflowPanel } from './components/HeaderOverflowPanel';
|
|
21
22
|
export { SideNavSlot } from './components/SideNavSlot';
|
|
22
23
|
export { SideNavTitle } from './components/SideNavTitle';
|
package/es/index.js
CHANGED
|
@@ -18,5 +18,6 @@ export { HeaderDivider } from './components/HeaderDivider.js';
|
|
|
18
18
|
export { TrialCountdown } from './components/TrialCountdown.js';
|
|
19
19
|
import * as Profile from './components/Profile.js';
|
|
20
20
|
export { Profile };
|
|
21
|
+
export { HeaderOverflowPanel } from './components/HeaderOverflowPanel.js';
|
|
21
22
|
export { SideNavSlot } from './components/SideNavSlot.js';
|
|
22
23
|
export { SideNavTitle } from './components/SideNavTitle.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
*
|
|
4
|
+
* Copyright IBM Corp. 2025
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
export interface HeaderOverflowPanelProps {
|
|
11
|
+
/**
|
|
12
|
+
* Provide an optional class to be applied to the containing node
|
|
13
|
+
*/
|
|
14
|
+
className?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Custom children to be rendered within the popover of the Overflow panel menu
|
|
17
|
+
*/
|
|
18
|
+
children?: React.ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Provide the Overflow panel's label
|
|
21
|
+
*/
|
|
22
|
+
label?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const HeaderOverflowPanel: React.ForwardRefExoticComponent<HeaderOverflowPanelProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js');
|
|
11
|
+
var cx = require('classnames');
|
|
12
|
+
var PropTypes = require('prop-types');
|
|
13
|
+
var React__default = require('react');
|
|
14
|
+
var usePrefix = require('../internal/usePrefix.js');
|
|
15
|
+
var HeaderPopover = require('./HeaderPopover.js');
|
|
16
|
+
var iconsReact = require('@carbon/icons-react');
|
|
17
|
+
var useMatchMedia = require('../internal/useMatchMedia.js');
|
|
18
|
+
var index = require('../node_modules/@carbon/layout/es/index.js');
|
|
19
|
+
|
|
20
|
+
var _OverflowMenuVertical;
|
|
21
|
+
const mdMediaQuery = `(max-width: ${index.breakpoints.md.width})`;
|
|
22
|
+
const HeaderOverflowPanel = /*#__PURE__*/React__default.forwardRef(function HeaderOverflowPanel({
|
|
23
|
+
className: customClassName,
|
|
24
|
+
children,
|
|
25
|
+
label,
|
|
26
|
+
...rest
|
|
27
|
+
}, ref) {
|
|
28
|
+
const prefix = usePrefix.usePrefix();
|
|
29
|
+
const className = cx({
|
|
30
|
+
[`${prefix}--header-overflow-panel`]: true,
|
|
31
|
+
[customClassName]: !!customClassName
|
|
32
|
+
});
|
|
33
|
+
const isMd = useMatchMedia.useMatchMedia(mdMediaQuery);
|
|
34
|
+
return /*#__PURE__*/React__default.createElement(HeaderPopover.HeaderPopover, _rollupPluginBabelHelpers.extends({
|
|
35
|
+
ref: ref,
|
|
36
|
+
align: "bottom-end",
|
|
37
|
+
className: className
|
|
38
|
+
}, rest), /*#__PURE__*/React__default.createElement(HeaderPopover.HeaderPopoverButton, {
|
|
39
|
+
align: isMd ? 'bottom-end' : 'bottom',
|
|
40
|
+
label: label
|
|
41
|
+
}, _OverflowMenuVertical || (_OverflowMenuVertical = /*#__PURE__*/React__default.createElement(iconsReact.OverflowMenuVertical, null))), /*#__PURE__*/React__default.createElement(HeaderPopover.HeaderPopoverContent, null, /*#__PURE__*/React__default.createElement("ul", null, children)));
|
|
42
|
+
});
|
|
43
|
+
HeaderOverflowPanel.propTypes = {
|
|
44
|
+
/**
|
|
45
|
+
* Custom children to be rendered within the popover of the Profile menu
|
|
46
|
+
*/
|
|
47
|
+
children: PropTypes.any,
|
|
48
|
+
/**
|
|
49
|
+
* Provide an optional class to be applied to the containing node
|
|
50
|
+
*/
|
|
51
|
+
className: PropTypes.string,
|
|
52
|
+
/**
|
|
53
|
+
* Provide the Overflow panel's label
|
|
54
|
+
*/
|
|
55
|
+
label: PropTypes.string
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
exports.HeaderOverflowPanel = HeaderOverflowPanel;
|
|
@@ -32,7 +32,7 @@ const Profile = /*#__PURE__*/React__default.forwardRef(function Profile({
|
|
|
32
32
|
align: "bottom-end",
|
|
33
33
|
className: className
|
|
34
34
|
}, rest), /*#__PURE__*/React__default.createElement(HeaderPopover.HeaderPopoverButton, {
|
|
35
|
-
align: "bottom",
|
|
35
|
+
align: "bottom-end",
|
|
36
36
|
label: label
|
|
37
37
|
}, IconElement), /*#__PURE__*/React__default.createElement(HeaderPopover.HeaderPopoverContent, null, children));
|
|
38
38
|
});
|
|
@@ -38,6 +38,7 @@ export interface SideNavProps extends ComponentProps<'nav'>, TranslateWithId<Tra
|
|
|
38
38
|
hideOverlay?: boolean;
|
|
39
39
|
navType?: SIDE_NAV_TYPE;
|
|
40
40
|
isTreeview?: boolean;
|
|
41
|
+
headerOverflowPanel?: boolean;
|
|
41
42
|
}
|
|
42
43
|
interface SideNavContextData {
|
|
43
44
|
autoExpand?: boolean;
|
|
@@ -48,6 +49,7 @@ interface SideNavContextData {
|
|
|
48
49
|
setIsTreeview?: (value: boolean) => void;
|
|
49
50
|
currentPrimaryMenu?: string;
|
|
50
51
|
setCurrentPrimaryMenu?: (value: string) => void;
|
|
52
|
+
headerOverflowPanel?: boolean;
|
|
51
53
|
}
|
|
52
54
|
export declare const SideNavContext: React.Context<SideNavContextData>;
|
|
53
55
|
export declare const SideNav: React.ForwardRefExoticComponent<Omit<SideNavProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
|
@@ -70,6 +70,7 @@ function SideNavRenderFunction({
|
|
|
70
70
|
isCollapsible = false,
|
|
71
71
|
hideOverlay = false,
|
|
72
72
|
translateWithId: t = defaultTranslateWithId,
|
|
73
|
+
headerOverflowPanel,
|
|
73
74
|
...other
|
|
74
75
|
}, ref) {
|
|
75
76
|
const [internalIsTreeview, setInternalIsTreeview] = React__default.useState(isTreeviewProp ?? false);
|
|
@@ -143,7 +144,7 @@ function SideNavRenderFunction({
|
|
|
143
144
|
const resetNodeTabIndices = React__default.useCallback(() => {
|
|
144
145
|
const items = sideNavRef?.current?.querySelectorAll('[tabIndex="0"]') ?? [];
|
|
145
146
|
items.forEach(item => {
|
|
146
|
-
if (item.classList.contains(`${prefix}--side-nav__toggle`) || item.classList.contains(`${prefix}--side-nav__back-button`) || item.closest(`.${prefix}--side-nav__slot-item`) || item.classList.contains(`${prefix}--side-nav__link`) && item.closest('ul')?.getAttribute('aria-label') === ariaLabel) {
|
|
147
|
+
if (item.classList.contains(`${prefix}--side-nav__toggle`) || item.classList.contains(`${prefix}--side-nav__back-button`) || item.closest(`.${prefix}--side-nav__slot-item`) || item.classList.contains(`${prefix}--side-nav__link`) && item.closest('ul')?.getAttribute('aria-label') === ariaLabel || item.closest(`.${prefix}--header-overflow-panel-secondary-container`)) {
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
150
|
item.tabIndex = -1;
|
|
@@ -170,7 +171,9 @@ function SideNavRenderFunction({
|
|
|
170
171
|
}
|
|
171
172
|
}, [prefix, internalIsTreeview, resetNodeTabIndices]);
|
|
172
173
|
const smMediaQuery = `(min-width: ${index.breakpoints.sm.width})`;
|
|
173
|
-
const
|
|
174
|
+
const lgMediaQuery = `(min-width: ${index.breakpoints.lg.width})`;
|
|
175
|
+
const query = !headerOverflowPanel ? smMediaQuery : lgMediaQuery;
|
|
176
|
+
const isSm = useMatchMedia.useMatchMedia(query);
|
|
174
177
|
React__default.useEffect(() => {
|
|
175
178
|
if (sideNavRef.current) {
|
|
176
179
|
const backButton = sideNavRef?.current.querySelector(`.${prefix}--side-nav__back-button`);
|
|
@@ -381,7 +384,6 @@ function SideNavRenderFunction({
|
|
|
381
384
|
sideNavRef.current.focus();
|
|
382
385
|
}
|
|
383
386
|
});
|
|
384
|
-
const lgMediaQuery = `(min-width: ${index.breakpoints.lg.width})`;
|
|
385
387
|
const isLg = useMatchMedia.useMatchMedia(lgMediaQuery);
|
|
386
388
|
|
|
387
389
|
// ensure that changes are in sync with internal treeview prop
|
|
@@ -419,7 +421,8 @@ function SideNavRenderFunction({
|
|
|
419
421
|
isTreeview: internalIsTreeview,
|
|
420
422
|
setIsTreeview,
|
|
421
423
|
currentPrimaryMenu,
|
|
422
|
-
setCurrentPrimaryMenu
|
|
424
|
+
setCurrentPrimaryMenu,
|
|
425
|
+
headerOverflowPanel
|
|
423
426
|
}
|
|
424
427
|
}, isFixedNav || hideOverlay || navType === SIDE_NAV_TYPE.RAIL_PANEL ? null :
|
|
425
428
|
/*#__PURE__*/
|
|
@@ -460,84 +463,74 @@ SideNav.propTypes = {
|
|
|
460
463
|
*/
|
|
461
464
|
addMouseListeners: PropTypes.bool,
|
|
462
465
|
/**
|
|
463
|
-
* Optionally provide a custom class to apply to the
|
|
466
|
+
* Optionally provide a custom class to apply to the `<nav>` element
|
|
464
467
|
*/
|
|
465
468
|
className: PropTypes.string,
|
|
466
469
|
/**
|
|
467
|
-
*
|
|
470
|
+
* Specify whether the `SideNav` starts expanded when initially rendered. Only applies when using the `SideNav` as an uncontrolled component.
|
|
468
471
|
*/
|
|
469
472
|
defaultExpanded: PropTypes.bool,
|
|
470
473
|
/**
|
|
471
|
-
* Specify the duration in milliseconds to delay before displaying the
|
|
474
|
+
* Specify the duration in milliseconds to delay before displaying the `SideNav`.
|
|
472
475
|
*/
|
|
473
476
|
enterDelayMs: PropTypes.number,
|
|
474
477
|
/**
|
|
475
|
-
*
|
|
476
|
-
* Using this prop causes SideNav to become a controled component.
|
|
478
|
+
* Control the expanded state of the `SideNav` externally. When provided, the `SideNav` becomes a controlled component and you must handle toggle events.
|
|
477
479
|
*/
|
|
478
480
|
expanded: PropTypes.bool,
|
|
479
481
|
/**
|
|
480
|
-
*
|
|
482
|
+
* Specify whether the `SideNav` is rendered inside a `HeaderOverflowPanel`. When `true`, adjusts the responsive behavior to work correctly within the overflow menu at mobile/tablet breakpoints.
|
|
483
|
+
*/
|
|
484
|
+
headerOverflowPanel: PropTypes.bool,
|
|
485
|
+
/**
|
|
486
|
+
* If `true`, the backdrop overlay will be hidden at all breakpoints. By default, the overlay appears behind the `SideNav` on mobile and tablet (below `lg` breakpoint).
|
|
481
487
|
*/
|
|
482
488
|
hideOverlay: PropTypes.bool,
|
|
483
489
|
/**
|
|
484
|
-
* Specify the breakpoint at which the SideNav will be hidden.
|
|
485
|
-
* Can be one of `sm`, `md`, `lg`, `xlg`, or `max`.
|
|
486
|
-
* Only applies when `isRail` is `true`.
|
|
490
|
+
* Specify the breakpoint at which the `SideNav` will be hidden. Can be one of `sm`, `md`, `lg`, `xlg`, or `max`. Only applies when `isRail` is `true` or `navType` is `RAIL_PANEL`.
|
|
487
491
|
*/
|
|
488
492
|
hideRailBreakpointDown: PropTypes.oneOf(['sm', 'md', 'lg', 'xlg', 'max']),
|
|
489
493
|
/**
|
|
490
|
-
* Provide
|
|
491
|
-
* main content.
|
|
494
|
+
* Provide an `href` (typically an anchor like `#main-content`) to move focus to when closing the `SideNav` with the Escape key.
|
|
492
495
|
*/
|
|
493
496
|
href: PropTypes.string,
|
|
494
497
|
/**
|
|
495
|
-
*
|
|
498
|
+
* Specify whether the `SideNav` is the primary navigation controlled by the header. When `true`, the `SideNav` is part of the UI Shell header layout (full-width on desktop, collapses on mobile). Set to `false` for secondary navigation / rails, overflow panels, or standalone navigation that is independent of the header.
|
|
496
499
|
*/
|
|
497
500
|
isChildOfHeader: PropTypes.bool,
|
|
498
501
|
/**
|
|
499
|
-
* Specify whether the SideNav
|
|
502
|
+
* Specify whether the `SideNav` can be toggled open/closed on desktop. When `true`, the `SideNav` starts collapsed and users can expand it. Requires `isChildOfHeader` to be `true` (default).
|
|
500
503
|
*/
|
|
501
504
|
isCollapsible: PropTypes.bool,
|
|
502
505
|
/**
|
|
503
|
-
* Specify if
|
|
506
|
+
* Specify if `SideNav` is standalone.
|
|
504
507
|
*/
|
|
505
508
|
isFixedNav: PropTypes.bool,
|
|
506
509
|
/**
|
|
507
|
-
* Specify
|
|
510
|
+
* Specify whether the `SideNav` is visible by default. When `false`, applies the hidden class which sets width to 0.
|
|
508
511
|
*/
|
|
509
512
|
isPersistent: PropTypes.bool,
|
|
510
513
|
/**
|
|
511
|
-
*
|
|
514
|
+
* Specify whether to display the `SideNav` rail variant. When `true`, the `SideNav` displays as a narrow rail (48px) that expands to full-width on hover.
|
|
512
515
|
*/
|
|
513
516
|
isRail: PropTypes.bool,
|
|
514
517
|
/**
|
|
515
|
-
* An optional listener that is called when the SideNav overlay is clicked
|
|
518
|
+
* An optional listener that is called when the `SideNav` overlay is clicked.
|
|
516
519
|
*
|
|
517
520
|
* @param {object} event
|
|
518
521
|
*/
|
|
519
522
|
onOverlayClick: PropTypes.func,
|
|
520
523
|
/**
|
|
521
|
-
* An optional listener that is called a callback to collapse the SideNav
|
|
524
|
+
* An optional listener that is called as a callback to collapse the `SideNav`.
|
|
522
525
|
*/
|
|
523
|
-
|
|
524
526
|
onSideNavBlur: PropTypes.func,
|
|
525
527
|
/**
|
|
526
|
-
* An optional listener that is called when an event that would cause
|
|
527
|
-
* toggling the SideNav occurs.
|
|
528
|
+
* An optional listener that is called when an event that would cause toggling the `SideNav` occurs.
|
|
528
529
|
*
|
|
529
530
|
* @param {object} event
|
|
530
531
|
* @param {boolean} value
|
|
531
532
|
*/
|
|
532
533
|
onToggle: PropTypes.func
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* Provide a custom function for translating all message ids within this
|
|
536
|
-
* component. This function will take in two arguments: the mesasge Id and the
|
|
537
|
-
* state of the component. From this, you should return a string representing
|
|
538
|
-
* the label you want displayed or read by screen readers.
|
|
539
|
-
*/
|
|
540
|
-
// translateById: PropTypes.func,
|
|
541
534
|
};
|
|
542
535
|
|
|
543
536
|
exports.SIDE_NAV_TYPE = SIDE_NAV_TYPE;
|
|
@@ -27,6 +27,7 @@ var useMatchMedia = require('../internal/useMatchMedia.js');
|
|
|
27
27
|
|
|
28
28
|
var _ArrowLeft, _SharkFinIcon, _ChevronRight, _ChevronDown;
|
|
29
29
|
const smMediaQuery = `(max-width: ${index.breakpoints.md.width})`;
|
|
30
|
+
const mdMediaQuery = `(max-width: ${index.breakpoints.lg.width})`;
|
|
30
31
|
const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu({
|
|
31
32
|
backButtonRenderIcon = () => _ArrowLeft || (_ArrowLeft = /*#__PURE__*/React__default.createElement(iconsReact.ArrowLeft, {
|
|
32
33
|
size: 16
|
|
@@ -52,7 +53,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
52
53
|
expanded,
|
|
53
54
|
navType,
|
|
54
55
|
isRail,
|
|
55
|
-
setIsTreeview
|
|
56
|
+
setIsTreeview,
|
|
57
|
+
headerOverflowPanel
|
|
56
58
|
} = React__default.useContext(SideNav.SideNavContext);
|
|
57
59
|
const sideNavExpanded = expanded;
|
|
58
60
|
const prefix = usePrefix.usePrefix();
|
|
@@ -99,8 +101,6 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
99
101
|
if (/*#__PURE__*/React__default.isValidElement(children)) {
|
|
100
102
|
const props = children.props;
|
|
101
103
|
if (props.isActive === true || props['aria-current']) {
|
|
102
|
-
// setActive(true);
|
|
103
|
-
|
|
104
104
|
return true;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
@@ -140,7 +140,7 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
140
140
|
[`${prefix}--side-nav__submenu`]: true,
|
|
141
141
|
[`${prefix}--side-nav__submenu--active`]: active || hasActiveDescendant && isExpanded
|
|
142
142
|
});
|
|
143
|
-
const
|
|
143
|
+
const secondaryClassNames = cx({
|
|
144
144
|
[`${prefix}--side-nav__menu-secondary-wrapper`]: true,
|
|
145
145
|
[`${prefix}--side-nav__menu-secondary-wrapper-expanded`]: isSideNavExpanded && isSecondaryOpen && currentPrimaryMenu === uniqueId
|
|
146
146
|
});
|
|
@@ -303,7 +303,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
303
303
|
}
|
|
304
304
|
}, [sideNavExpanded]);
|
|
305
305
|
const [openPopover, setOpenPopover] = React__default.useState(false);
|
|
306
|
-
const
|
|
306
|
+
const query = !headerOverflowPanel ? smMediaQuery : mdMediaQuery;
|
|
307
|
+
const isSm = useMatchMedia.useMatchMedia(query);
|
|
307
308
|
|
|
308
309
|
// keeps the secondary open when moving from small to large breakpoints
|
|
309
310
|
React__default.useEffect(() => {
|
|
@@ -357,8 +358,8 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
357
358
|
})) : _ChevronDown || (_ChevronDown = /*#__PURE__*/React__default.createElement(iconsReact.ChevronDown, {
|
|
358
359
|
size: 20
|
|
359
360
|
})))), primary ? /*#__PURE__*/React__default.createElement(react.Layer, null, /*#__PURE__*/React__default.createElement("div", {
|
|
360
|
-
className:
|
|
361
|
-
}, /*#__PURE__*/React__default.createElement(SideNavItems.SideNavItems, {
|
|
361
|
+
className: secondaryClassNames
|
|
362
|
+
}, !headerOverflowPanel ? /*#__PURE__*/React__default.createElement(SideNavItems.SideNavItems, {
|
|
362
363
|
accessibilityLabel: {
|
|
363
364
|
'aria-label': `${title} submenu`
|
|
364
365
|
}
|
|
@@ -369,6 +370,15 @@ const SideNavMenu = /*#__PURE__*/React__default.forwardRef(function SideNavMenu(
|
|
|
369
370
|
onClick: handleOnBackButtonClick,
|
|
370
371
|
className: `${prefix}--side-nav__back-button`,
|
|
371
372
|
renderIcon: backButtonRenderIcon
|
|
373
|
+
}, backButtonTitle), childrenToRender) : /*#__PURE__*/React__default.createElement("div", {
|
|
374
|
+
className: `${prefix}--header-overflow-panel-secondary-container`
|
|
375
|
+
}, /*#__PURE__*/React__default.createElement(react.Button, {
|
|
376
|
+
ref: backButtonRef,
|
|
377
|
+
kind: "ghost",
|
|
378
|
+
size: "md",
|
|
379
|
+
onClick: handleOnBackButtonClick,
|
|
380
|
+
className: `${prefix}--side-nav__back-button`,
|
|
381
|
+
renderIcon: backButtonRenderIcon
|
|
372
382
|
}, backButtonTitle), childrenToRender))) : /*#__PURE__*/React__default.createElement("ul", {
|
|
373
383
|
className: `${prefix}--side-nav__menu`,
|
|
374
384
|
role: "group"
|
package/lib/index.d.ts
CHANGED
|
@@ -18,5 +18,6 @@ export { SharkFinIcon } from './components/SharkFinIcon';
|
|
|
18
18
|
export { HeaderDivider } from './components/HeaderDivider';
|
|
19
19
|
export { TrialCountdown } from './components/TrialCountdown';
|
|
20
20
|
export * as Profile from './components/Profile';
|
|
21
|
+
export { HeaderOverflowPanel } from './components/HeaderOverflowPanel';
|
|
21
22
|
export { SideNavSlot } from './components/SideNavSlot';
|
|
22
23
|
export { SideNavTitle } from './components/SideNavTitle';
|
package/lib/index.js
CHANGED
|
@@ -19,6 +19,7 @@ var SharkFinIcon = require('./components/SharkFinIcon.js');
|
|
|
19
19
|
var HeaderDivider = require('./components/HeaderDivider.js');
|
|
20
20
|
var TrialCountdown = require('./components/TrialCountdown.js');
|
|
21
21
|
var Profile = require('./components/Profile.js');
|
|
22
|
+
var HeaderOverflowPanel = require('./components/HeaderOverflowPanel.js');
|
|
22
23
|
var SideNavSlot = require('./components/SideNavSlot.js');
|
|
23
24
|
var SideNavTitle = require('./components/SideNavTitle.js');
|
|
24
25
|
|
|
@@ -40,5 +41,6 @@ exports.SharkFinIcon = SharkFinIcon.SharkFinIcon;
|
|
|
40
41
|
exports.HeaderDivider = HeaderDivider.HeaderDivider;
|
|
41
42
|
exports.TrialCountdown = TrialCountdown.TrialCountdown;
|
|
42
43
|
exports.Profile = Profile;
|
|
44
|
+
exports.HeaderOverflowPanel = HeaderOverflowPanel.HeaderOverflowPanel;
|
|
43
45
|
exports.SideNavSlot = SideNavSlot.SideNavSlot;
|
|
44
46
|
exports.SideNavTitle = SideNavTitle.SideNavTitle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carbon-labs/react-ui-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.84.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"provenance": true
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@ibm/telemetry-js": "^1.10.2"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "a0eaa1502bff6b7ee998a43d67e260a4ede0e2eb"
|
|
46
46
|
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2025
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
@use '@carbon/styles/scss/spacing' as *;
|
|
9
|
+
@use '@carbon/styles/scss/theme' as *;
|
|
10
|
+
@use '@carbon/react/scss/utilities/convert' as convert;
|
|
11
|
+
@use '@carbon/styles/scss/breakpoint' as *;
|
|
12
|
+
@use '@carbon/styles/scss/type' as *;
|
|
13
|
+
|
|
14
|
+
$prefix: 'cds' !default;
|
|
15
|
+
|
|
16
|
+
@include breakpoint-up(lg) {
|
|
17
|
+
.#{$prefix}--header-overflow-panel {
|
|
18
|
+
display: none;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// COPIED FROM SIDE NAV BUT NOW AT LG BREAKPOINT
|
|
23
|
+
@include breakpoint-down(lg) {
|
|
24
|
+
.#{$prefix}--header-overflow-panel
|
|
25
|
+
.#{$prefix}--side-nav--collapsible.#{$prefix}--side-nav--expanded {
|
|
26
|
+
inline-size: 100%;
|
|
27
|
+
max-inline-size: 100%;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.#{$prefix}--header-overflow-panel
|
|
31
|
+
.#{$prefix}--header-overflow-panel-secondary-container {
|
|
32
|
+
padding-block-start: $spacing-05;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.#{$prefix}--header-overflow-panel
|
|
36
|
+
.#{$prefix}--side-nav__menu-secondary-wrapper-expanded {
|
|
37
|
+
z-index: 1;
|
|
38
|
+
background-color: $background;
|
|
39
|
+
inline-size: 100%;
|
|
40
|
+
inset-inline-start: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.#{$prefix}--header-overflow-panel
|
|
44
|
+
.#{$prefix}--side-nav__back-button.#{$prefix}--btn--ghost {
|
|
45
|
+
flex-direction: row-reverse;
|
|
46
|
+
justify-content: flex-end;
|
|
47
|
+
gap: 1rem;
|
|
48
|
+
inline-size: 100%;
|
|
49
|
+
max-inline-size: 100%;
|
|
50
|
+
|
|
51
|
+
&:focus {
|
|
52
|
+
box-shadow: inset 0 0 0 1px $focus;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.#{$prefix}--header-overflow-panel
|
|
57
|
+
.#{$prefix}--side-nav__back-button.#{$prefix}--btn--ghost:not([disabled]) {
|
|
58
|
+
svg {
|
|
59
|
+
align-self: center;
|
|
60
|
+
fill: $icon-interactive;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&:hover svg {
|
|
64
|
+
fill: $link-primary-hover;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.#{$prefix}--header-overflow-panel .#{$prefix}--side-nav__item {
|
|
69
|
+
.#{$prefix}--side-nav__link,
|
|
70
|
+
.#{$prefix}--side-nav__submenu {
|
|
71
|
+
block-size: $spacing-08;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@include breakpoint(md) {
|
|
77
|
+
.#{$prefix}--header-overflow-panel.#{$prefix}--popover--tab-tip.#{$prefix}--popover--bottom-end
|
|
78
|
+
.#{$prefix}--popover
|
|
79
|
+
> .#{$prefix}--header-action__content.#{$prefix}--popover-content {
|
|
80
|
+
inset-inline-end: -$spacing-09;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.#{$prefix}--header-overflow-panel .#{$prefix}--toggletip-content {
|
|
85
|
+
padding: 0;
|
|
86
|
+
background-color: $background;
|
|
87
|
+
block-size: 100vh;
|
|
88
|
+
border-block-end: 1px solid $border-subtle;
|
|
89
|
+
border-inline-start: 1px solid $border-subtle;
|
|
90
|
+
gap: 0;
|
|
91
|
+
inline-size: convert.to-rem(256px);
|
|
92
|
+
overflow-y: auto;
|
|
93
|
+
|
|
94
|
+
> * {
|
|
95
|
+
padding: $spacing-05;
|
|
96
|
+
outline: convert.to-rem(0.5px) solid $border-subtle;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.#{$prefix}--header-overflow-panel .#{$prefix}--side-nav__link-text {
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
justify-content: space-between;
|
|
104
|
+
inline-size: 100%;
|
|
105
|
+
}
|
|
@@ -15,10 +15,12 @@
|
|
|
15
15
|
$prefix: 'cds' !default;
|
|
16
16
|
|
|
17
17
|
// profile
|
|
18
|
+
|
|
18
19
|
.#{$prefix}--profile.#{$prefix}--popover--open {
|
|
19
20
|
background-color: $background;
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
.#{$prefix}--header-overflow-panel .#{$prefix}--toggletip-content,
|
|
22
24
|
.#{$prefix}--profile .#{$prefix}--toggletip-content {
|
|
23
25
|
padding: 0;
|
|
24
26
|
background-color: $background;
|
|
@@ -28,15 +30,21 @@ $prefix: 'cds' !default;
|
|
|
28
30
|
inline-size: convert.to-rem(256px);
|
|
29
31
|
max-block-size: 100vh;
|
|
30
32
|
overflow-y: auto;
|
|
33
|
+
}
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
.#{$prefix}--header-overflow-panel,
|
|
36
|
+
.#{$prefix}--profile {
|
|
37
|
+
.#{$prefix}--profile-user-info,
|
|
38
|
+
.#{$prefix}--profile-read-only,
|
|
39
|
+
.clabs--theme-settings {
|
|
33
40
|
padding: $spacing-05;
|
|
34
|
-
|
|
41
|
+
border-block-end: convert.to-rem(0.5px) solid $border-subtle;
|
|
42
|
+
border-block-start: convert.to-rem(0.5px) solid $border-subtle;
|
|
35
43
|
}
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
// user-info
|
|
39
|
-
.#{$prefix}--profile
|
|
47
|
+
.#{$prefix}--profile-user-info {
|
|
40
48
|
display: flex;
|
|
41
49
|
}
|
|
42
50
|
|