@carbon-labs/react-ui-shell 0.27.0 → 0.29.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/README.md CHANGED
@@ -26,7 +26,7 @@ yarn add @carbon-labs/react-ui-shell @carbon/react
26
26
  ## ⚡ Usage
27
27
 
28
28
  To use this package you will need to import components from both `@carbon/react`
29
- and `@carbon-labs/react-ui-shell`o compose the UI Shell. The following
29
+ and `@carbon-labs/react-ui-shell` to compose the UI Shell. The following
30
30
  components are provided by `@carbon-labs/react-ui-shell`:
31
31
 
32
32
  - `SideNav`
@@ -35,6 +35,8 @@ components are provided by `@carbon-labs/react-ui-shell`:
35
35
  - `SideNavMenu`
36
36
  - `SideNavMenuItem`
37
37
  - `HeaderPanel`
38
+ - `HeaderDivider`
39
+ - `SharkFinIcon`
38
40
 
39
41
  ```jsx
40
42
  import { SideNav } from '@carbon-labs/react-ui-shell/es/index';
@@ -0,0 +1,14 @@
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
+ import React from 'react';
8
+ export interface HeaderDividerProps {
9
+ /**
10
+ * Provide an optional class to be applied to the containing node
11
+ */
12
+ className?: string;
13
+ }
14
+ export declare const HeaderDivider: React.FC<HeaderDividerProps>;
@@ -0,0 +1,30 @@
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 cx from '../_virtual/index.js';
9
+ import PropTypes from 'prop-types';
10
+ import React from 'react';
11
+ import { usePrefix } from '../internal/usePrefix.js';
12
+
13
+ const HeaderDivider = _ref => {
14
+ let {
15
+ className
16
+ } = _ref;
17
+ const prefix = usePrefix();
18
+ const classNames = cx(`${prefix}--header__divider`, className);
19
+ return /*#__PURE__*/React.createElement("span", {
20
+ className: classNames
21
+ });
22
+ };
23
+ HeaderDivider.propTypes = {
24
+ /**
25
+ * Provide an optional class to be applied to the containing node
26
+ */
27
+ className: PropTypes.string
28
+ };
29
+
30
+ export { HeaderDivider };
@@ -31,6 +31,11 @@ export interface SideNavMenuProps {
31
31
  * Specifies whether the SideNavMenu is in a large variation.
32
32
  */
33
33
  large?: boolean;
34
+ /**
35
+ *
36
+ * A custom onClick handler hook that runs when the SideNavMenu is toggled.
37
+ */
38
+ onMenuToggle?: () => void;
34
39
  /**
35
40
  * A custom icon to render next to the SideNavMenu title. This can be a function returning JSX or JSX itself.
36
41
  */
@@ -30,7 +30,8 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
30
30
  large = false,
31
31
  renderIcon: IconElement,
32
32
  isSideNavExpanded,
33
- title
33
+ title,
34
+ onMenuToggle
34
35
  } = _ref;
35
36
  const depth = propDepth;
36
37
  const {
@@ -149,6 +150,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
149
150
  function handleKeyDown(event) {
150
151
  if (match(event, Escape)) {
151
152
  setIsExpanded(false);
153
+ if (onMenuToggle) {
154
+ onMenuToggle();
155
+ }
152
156
  }
153
157
  if (isTreeview) {
154
158
  const node = event.target;
@@ -161,6 +165,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
161
165
  // collapse menu
162
166
  if (isMenu && sideNavExpanded) {
163
167
  if (isExpanded == 'true') {
168
+ if (onMenuToggle) {
169
+ onMenuToggle();
170
+ }
164
171
  setIsExpanded(false);
165
172
 
166
173
  // go to previous level's side nav menu button
@@ -185,6 +192,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
185
192
  // expand menu when sidenav is expanded
186
193
  if (isMenu && sideNavExpanded) {
187
194
  setIsExpanded(true);
195
+ if (onMenuToggle) {
196
+ onMenuToggle();
197
+ }
188
198
 
189
199
  // if already expanded, focus on first element
190
200
  if (isExpanded == 'true') {
@@ -225,6 +235,10 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
225
235
  "aria-expanded": isExpanded,
226
236
  className: buttonClassName,
227
237
  onClick: () => {
238
+ if (onMenuToggle) {
239
+ onMenuToggle();
240
+ }
241
+
228
242
  // only when sidenav is panel view
229
243
  if (navType == SIDE_NAV_TYPE.PANEL && !isExpanded && firstLink.current && !sideNavExpanded) {
230
244
  setOpenPopover(!openPopover);
@@ -294,6 +308,11 @@ SideNavMenu.propTypes = {
294
308
  * Specify if this is a large variation of the SideNavMenu
295
309
  */
296
310
  large: PropTypes.bool,
311
+ /**
312
+ *
313
+ * A custom onClick handler hook that runs when the SideNavMenu is toggled.
314
+ */
315
+ onMenuToggle: PropTypes.func,
297
316
  /**
298
317
  * Pass in a custom icon to render next to the `SideNavMenu` title
299
318
  */
package/es/index.d.ts CHANGED
@@ -15,3 +15,4 @@ export { SideNavMenuItem } from './components/SideNavMenuItem.js';
15
15
  export { HeaderContainer } from './components/HeaderContainer';
16
16
  export { HeaderPanel } from './components/HeaderPanel';
17
17
  export { SharkFinIcon } from './components/SharkFinIcon';
18
+ export { HeaderDivider } from './components/HeaderDivider';
package/es/index.js CHANGED
@@ -14,3 +14,4 @@ export { SideNavMenuItem } from './components/SideNavMenuItem.js';
14
14
  export { HeaderContainer } from './components/HeaderContainer.js';
15
15
  export { HeaderPanel } from './components/HeaderPanel.js';
16
16
  export { SharkFinIcon } from './components/SharkFinIcon.js';
17
+ export { HeaderDivider } from './components/HeaderDivider.js';
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import { getAttributes } from '../../icon-helpers/es/index.js';
8
+ import { getAttributes } from '../node_modules/@carbon/icon-helpers/es/index.js';
9
9
  import PropTypes from 'prop-types';
10
10
  import React from 'react';
11
11
 
@@ -0,0 +1,14 @@
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
+ import React from 'react';
8
+ export interface HeaderDividerProps {
9
+ /**
10
+ * Provide an optional class to be applied to the containing node
11
+ */
12
+ className?: string;
13
+ }
14
+ export declare const HeaderDivider: React.FC<HeaderDividerProps>;
@@ -0,0 +1,32 @@
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 index = require('../_virtual/index.js');
11
+ var PropTypes = require('prop-types');
12
+ var React = require('react');
13
+ var usePrefix = require('../internal/usePrefix.js');
14
+
15
+ const HeaderDivider = _ref => {
16
+ let {
17
+ className
18
+ } = _ref;
19
+ const prefix = usePrefix.usePrefix();
20
+ const classNames = index.default(`${prefix}--header__divider`, className);
21
+ return /*#__PURE__*/React.createElement("span", {
22
+ className: classNames
23
+ });
24
+ };
25
+ HeaderDivider.propTypes = {
26
+ /**
27
+ * Provide an optional class to be applied to the containing node
28
+ */
29
+ className: PropTypes.string
30
+ };
31
+
32
+ exports.HeaderDivider = HeaderDivider;
@@ -31,6 +31,11 @@ export interface SideNavMenuProps {
31
31
  * Specifies whether the SideNavMenu is in a large variation.
32
32
  */
33
33
  large?: boolean;
34
+ /**
35
+ *
36
+ * A custom onClick handler hook that runs when the SideNavMenu is toggled.
37
+ */
38
+ onMenuToggle?: () => void;
34
39
  /**
35
40
  * A custom icon to render next to the SideNavMenu title. This can be a function returning JSX or JSX itself.
36
41
  */
@@ -32,7 +32,8 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
32
32
  large = false,
33
33
  renderIcon: IconElement,
34
34
  isSideNavExpanded,
35
- title
35
+ title,
36
+ onMenuToggle
36
37
  } = _ref;
37
38
  const depth = propDepth;
38
39
  const {
@@ -151,6 +152,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
151
152
  function handleKeyDown(event) {
152
153
  if (match.match(event, keys.Escape)) {
153
154
  setIsExpanded(false);
155
+ if (onMenuToggle) {
156
+ onMenuToggle();
157
+ }
154
158
  }
155
159
  if (isTreeview) {
156
160
  const node = event.target;
@@ -163,6 +167,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
163
167
  // collapse menu
164
168
  if (isMenu && sideNavExpanded) {
165
169
  if (isExpanded == 'true') {
170
+ if (onMenuToggle) {
171
+ onMenuToggle();
172
+ }
166
173
  setIsExpanded(false);
167
174
 
168
175
  // go to previous level's side nav menu button
@@ -187,6 +194,9 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
187
194
  // expand menu when sidenav is expanded
188
195
  if (isMenu && sideNavExpanded) {
189
196
  setIsExpanded(true);
197
+ if (onMenuToggle) {
198
+ onMenuToggle();
199
+ }
190
200
 
191
201
  // if already expanded, focus on first element
192
202
  if (isExpanded == 'true') {
@@ -227,6 +237,10 @@ const SideNavMenu = /*#__PURE__*/React.forwardRef(function SideNavMenu(_ref, ref
227
237
  "aria-expanded": isExpanded,
228
238
  className: buttonClassName,
229
239
  onClick: () => {
240
+ if (onMenuToggle) {
241
+ onMenuToggle();
242
+ }
243
+
230
244
  // only when sidenav is panel view
231
245
  if (navType == SideNav.SIDE_NAV_TYPE.PANEL && !isExpanded && firstLink.current && !sideNavExpanded) {
232
246
  setOpenPopover(!openPopover);
@@ -296,6 +310,11 @@ SideNavMenu.propTypes = {
296
310
  * Specify if this is a large variation of the SideNavMenu
297
311
  */
298
312
  large: PropTypes.bool,
313
+ /**
314
+ *
315
+ * A custom onClick handler hook that runs when the SideNavMenu is toggled.
316
+ */
317
+ onMenuToggle: PropTypes.func,
299
318
  /**
300
319
  * Pass in a custom icon to render next to the `SideNavMenu` title
301
320
  */
package/lib/index.d.ts CHANGED
@@ -15,3 +15,4 @@ export { SideNavMenuItem } from './components/SideNavMenuItem.js';
15
15
  export { HeaderContainer } from './components/HeaderContainer';
16
16
  export { HeaderPanel } from './components/HeaderPanel';
17
17
  export { SharkFinIcon } from './components/SharkFinIcon';
18
+ export { HeaderDivider } from './components/HeaderDivider';
package/lib/index.js CHANGED
@@ -16,6 +16,7 @@ var SideNavMenuItem = require('./components/SideNavMenuItem.js');
16
16
  var HeaderContainer = require('./components/HeaderContainer.js');
17
17
  var HeaderPanel = require('./components/HeaderPanel.js');
18
18
  var SharkFinIcon = require('./components/SharkFinIcon.js');
19
+ var HeaderDivider = require('./components/HeaderDivider.js');
19
20
 
20
21
 
21
22
 
@@ -29,3 +30,4 @@ exports.SideNavMenuItem = SideNavMenuItem.SideNavMenuItem;
29
30
  exports.HeaderContainer = HeaderContainer.HeaderContainer;
30
31
  exports.HeaderPanel = HeaderPanel.HeaderPanel;
31
32
  exports.SharkFinIcon = SharkFinIcon.SharkFinIcon;
33
+ exports.HeaderDivider = HeaderDivider.HeaderDivider;
@@ -9,7 +9,7 @@
9
9
 
10
10
  Object.defineProperty(exports, '__esModule', { value: true });
11
11
 
12
- var index = require('../../icon-helpers/es/index.js');
12
+ var index = require('../node_modules/@carbon/icon-helpers/es/index.js');
13
13
  var PropTypes = require('prop-types');
14
14
  var React = require('react');
15
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carbon-labs/react-ui-shell",
3
- "version": "0.27.0",
3
+ "version": "0.29.0",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "provenance": true
@@ -33,5 +33,5 @@
33
33
  "dependencies": {
34
34
  "@ibm/telemetry-js": "^1.9.1"
35
35
  },
36
- "gitHead": "94522ab158f8e47f9d0312eccccd32ea35dd1ae6"
36
+ "gitHead": "0b543e502dcedecdc6d8b624536dc3d7f153607b"
37
37
  }
@@ -0,0 +1,17 @@
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
+ @use '@carbon/styles/scss/utilities/convert' as convert;
8
+ @use '@carbon/styles/scss/theme' as *;
9
+
10
+ $prefix: 'cds' !default;
11
+
12
+ .#{$prefix}--header__divider {
13
+ flex-shrink: 0;
14
+ background: $border-subtle;
15
+ block-size: convert.to-rem(24px);
16
+ inline-size: 1px;
17
+ }
@@ -4,9 +4,27 @@
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
+ @use '@carbon/styles/scss/theme' as *;
7
8
 
8
9
  $prefix: 'cds' !default;
9
10
 
11
+ .#{$prefix}--header__global {
12
+ align-items: center;
13
+ }
14
+
15
+ .#{$prefix}--header__action {
16
+ flex-shrink: 0;
17
+ }
18
+
10
19
  .#{$prefix}--header__action:focus {
11
20
  border-width: 2px;
12
21
  }
22
+
23
+ //----------------------------------------------------------------------------
24
+ // Menu button inside Header
25
+ //----------------------------------------------------------------------------
26
+
27
+ .#{$prefix}--header
28
+ .#{$prefix}--menu-button__trigger.#{$prefix}--btn--ghost:not([disabled]) {
29
+ color: $text-secondary;
30
+ }
@@ -9,3 +9,4 @@
9
9
  @use 'styles/side-nav';
10
10
  @use 'styles/content';
11
11
  @use 'styles/shark-fin-icon.scss';
12
+ @use 'styles/header-divider.scss';