@redis-ui/components 47.0.0 → 47.1.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.
Files changed (49) hide show
  1. package/dist/Badge/Badge.cjs +3 -2
  2. package/dist/Badge/Badge.d.ts +1 -1
  3. package/dist/Badge/Badge.js +4 -2
  4. package/dist/SideBar/SideBar.cjs +5 -2
  5. package/dist/SideBar/SideBar.d.ts +5 -1
  6. package/dist/SideBar/SideBar.js +5 -2
  7. package/dist/SideBar/SideBar.style.cjs +4 -4
  8. package/dist/SideBar/SideBar.style.d.ts +3 -3
  9. package/dist/SideBar/SideBar.style.js +4 -4
  10. package/dist/SideBar/SideBar.types.d.ts +1 -0
  11. package/dist/SideBar/components/Group/Group.cjs +7 -0
  12. package/dist/SideBar/components/Group/Group.d.ts +5 -0
  13. package/dist/SideBar/components/Group/Group.js +6 -0
  14. package/dist/SideBar/components/Group/Group.types.d.ts +2 -0
  15. package/dist/SideBar/components/Group/Group.types.js +1 -0
  16. package/dist/SideBar/components/Group/components/Title/Title.cjs +22 -0
  17. package/dist/SideBar/components/Group/components/Title/Title.d.ts +3 -0
  18. package/dist/SideBar/components/Group/components/Title/Title.js +21 -0
  19. package/dist/SideBar/components/Group/components/Title/Title.style.cjs +19 -0
  20. package/dist/SideBar/components/Group/components/Title/Title.style.d.ts +5 -0
  21. package/dist/SideBar/components/Group/components/Title/Title.style.js +16 -0
  22. package/dist/SideBar/components/Group/components/Title/Title.types.d.ts +4 -0
  23. package/dist/SideBar/components/Group/components/Title/Title.types.js +1 -0
  24. package/dist/SideBar/components/Item/Item.cjs +3 -1
  25. package/dist/SideBar/components/Item/Item.d.ts +1 -0
  26. package/dist/SideBar/components/Item/Item.js +3 -1
  27. package/dist/SideBar/components/Item/Item.style.cjs +6 -4
  28. package/dist/SideBar/components/Item/Item.style.js +6 -4
  29. package/dist/SideBar/components/Item/components/Badge/Badge.cjs +18 -0
  30. package/dist/SideBar/components/Item/components/Badge/Badge.d.ts +4 -0
  31. package/dist/SideBar/components/Item/components/Badge/Badge.js +16 -0
  32. package/dist/SideBar/components/Item/components/Badge/Badge.style.cjs +11 -0
  33. package/dist/SideBar/components/Item/components/Badge/Badge.style.d.ts +4 -0
  34. package/dist/SideBar/components/Item/components/Badge/Badge.style.js +9 -0
  35. package/dist/SideBar/components/Item/components/Button/Button.cjs +11 -4
  36. package/dist/SideBar/components/Item/components/Button/Button.js +11 -4
  37. package/dist/SideBar/components/Item/components/Button/Button.style.cjs +6 -1
  38. package/dist/SideBar/components/Item/components/Button/Button.style.d.ts +4 -1
  39. package/dist/SideBar/components/Item/components/Button/Button.style.js +6 -1
  40. package/dist/SideBar/components/Item/components/Text/Text.cjs +12 -6
  41. package/dist/SideBar/components/Item/components/Text/Text.js +12 -6
  42. package/dist/SideBar/components/Item/components/Text/Text.style.cjs +1 -5
  43. package/dist/SideBar/components/Item/components/Text/Text.style.d.ts +4 -1
  44. package/dist/SideBar/components/Item/components/Text/Text.style.js +1 -5
  45. package/dist/SideBar/components/ScrollContainer/ScrollContainer.style.cjs +1 -1
  46. package/dist/SideBar/components/ScrollContainer/ScrollContainer.style.js +1 -1
  47. package/package.json +2 -2
  48. package/skills/redis-ui-components/references/Badge.md +18 -0
  49. package/skills/redis-ui-components/references/SideBar.md +91 -5
@@ -4,10 +4,11 @@ const require_BadgeIcon = require("./BadgeIcon.cjs");
4
4
  const require_Badge_style = require("./Badge.style.cjs");
5
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
6
  //#region src/Badge/Badge.tsx
7
- var Badge = ({ label, variant = "default", color, withIcon, icon, ...restBadgeProps }) => {
7
+ var Badge = (0, require("react").forwardRef)(({ label, variant = "default", color, withIcon, icon, ...restBadgeProps }, ref) => {
8
8
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_Badge_style.Badge, {
9
9
  $variant: variant,
10
10
  $color: color,
11
+ ref,
11
12
  ...restBadgeProps,
12
13
  children: [withIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_BadgeIcon.BadgeIcon, {
13
14
  variant,
@@ -19,6 +20,6 @@ var Badge = ({ label, variant = "default", color, withIcon, icon, ...restBadgePr
19
20
  children: label
20
21
  })]
21
22
  });
22
- };
23
+ });
23
24
  //#endregion
24
25
  exports.default = Badge;
@@ -1,3 +1,3 @@
1
1
  import { BadgeProps } from './Badge.types';
2
- declare const Badge: ({ label, variant, color, withIcon, icon, ...restBadgeProps }: BadgeProps) => import("react/jsx-runtime").JSX.Element;
2
+ declare const Badge: import("react").ForwardRefExoticComponent<BadgeProps & import("react").RefAttributes<HTMLDivElement>>;
3
3
  export default Badge;
@@ -2,11 +2,13 @@ import Typography from "../Typography/Typography.js";
2
2
  import { BadgeIcon } from "./BadgeIcon.js";
3
3
  import { Badge as Badge$1 } from "./Badge.style.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { forwardRef } from "react";
5
6
  //#region src/Badge/Badge.tsx
6
- var Badge = ({ label, variant = "default", color, withIcon, icon, ...restBadgeProps }) => {
7
+ var Badge = forwardRef(({ label, variant = "default", color, withIcon, icon, ...restBadgeProps }, ref) => {
7
8
  return /* @__PURE__ */ jsxs(Badge$1, {
8
9
  $variant: variant,
9
10
  $color: color,
11
+ ref,
10
12
  ...restBadgeProps,
11
13
  children: [withIcon && /* @__PURE__ */ jsx(BadgeIcon, {
12
14
  variant,
@@ -18,6 +20,6 @@ var Badge = ({ label, variant = "default", color, withIcon, icon, ...restBadgePr
18
20
  children: label
19
21
  })]
20
22
  });
21
- };
23
+ });
22
24
  //#endregion
23
25
  export { Badge as default };
@@ -12,12 +12,13 @@ const require_Button = require("./components/Button/Button.cjs");
12
12
  const require_Header = require("./components/Header/Header.cjs");
13
13
  const require_ScrollContainer = require("./components/ScrollContainer/ScrollContainer.cjs");
14
14
  const require_Footer = require("./components/Footer/Footer.cjs");
15
+ const require_Group = require("./components/Group/Group.cjs");
15
16
  const require_SideBarThemeProvider = require("./SideBarThemeProvider.cjs");
16
17
  let _redislabsdev_redis_ui_styles = require("@redislabsdev/redis-ui-styles");
17
18
  let react_jsx_runtime = require("react/jsx-runtime");
18
19
  let react = require("react");
19
20
  //#region src/SideBar/SideBar.tsx
20
- var SideBar = Object.assign(({ isExpanded, ...rest }) => {
21
+ var SideBar = Object.assign(({ isExpanded, expandedWidth, ...rest }) => {
21
22
  const [transitionEnd, setTransitionEnd] = (0, react.useState)(true);
22
23
  const prefersReducedMotion = (0, _redislabsdev_redis_ui_styles.usePrefersReducedMotion)();
23
24
  const sidebarId = require_index.useId();
@@ -40,6 +41,7 @@ var SideBar = Object.assign(({ isExpanded, ...rest }) => {
40
41
  "data-state": isExpanded ? "expanded" : "collapsed",
41
42
  "data-transition": transitionEnd ? "inactive" : "active",
42
43
  "data-role": "nav-bar",
44
+ $expandedWidth: expandedWidth,
43
45
  ...rest
44
46
  }) })
45
47
  }) });
@@ -52,7 +54,8 @@ var SideBar = Object.assign(({ isExpanded, ...rest }) => {
52
54
  Item: require_Item.default,
53
55
  Button: require_Button.default,
54
56
  Header: require_Header.default,
55
- Footer: require_Footer.default
57
+ Footer: require_Footer.default,
58
+ Group: require_Group.default
56
59
  });
57
60
  //#endregion
58
61
  exports.default = SideBar;
@@ -1,5 +1,5 @@
1
1
  import { SideBarProps } from './SideBar.types';
2
- declare const SideBar: (({ isExpanded, ...rest }: SideBarProps) => import("react/jsx-runtime").JSX.Element) & {
2
+ declare const SideBar: (({ isExpanded, expandedWidth, ...rest }: SideBarProps) => import("react/jsx-runtime").JSX.Element) & {
3
3
  SideBarLogo: ({ logoIcon: LogoIcon, ...restProps }: import("./components/SideBarLogo/SideBarLogo.types").SideBarLogoProps) => import("react/jsx-runtime").JSX.Element;
4
4
  ItemsContainer: (props: import("./components/ItemsContainer/ItemsContainer.types").SideBarItemsContainerProps) => import("react/jsx-runtime").JSX.Element;
5
5
  ScrollContainer: (props: import("./components/ScrollContainer/ScrollContainer.types").SideBarScrollContainerProps) => import("react/jsx-runtime").JSX.Element;
@@ -9,6 +9,7 @@ declare const SideBar: (({ isExpanded, ...rest }: SideBarProps) => import("react
9
9
  Icon: ({ icon: ItemIcon, ...restProps }: import("./components/Item/components/Icon/Icon.types").SideBarItemIconProps) => import("react/jsx-runtime").JSX.Element;
10
10
  Text: (props: import("./components/Item/components/Text/Text.types").SideBarItemTextProps) => import("react/jsx-runtime").JSX.Element;
11
11
  Button: import("react").ForwardRefExoticComponent<import("..").ActionIconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
12
+ Badge: import("react").ForwardRefExoticComponent<import("..").BadgeProps & import("react").RefAttributes<HTMLDivElement>>;
12
13
  };
13
14
  Button: ({ tooltipProps: { text: tooltipText, placement, ...tooltipProps }, buttonExpandedContent, buttonCollapsedIcon: ButtonCollapsedIcon, ...rest }: import("./components/Button/Button.types").SideBarButtonProps) => import("react/jsx-runtime").JSX.Element;
14
15
  Header: ({ children, onToggle, ...rest }: import("./components/Header/Header.types").SideBarHeaderProps) => import("react/jsx-runtime").JSX.Element;
@@ -17,5 +18,8 @@ declare const SideBar: (({ isExpanded, ...rest }: SideBarProps) => import("react
17
18
  Link: ({ children, ...rest }: import("./components/Footer/components/Link/Link.types").LinkProps) => import("react/jsx-runtime").JSX.Element;
18
19
  Text: (props: import("./components/Footer/components/Text/Text.types").TextProps) => import("react/jsx-runtime").JSX.Element;
19
20
  };
21
+ Group: ((props: import("./components/Group/Group.types").SideBarGroupProps) => import("react/jsx-runtime").JSX.Element) & {
22
+ Title: ({ children, ...rest }: import("./components/Group/components/Title/Title.types").SideBarGroupTitleProps) => import("react/jsx-runtime").JSX.Element;
23
+ };
20
24
  };
21
25
  export default SideBar;
@@ -11,12 +11,13 @@ import Button from "./components/Button/Button.js";
11
11
  import Header from "./components/Header/Header.js";
12
12
  import ScrollContainer from "./components/ScrollContainer/ScrollContainer.js";
13
13
  import Footer from "./components/Footer/Footer.js";
14
+ import Group from "./components/Group/Group.js";
14
15
  import { SideBarThemeProvider } from "./SideBarThemeProvider.js";
15
16
  import { usePrefersReducedMotion } from "@redislabsdev/redis-ui-styles";
16
17
  import { jsx } from "react/jsx-runtime";
17
18
  import { useState } from "react";
18
19
  //#region src/SideBar/SideBar.tsx
19
- var SideBar = Object.assign(({ isExpanded, ...rest }) => {
20
+ var SideBar = Object.assign(({ isExpanded, expandedWidth, ...rest }) => {
20
21
  const [transitionEnd, setTransitionEnd] = useState(true);
21
22
  const prefersReducedMotion = usePrefersReducedMotion();
22
23
  const sidebarId = useId();
@@ -39,6 +40,7 @@ var SideBar = Object.assign(({ isExpanded, ...rest }) => {
39
40
  "data-state": isExpanded ? "expanded" : "collapsed",
40
41
  "data-transition": transitionEnd ? "inactive" : "active",
41
42
  "data-role": "nav-bar",
43
+ $expandedWidth: expandedWidth,
42
44
  ...rest
43
45
  }) })
44
46
  }) });
@@ -51,7 +53,8 @@ var SideBar = Object.assign(({ isExpanded, ...rest }) => {
51
53
  Item,
52
54
  Button,
53
55
  Header,
54
- Footer
56
+ Footer,
57
+ Group
55
58
  });
56
59
  //#endregion
57
60
  export { SideBar as default };
@@ -11,20 +11,20 @@ var useRootStateStyle = (getStyle) => {
11
11
  const { expanded, collapsed } = (0, _redislabsdev_redis_ui_styles.useTheme)().components.sideBar;
12
12
  return styled_components.css`
13
13
  &[data-state='collapsed'] {
14
- ${getStyle(collapsed)}
14
+ ${getStyle(collapsed, "collapsed")}
15
15
  }
16
16
  &[data-state='expanded'] {
17
- ${getStyle(expanded)}
17
+ ${getStyle(expanded, "expanded")}
18
18
  }
19
19
  `;
20
20
  };
21
21
  var SideBarContainer = (0, styled_components.default)(require_FlexGroup.FlexGroup).withConfig({
22
22
  displayName: "SideBarstyle__SideBarContainer",
23
23
  componentId: "RedisUI__sc-suwica-0"
24
- })(["position:relative;height:100%;transition:width 0.6s;@media (prefers-reduced-motion:reduce){transition:none;}", ""], () => useRootStateStyle((theme) => styled_components.css`
24
+ })(["position:relative;height:100%;transition:width 0.6s;@media (prefers-reduced-motion:reduce){transition:none;}", ""], ({ $expandedWidth }) => useRootStateStyle((theme, state) => styled_components.css`
25
25
  box-shadow: ${theme.shadow};
26
26
  background-color: ${theme.bgColor};
27
- width: ${theme.width};
27
+ width: ${(state === "expanded" ? $expandedWidth : void 0) ?? theme.width};
28
28
  border-right: ${theme.borderRight};
29
29
  `));
30
30
  //#endregion
@@ -1,3 +1,3 @@
1
- import { ThemeProps } from 'styled-components/macro';
2
- import { Theme } from '@redislabsdev/redis-ui-styles';
3
- export declare const SideBarContainer: import("styled-components").StyledComponent<({ gap, direction, align, justify, wrap, ...restProps }: import("../Layouts").FlexGroupProps) => import("react/jsx-runtime").JSX.Element, any, ThemeProps<Theme>, never>;
1
+ export declare const SideBarContainer: import("styled-components").StyledComponent<({ gap, direction, align, justify, wrap, ...restProps }: import("../Layouts").FlexGroupProps) => import("react/jsx-runtime").JSX.Element, any, {
2
+ $expandedWidth?: string;
3
+ }, never>;
@@ -9,20 +9,20 @@ var useRootStateStyle = (getStyle) => {
9
9
  const { expanded, collapsed } = useTheme().components.sideBar;
10
10
  return css`
11
11
  &[data-state='collapsed'] {
12
- ${getStyle(collapsed)}
12
+ ${getStyle(collapsed, "collapsed")}
13
13
  }
14
14
  &[data-state='expanded'] {
15
- ${getStyle(expanded)}
15
+ ${getStyle(expanded, "expanded")}
16
16
  }
17
17
  `;
18
18
  };
19
19
  var SideBarContainer = _styled(FlexGroup).withConfig({
20
20
  displayName: "SideBarstyle__SideBarContainer",
21
21
  componentId: "RedisUI__sc-suwica-0"
22
- })(["position:relative;height:100%;transition:width 0.6s;@media (prefers-reduced-motion:reduce){transition:none;}", ""], () => useRootStateStyle((theme) => css`
22
+ })(["position:relative;height:100%;transition:width 0.6s;@media (prefers-reduced-motion:reduce){transition:none;}", ""], ({ $expandedWidth }) => useRootStateStyle((theme, state) => css`
23
23
  box-shadow: ${theme.shadow};
24
24
  background-color: ${theme.bgColor};
25
- width: ${theme.width};
25
+ width: ${(state === "expanded" ? $expandedWidth : void 0) ?? theme.width};
26
26
  border-right: ${theme.borderRight};
27
27
  `));
28
28
  //#endregion
@@ -2,6 +2,7 @@ import { TooltipContentProps } from '../Tooltip/components/Content/Content.types
2
2
  import { FlexGroupProps } from '../Layouts';
3
3
  export interface SideBarProps extends Omit<FlexGroupProps, 'direction'> {
4
4
  isExpanded: boolean;
5
+ expandedWidth?: string;
5
6
  }
6
7
  export interface SideBarContextProps {
7
8
  isExpanded: boolean;
@@ -0,0 +1,7 @@
1
+ require("../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_Title = require("./components/Title/Title.cjs");
3
+ let react_jsx_runtime = require("react/jsx-runtime");
4
+ //#region src/SideBar/components/Group/Group.tsx
5
+ var Group = Object.assign((props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ...props }), { Title: require_Title.default });
6
+ //#endregion
7
+ exports.default = Group;
@@ -0,0 +1,5 @@
1
+ import { SideBarGroupProps } from './Group.types';
2
+ declare const Group: ((props: SideBarGroupProps) => import("react/jsx-runtime").JSX.Element) & {
3
+ Title: ({ children, ...rest }: import("./components/Title/Title.types").SideBarGroupTitleProps) => import("react/jsx-runtime").JSX.Element;
4
+ };
5
+ export default Group;
@@ -0,0 +1,6 @@
1
+ import Title from "./components/Title/Title.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/SideBar/components/Group/Group.tsx
4
+ var Group = Object.assign((props) => /* @__PURE__ */ jsx("div", { ...props }), { Title });
5
+ //#endregion
6
+ export { Group as default };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export type SideBarGroupProps = React.HTMLAttributes<HTMLDivElement>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,22 @@
1
+ require("../../../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_SideBar_context = require("../../../../SideBar.context.cjs");
3
+ const require_Title_style = require("./Title.style.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ //#region src/SideBar/components/Group/components/Title/Title.tsx
6
+ var Title = ({ children, ...rest }) => {
7
+ const { isExpanded, transitionEnd } = require_SideBar_context.useSideBarContext();
8
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Title_style.Container, {
9
+ ...rest,
10
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Title_style.Label, {
11
+ size: "M",
12
+ variant: "semiBold",
13
+ color: "secondary",
14
+ component: "span",
15
+ $isExpanded: isExpanded,
16
+ $transitionEnd: transitionEnd,
17
+ children
18
+ })
19
+ });
20
+ };
21
+ //#endregion
22
+ exports.default = Title;
@@ -0,0 +1,3 @@
1
+ import { SideBarGroupTitleProps } from './Title.types';
2
+ declare const Title: ({ children, ...rest }: SideBarGroupTitleProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default Title;
@@ -0,0 +1,21 @@
1
+ import { useSideBarContext } from "../../../../SideBar.context.js";
2
+ import { Container, Label } from "./Title.style.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/SideBar/components/Group/components/Title/Title.tsx
5
+ var Title = ({ children, ...rest }) => {
6
+ const { isExpanded, transitionEnd } = useSideBarContext();
7
+ return /* @__PURE__ */ jsx(Container, {
8
+ ...rest,
9
+ children: /* @__PURE__ */ jsx(Label, {
10
+ size: "M",
11
+ variant: "semiBold",
12
+ color: "secondary",
13
+ component: "span",
14
+ $isExpanded: isExpanded,
15
+ $transitionEnd: transitionEnd,
16
+ children
17
+ })
18
+ });
19
+ };
20
+ //#endregion
21
+ export { Title as default };
@@ -0,0 +1,19 @@
1
+ const require_runtime = require("../../../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_Typography = require("../../../../../Typography/Typography.cjs");
3
+ const require_SideBar_utils = require("../../../../SideBar.utils.cjs");
4
+ let styled_components = require("styled-components");
5
+ styled_components = require_runtime.__toESM(styled_components, 1);
6
+ //#region src/SideBar/components/Group/components/Title/Title.style.ts
7
+ var Container = styled_components.default.div.withConfig({
8
+ displayName: "Titlestyle__Container",
9
+ componentId: "RedisUI__sc-1qd2bt1-0"
10
+ })(["display:block;overflow:hidden;", ""], () => require_SideBar_utils.useStateStyle((theme) => styled_components.css`
11
+ padding: ${theme.groupTitle.padding};
12
+ `));
13
+ var Label = (0, styled_components.default)(require_Typography.default.Body).withConfig({
14
+ displayName: "Titlestyle__Label",
15
+ componentId: "RedisUI__sc-1qd2bt1-1"
16
+ })(["display:block;white-space:nowrap;transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
17
+ //#endregion
18
+ exports.Container = Container;
19
+ exports.Label = Label;
@@ -0,0 +1,5 @@
1
+ export declare const Container: import("styled-components").StyledComponent<"div", any, {}, never>;
2
+ export declare const Label: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../../Typography").TypographyBodyProps & import("react").RefAttributes<HTMLElement>>, any, {
3
+ $isExpanded: boolean;
4
+ $transitionEnd: boolean;
5
+ }, never>;
@@ -0,0 +1,16 @@
1
+ import Typography from "../../../../../Typography/Typography.js";
2
+ import { useStateStyle } from "../../../../SideBar.utils.js";
3
+ import _styled, { css } from "styled-components";
4
+ //#region src/SideBar/components/Group/components/Title/Title.style.ts
5
+ var Container = _styled.div.withConfig({
6
+ displayName: "Titlestyle__Container",
7
+ componentId: "RedisUI__sc-1qd2bt1-0"
8
+ })(["display:block;overflow:hidden;", ""], () => useStateStyle((theme) => css`
9
+ padding: ${theme.groupTitle.padding};
10
+ `));
11
+ var Label = _styled(Typography.Body).withConfig({
12
+ displayName: "Titlestyle__Label",
13
+ componentId: "RedisUI__sc-1qd2bt1-1"
14
+ })(["display:block;white-space:nowrap;transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
15
+ //#endregion
16
+ export { Container, Label };
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export interface SideBarGroupTitleProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
3
+ children: React.ReactNode;
4
+ }
@@ -4,6 +4,7 @@ const require_SideBar_context = require("../../SideBar.context.cjs");
4
4
  const require_Icon = require("./components/Icon/Icon.cjs");
5
5
  const require_Text = require("./components/Text/Text.cjs");
6
6
  const require_Button = require("./components/Button/Button.cjs");
7
+ const require_Badge = require("./components/Badge/Badge.cjs");
7
8
  const require_Item_style = require("./Item.style.cjs");
8
9
  let react_jsx_runtime = require("react/jsx-runtime");
9
10
  let react = require("react");
@@ -39,7 +40,8 @@ var Item = Object.assign(({ tooltipProps, isActive = false, onKeyDown, ...restPr
39
40
  }, {
40
41
  Icon: require_Icon.default,
41
42
  Text: require_Text.default,
42
- Button: require_Button.default
43
+ Button: require_Button.default,
44
+ Badge: require_Badge.default
43
45
  });
44
46
  //#endregion
45
47
  exports.default = Item;
@@ -3,5 +3,6 @@ declare const Item: (({ tooltipProps, isActive, onKeyDown, ...restProps }: SideB
3
3
  Icon: ({ icon: ItemIcon, ...restProps }: import("./components/Icon/Icon.types").SideBarItemIconProps) => import("react/jsx-runtime").JSX.Element;
4
4
  Text: (props: import("./components/Text/Text.types").SideBarItemTextProps) => import("react/jsx-runtime").JSX.Element;
5
5
  Button: import("react").ForwardRefExoticComponent<import("../../..").ActionIconButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
6
+ Badge: import("react").ForwardRefExoticComponent<import("../../..").BadgeProps & import("react").RefAttributes<HTMLDivElement>>;
6
7
  };
7
8
  export default Item;
@@ -3,6 +3,7 @@ import { useSideBarContext } from "../../SideBar.context.js";
3
3
  import Icon from "./components/Icon/Icon.js";
4
4
  import Text from "./components/Text/Text.js";
5
5
  import Button from "./components/Button/Button.js";
6
+ import Badge from "./components/Badge/Badge.js";
6
7
  import { SideBarItem, TooltipContent } from "./Item.style.js";
7
8
  import { jsx } from "react/jsx-runtime";
8
9
  import { useRef } from "react";
@@ -38,7 +39,8 @@ var Item = Object.assign(({ tooltipProps, isActive = false, onKeyDown, ...restPr
38
39
  }, {
39
40
  Icon,
40
41
  Text,
41
- Button
42
+ Button,
43
+ Badge
42
44
  });
43
45
  //#endregion
44
46
  export { Item as default };
@@ -17,13 +17,15 @@ var SideBarItem = styled_components.default.li.withConfig({
17
17
  ";}",
18
18
  ";& > svg{transition:inherit;}"
19
19
  ], () => (0, _redislabsdev_redis_ui_styles.useTheme)().core.focus.size, () => (0, _redislabsdev_redis_ui_styles.useTheme)().core.focus.color, () => (0, _redislabsdev_redis_ui_styles.useTheme)().core.focus.size, () => {
20
- return require_SideBar_utils.useStateStyle(({ item: theme }) => {
20
+ return require_SideBar_utils.useStateStyle(({ item: theme }, state) => {
21
21
  const { states } = theme;
22
22
  return styled_components.css`
23
23
  margin: ${theme.margin};
24
- :has(> button) {
25
- margin-inline-end: ${theme.itemWithButtonOffset};
26
- }
24
+ ${state === "expanded" && styled_components.css`
25
+ :has(> button) {
26
+ margin-inline-end: ${theme.itemWithButtonOffset};
27
+ }
28
+ `}
27
29
  height: ${theme.height};
28
30
  padding: ${theme.padding};
29
31
  border-radius: ${theme.borderRadius};
@@ -15,13 +15,15 @@ var SideBarItem = _styled.li.withConfig({
15
15
  ";}",
16
16
  ";& > svg{transition:inherit;}"
17
17
  ], () => useTheme().core.focus.size, () => useTheme().core.focus.color, () => useTheme().core.focus.size, () => {
18
- return useStateStyle(({ item: theme }) => {
18
+ return useStateStyle(({ item: theme }, state) => {
19
19
  const { states } = theme;
20
20
  return css`
21
21
  margin: ${theme.margin};
22
- :has(> button) {
23
- margin-inline-end: ${theme.itemWithButtonOffset};
24
- }
22
+ ${state === "expanded" && css`
23
+ :has(> button) {
24
+ margin-inline-end: ${theme.itemWithButtonOffset};
25
+ }
26
+ `}
25
27
  height: ${theme.height};
26
28
  padding: ${theme.padding};
27
29
  border-radius: ${theme.borderRadius};
@@ -0,0 +1,18 @@
1
+ const require_runtime = require("../../../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_SideBar_context = require("../../../../SideBar.context.cjs");
3
+ const require_Badge_style = require("./Badge.style.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ let react = require("react");
6
+ react = require_runtime.__toESM(react, 1);
7
+ //#region src/SideBar/components/Item/components/Badge/Badge.tsx
8
+ var Badge = react.default.forwardRef((props, ref) => {
9
+ const { isExpanded, transitionEnd } = require_SideBar_context.useSideBarContext();
10
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Badge_style.Badge, {
11
+ ref,
12
+ $isExpanded: isExpanded,
13
+ $transitionEnd: transitionEnd,
14
+ ...props
15
+ });
16
+ });
17
+ //#endregion
18
+ exports.default = Badge;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { BadgeProps } from '../../../../../Badge/Badge.types';
3
+ declare const Badge: React.ForwardRefExoticComponent<BadgeProps & React.RefAttributes<HTMLDivElement>>;
4
+ export default Badge;
@@ -0,0 +1,16 @@
1
+ import { useSideBarContext } from "../../../../SideBar.context.js";
2
+ import { Badge as Badge$1 } from "./Badge.style.js";
3
+ import { jsx } from "react/jsx-runtime";
4
+ import React from "react";
5
+ //#region src/SideBar/components/Item/components/Badge/Badge.tsx
6
+ var Badge = React.forwardRef((props, ref) => {
7
+ const { isExpanded, transitionEnd } = useSideBarContext();
8
+ return /* @__PURE__ */ jsx(Badge$1, {
9
+ ref,
10
+ $isExpanded: isExpanded,
11
+ $transitionEnd: transitionEnd,
12
+ ...props
13
+ });
14
+ });
15
+ //#endregion
16
+ export { Badge as default };
@@ -0,0 +1,11 @@
1
+ const require_runtime = require("../../../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_Badge = require("../../../../../Badge/Badge.cjs");
3
+ let styled_components = require("styled-components");
4
+ styled_components = require_runtime.__toESM(styled_components, 1);
5
+ //#region src/SideBar/components/Item/components/Badge/Badge.style.ts
6
+ var Badge = (0, styled_components.default)(require_Badge.default).withConfig({
7
+ displayName: "Badgestyle__Badge",
8
+ componentId: "RedisUI__sc-am1mdr-0"
9
+ })(["margin-inline-start:auto;transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
10
+ //#endregion
11
+ exports.Badge = Badge;
@@ -0,0 +1,4 @@
1
+ export declare const Badge: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../..").BadgeProps & import("react").RefAttributes<HTMLDivElement>>, any, {
2
+ $isExpanded: boolean;
3
+ $transitionEnd: boolean;
4
+ }, never>;
@@ -0,0 +1,9 @@
1
+ import Badge$1 from "../../../../../Badge/Badge.js";
2
+ import _styled from "styled-components";
3
+ //#region src/SideBar/components/Item/components/Badge/Badge.style.ts
4
+ var Badge = _styled(Badge$1).withConfig({
5
+ displayName: "Badgestyle__Badge",
6
+ componentId: "RedisUI__sc-am1mdr-0"
7
+ })(["margin-inline-start:auto;transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
8
+ //#endregion
9
+ export { Badge };
@@ -6,12 +6,19 @@ let react = require("react");
6
6
  react = require_runtime.__toESM(react, 1);
7
7
  //#region src/SideBar/components/Item/components/Button/Button.tsx
8
8
  var Button = react.default.forwardRef(({ size = "M", ...props }, ref) => {
9
- const { isExpanded } = require_SideBar_context.useSideBarContext();
10
- return isExpanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button_style.SideBarItemButton, {
9
+ const { isExpanded, transitionEnd } = require_SideBar_context.useSideBarContext();
10
+ const isHidden = !isExpanded || !transitionEnd;
11
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Button_style.SideBarItemButton, {
11
12
  size,
12
13
  ref,
13
- ...props
14
- }) : null;
14
+ $isExpanded: isExpanded,
15
+ $transitionEnd: transitionEnd,
16
+ ...props,
17
+ ...isHidden && {
18
+ tabIndex: -1,
19
+ "aria-hidden": true
20
+ }
21
+ });
15
22
  });
16
23
  //#endregion
17
24
  exports.default = Button;
@@ -4,12 +4,19 @@ import { jsx } from "react/jsx-runtime";
4
4
  import React from "react";
5
5
  //#region src/SideBar/components/Item/components/Button/Button.tsx
6
6
  var Button = React.forwardRef(({ size = "M", ...props }, ref) => {
7
- const { isExpanded } = useSideBarContext();
8
- return isExpanded ? /* @__PURE__ */ jsx(SideBarItemButton, {
7
+ const { isExpanded, transitionEnd } = useSideBarContext();
8
+ const isHidden = !isExpanded || !transitionEnd;
9
+ return /* @__PURE__ */ jsx(SideBarItemButton, {
9
10
  size,
10
11
  ref,
11
- ...props
12
- }) : null;
12
+ $isExpanded: isExpanded,
13
+ $transitionEnd: transitionEnd,
14
+ ...props,
15
+ ...isHidden && {
16
+ tabIndex: -1,
17
+ "aria-hidden": true
18
+ }
19
+ });
13
20
  });
14
21
  //#endregion
15
22
  export { Button as default };
@@ -7,7 +7,12 @@ styled_components = require_runtime.__toESM(styled_components, 1);
7
7
  var SideBarItemButton = (0, styled_components.default)(require_ActionIconButton.default).withConfig({
8
8
  displayName: "Buttonstyle__SideBarItemButton",
9
9
  componentId: "RedisUI__sc-13x3wha-0"
10
- })(["position:absolute;padding:0;right:0;transform:translateX(50%);", ""], () => require_SideBar_utils.useStateStyle((theme) => styled_components.css`
10
+ })([
11
+ "position:absolute;padding:0;right:0;transform:translateX(50%);transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:",
12
+ ";pointer-events:",
13
+ ";",
14
+ ""
15
+ ], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0", ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "auto" : "none", () => require_SideBar_utils.useStateStyle((theme) => styled_components.css`
11
16
  background-color: ${theme.item.button.bgColor};
12
17
  border-color: ${theme.item.button.borderColor};
13
18
  border-width: ${theme.item.button.borderSize};
@@ -1 +1,4 @@
1
- export declare const SideBarItemButton: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../..").ActionIconButtonProps & import("react").RefAttributes<HTMLButtonElement>>, any, {}, never>;
1
+ export declare const SideBarItemButton: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../..").ActionIconButtonProps & import("react").RefAttributes<HTMLButtonElement>>, any, {
2
+ $isExpanded: boolean;
3
+ $transitionEnd: boolean;
4
+ }, never>;
@@ -5,7 +5,12 @@ import _styled, { css } from "styled-components";
5
5
  var SideBarItemButton = _styled(ActionIconButton).withConfig({
6
6
  displayName: "Buttonstyle__SideBarItemButton",
7
7
  componentId: "RedisUI__sc-13x3wha-0"
8
- })(["position:absolute;padding:0;right:0;transform:translateX(50%);", ""], () => useStateStyle((theme) => css`
8
+ })([
9
+ "position:absolute;padding:0;right:0;transform:translateX(50%);transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:",
10
+ ";pointer-events:",
11
+ ";",
12
+ ""
13
+ ], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0", ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "auto" : "none", () => useStateStyle((theme) => css`
9
14
  background-color: ${theme.item.button.bgColor};
10
15
  border-color: ${theme.item.button.borderColor};
11
16
  border-width: ${theme.item.button.borderSize};
@@ -1,12 +1,18 @@
1
1
  require("../../../../../_virtual/_rolldown/runtime.cjs");
2
+ const require_SideBar_context = require("../../../../SideBar.context.cjs");
2
3
  const require_Text_style = require("./Text.style.cjs");
3
4
  let react_jsx_runtime = require("react/jsx-runtime");
4
5
  //#region src/SideBar/components/Item/components/Text/Text.tsx
5
- var Text = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Text_style.SideBarItemText, {
6
- ellipsis: true,
7
- tooltipOnEllipsis: true,
8
- component: "span",
9
- ...props
10
- });
6
+ var Text = (props) => {
7
+ const { isExpanded, transitionEnd } = require_SideBar_context.useSideBarContext();
8
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Text_style.SideBarItemText, {
9
+ ellipsis: true,
10
+ tooltipOnEllipsis: true,
11
+ component: "span",
12
+ $isExpanded: isExpanded,
13
+ $transitionEnd: transitionEnd,
14
+ ...props
15
+ });
16
+ };
11
17
  //#endregion
12
18
  exports.default = Text;
@@ -1,11 +1,17 @@
1
+ import { useSideBarContext } from "../../../../SideBar.context.js";
1
2
  import { SideBarItemText } from "./Text.style.js";
2
3
  import { jsx } from "react/jsx-runtime";
3
4
  //#region src/SideBar/components/Item/components/Text/Text.tsx
4
- var Text = (props) => /* @__PURE__ */ jsx(SideBarItemText, {
5
- ellipsis: true,
6
- tooltipOnEllipsis: true,
7
- component: "span",
8
- ...props
9
- });
5
+ var Text = (props) => {
6
+ const { isExpanded, transitionEnd } = useSideBarContext();
7
+ return /* @__PURE__ */ jsx(SideBarItemText, {
8
+ ellipsis: true,
9
+ tooltipOnEllipsis: true,
10
+ component: "span",
11
+ $isExpanded: isExpanded,
12
+ $transitionEnd: transitionEnd,
13
+ ...props
14
+ });
15
+ };
10
16
  //#endregion
11
17
  export { Text as default };
@@ -1,15 +1,11 @@
1
1
  const require_runtime = require("../../../../../_virtual/_rolldown/runtime.cjs");
2
2
  const require_Typography = require("../../../../../Typography/Typography.cjs");
3
- const require_SideBar_context = require("../../../../SideBar.context.cjs");
4
3
  let styled_components = require("styled-components");
5
4
  styled_components = require_runtime.__toESM(styled_components, 1);
6
5
  //#region src/SideBar/components/Item/components/Text/Text.style.ts
7
6
  var SideBarItemText = (0, styled_components.default)(require_Typography.default.Body).withConfig({
8
7
  displayName: "Textstyle__SideBarItemText",
9
8
  componentId: "RedisUI__sc-17tjfvd-0"
10
- })(["transition:width 0.6s,opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], () => {
11
- const { isExpanded, transitionEnd } = require_SideBar_context.useSideBarContext();
12
- return isExpanded && transitionEnd ? "1" : "0";
13
- });
9
+ })(["transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
14
10
  //#endregion
15
11
  exports.SideBarItemText = SideBarItemText;
@@ -1 +1,4 @@
1
- export declare const SideBarItemText: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../../Typography").TypographyBodyProps & import("react").RefAttributes<HTMLElement>>, any, {}, never>;
1
+ export declare const SideBarItemText: import("styled-components").StyledComponent<import("react").ForwardRefExoticComponent<import("../../../../../Typography").TypographyBodyProps & import("react").RefAttributes<HTMLElement>>, any, {
2
+ $isExpanded: boolean;
3
+ $transitionEnd: boolean;
4
+ }, never>;
@@ -1,13 +1,9 @@
1
1
  import Typography from "../../../../../Typography/Typography.js";
2
- import { useSideBarContext } from "../../../../SideBar.context.js";
3
2
  import _styled from "styled-components";
4
3
  //#region src/SideBar/components/Item/components/Text/Text.style.ts
5
4
  var SideBarItemText = _styled(Typography.Body).withConfig({
6
5
  displayName: "Textstyle__SideBarItemText",
7
6
  componentId: "RedisUI__sc-17tjfvd-0"
8
- })(["transition:width 0.6s,opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], () => {
9
- const { isExpanded, transitionEnd } = useSideBarContext();
10
- return isExpanded && transitionEnd ? "1" : "0";
11
- });
7
+ })(["transition:opacity 0.4s;@media (prefers-reduced-motion:reduce){transition:none;}opacity:", ";"], ({ $isExpanded, $transitionEnd }) => $isExpanded && $transitionEnd ? "1" : "0");
12
8
  //#endregion
13
9
  export { SideBarItemText };
@@ -6,6 +6,6 @@ styled_components = require_runtime.__toESM(styled_components, 1);
6
6
  var ScrollContainer = (0, styled_components.default)(require_FlexGroup.FlexGroup).withConfig({
7
7
  displayName: "ScrollContainerstyle__ScrollContainer",
8
8
  componentId: "RedisUI__sc-15iez38-0"
9
- })(["overflow-y:auto;"]);
9
+ })(["overflow-y:auto;overflow-x:hidden;"]);
10
10
  //#endregion
11
11
  exports.ScrollContainer = ScrollContainer;
@@ -4,6 +4,6 @@ import _styled from "styled-components";
4
4
  var ScrollContainer = _styled(FlexGroup).withConfig({
5
5
  displayName: "ScrollContainerstyle__ScrollContainer",
6
6
  componentId: "RedisUI__sc-15iez38-0"
7
- })(["overflow-y:auto;"]);
7
+ })(["overflow-y:auto;overflow-x:hidden;"]);
8
8
  //#endregion
9
9
  export { ScrollContainer };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@redis-ui/components",
3
3
  "license": "UNLICENSED",
4
- "version": "47.0.0",
4
+ "version": "47.1.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "repository": "git@github.com:redislabsdev/redis-ui.git",
@@ -30,7 +30,7 @@
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@redis-ui/icons": "^8.0.0",
33
- "@redis-ui/styles": "^16.0.0",
33
+ "@redis-ui/styles": "^16.2.0",
34
34
  "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
35
35
  "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
36
36
  "styled-components": "^5.0.0"
@@ -8,6 +8,12 @@ Compact status badge with variant-based coloring and optional icons.
8
8
  import { Badge } from '@redis-ui/components';
9
9
  ```
10
10
 
11
+ For tooltip examples:
12
+
13
+ ```tsx
14
+ import { Badge, Tooltip } from '@redis-ui/components';
15
+ ```
16
+
11
17
  If you pass a custom icon in examples, import it from `@redis-ui/icons`.
12
18
 
13
19
  ## Props
@@ -41,6 +47,16 @@ import { Badge } from '@redis-ui/components';
41
47
  <Badge label="Badge" withIcon color="#0366d6" />
42
48
  ```
43
49
 
50
+ ### WithTooltip
51
+
52
+ ```tsx
53
+ import { Badge, Tooltip } from '@redis-ui/components';
54
+
55
+ <Tooltip content="hello world">
56
+ <Badge label="New" variant="informative" withIcon tabIndex={0} />
57
+ </Tooltip>
58
+ ```
59
+
44
60
  ### Icons
45
61
 
46
62
  > `Badge` can be rendered with or without an icon using `withIcon`. Pass `icon` to customize the icon.
@@ -75,3 +91,5 @@ import { Badge, badgeVariants } from '@redis-ui/components';
75
91
  - `withIcon` uses the default icon for the selected variant when `icon` is not provided.
76
92
  - `variant` controls both the badge surface color and the default icon choice.
77
93
  - `color` overrides the badge accent color directly and is used instead of the theme variant color.
94
+ - `Badge` forwards refs to its root `HTMLDivElement`, so it can be used directly as a trigger for components such as `Tooltip`.
95
+ - When using `Badge` as a tooltip trigger, pass `tabIndex={0}` so keyboard users can focus the badge and open the tooltip.
@@ -1,6 +1,6 @@
1
1
  # SideBar
2
2
 
3
- Collapsible sidebar navigation with a header toggle, grouped items, scrollable middle content, and a footer area. The component is designed as a compound API so the header, items, splitters, and footer pieces can be composed as needed.
3
+ Collapsible sidebar navigation with a header toggle, grouped items, scrollable middle content, and a footer area. The component is designed as a compound API so the header, items, splitters, group titles, and footer pieces can be composed as needed.
4
4
 
5
5
  ## Import
6
6
 
@@ -13,6 +13,7 @@ import { SideBar } from '@redis-ui/components';
13
13
  | Prop | Type | Default | Description |
14
14
  |------|------|---------|-------------|
15
15
  | isExpanded | `boolean` | *required* | Controls whether the sidebar is expanded or collapsed |
16
+ | expandedWidth | `string` | theme value | Overrides the sidebar width when expanded (falls back to the theme's `sideBar.expanded.width`, e.g. `20rem` in the light theme) |
16
17
 
17
18
  The component also accepts all `FlexGroupProps` except `direction`, which is fixed to a vertical sidebar layout.
18
19
 
@@ -28,7 +29,10 @@ The component also accepts all `FlexGroupProps` except `direction`, which is fix
28
29
  - `SideBar.Item` - Navigation item with tooltip support when collapsed.
29
30
  - `SideBar.Item.Icon` - Icon slot for a sidebar item.
30
31
  - `SideBar.Item.Text` - Text slot for a sidebar item.
31
- - `SideBar.Item.Button` - Compact action button that is shown only when the sidebar is expanded.
32
+ - `SideBar.Item.Button` - Compact action button that stays mounted in the DOM and is visually hidden (fades out and becomes non-interactive) when the sidebar is collapsed.
33
+ - `SideBar.Item.Badge` - Badge slot rendered to the right of `Item.Text` (e.g. `NEW`, `BETA`). Stays mounted in the DOM and fades out when the sidebar is collapsed.
34
+ - `SideBar.Group` - Wrapper around a section's `Group.Title` and items. Use one `SideBar.Group` per logical section.
35
+ - `SideBar.Group.Title` - Section label rendered above a group of items. Visible when the sidebar is expanded; the row stays mounted (text fades out) when collapsed so items don't jump around during the transition.
32
36
  - `SideBar.Footer` - Footer wrapper for metadata, links, and text.
33
37
  - `SideBar.Footer.MetaData` - Footer metadata container.
34
38
  - `SideBar.Footer.Link` - Footer link rendered as body text.
@@ -90,7 +94,24 @@ This slot inherits `TypographyBodyProps`. It renders a `Typography.Body` element
90
94
 
91
95
  ### SideBar.Item.Button Props
92
96
 
93
- This slot inherits all `ActionIconButtonProps`, defaults `size` to `M`, and renders only while the sidebar is expanded.
97
+ This slot inherits all `ActionIconButtonProps` and defaults `size` to `M`. It stays mounted in the DOM in both states. When the sidebar is collapsed (or while the expand/collapse transition is running) it fades to `opacity: 0`, gets `pointer-events: none`, and is forced to `tabIndex={-1}` and `aria-hidden={true}` so it is removed from the normal tab order and hidden from assistive tech while hidden. Consumer-provided `tabIndex` and `aria-hidden` are intentionally overridden in this state.
98
+
99
+ ### SideBar.Item.Badge Props
100
+
101
+ This slot inherits all `BadgeProps` from the base `Badge` component. The badge stays in the DOM in both states; when the sidebar is collapsed (or while the expand/collapse transition is running) it fades to `opacity: 0`, so consumers don't need to gate it themselves.
102
+
103
+ ### SideBar.Group Props
104
+
105
+ This wrapper accepts standard `HTMLAttributes<HTMLDivElement>`. Place a `SideBar.Group.Title` and the section's items inside.
106
+
107
+ ### SideBar.Group.Title Props
108
+
109
+ | Prop | Type | Default | Description |
110
+ |------|------|---------|-------------|
111
+ | children | `React.ReactNode` | *required* | Title text shown above the group of items |
112
+
113
+ The group title also accepts standard `HTMLAttributes<HTMLDivElement>` except `children`.
114
+ The label is rendered as a `Typography.Body` (size `M`, `semiBold`, `secondary` color, `span` element). When the sidebar is collapsed, the row stays in the DOM with its theme-driven padding so the items below don't jump, and the label fades to `opacity: 0` once the expand/collapse transition completes (mirroring the `SideBar.Item.Text` pattern).
94
115
 
95
116
  ### SideBar.Button Props
96
117
 
@@ -249,6 +270,68 @@ const [activeLink, setActiveLink] = useState(items.top[0].content);
249
270
  </SideBar>
250
271
  ```
251
272
 
273
+ ### Groups
274
+
275
+ > Sidebar items split into groups, each with a title label. When the sidebar is expanded, the group title is shown above its items; when collapsed, the title row stays mounted but the label fades out so the items below don't jump during the expand/collapse transition.
276
+ >
277
+ > A group with no title omits the `SideBar.Group.Title` element entirely, as shown by the first group below. Items inside a group may also render an optional `SideBar.Item.Badge` (e.g. `NEW`, `BETA`) to the right of the text — it stays mounted and fades out when the sidebar is collapsed.
278
+
279
+ ```tsx
280
+ import { SideBar } from '@redis-ui/components';
281
+ import { PlusIcon } from '@redis-ui/icons';
282
+ import { useState } from 'react';
283
+ import { RedisIcon } from '@redis-ui/icons/multicolor';
284
+ import { groups } from './SideBar.data';
285
+
286
+ const [expanded, setExpanded] = useState(true);
287
+ const [activeLink, setActiveLink] = useState(groups[0].items[0].content);
288
+
289
+ <SideBar
290
+ isExpanded={expanded}
291
+ style={{ maxHeight: '55rem', height: 'calc(100vh - 2rem)' }}
292
+ expandedWidth="35rem"
293
+ >
294
+ <SideBar.Header onToggle={() => setExpanded(!expanded)}>
295
+ <SideBar.SideBarLogo logoIcon={RedisIcon} />
296
+ </SideBar.Header>
297
+ <SideBar.ScrollContainer>
298
+ {groups.map((group, groupIdx) => (
299
+ <SideBar.Group key={group.title ?? `group-${groupIdx}`}>
300
+ {group.title && <SideBar.Group.Title>{group.title}</SideBar.Group.Title>}
301
+ <SideBar.ItemsContainer>
302
+ {group.items.map((item) => (
303
+ <SideBar.Item
304
+ isActive={item.content === activeLink}
305
+ onClick={() => setActiveLink(item.content)}
306
+ key={item.content}
307
+ tooltipProps={{ text: item.content, placement: 'right' }}
308
+ >
309
+ <SideBar.Item.Icon icon={item.icon} />
310
+ <SideBar.Item.Text>{item.content}</SideBar.Item.Text>
311
+ {'badge' in item && item.badge && (
312
+ <SideBar.Item.Badge label={item.badge.label} variant={item.badge.variant} />
313
+ )}
314
+ {'hasButton' in item && item.hasButton && (
315
+ <SideBar.Item.Button
316
+ icon={PlusIcon}
317
+ variant="primary"
318
+ onClick={(e) => e.stopPropagation()}
319
+ title={`New ${item.content}`}
320
+ />
321
+ )}
322
+ </SideBar.Item>
323
+ ))}
324
+ </SideBar.ItemsContainer>
325
+ </SideBar.Group>
326
+ ))}
327
+ </SideBar.ScrollContainer>
328
+ <SideBar.Footer>
329
+ <SideBar.Divider fullWidth />
330
+ <SideBar.Footer.MetaData>© 2026 Redis</SideBar.Footer.MetaData>
331
+ </SideBar.Footer>
332
+ </SideBar>
333
+ ```
334
+
252
335
  ### HeaderAndFooter
253
336
 
254
337
  > `Header` includes toggle button and. Set `onToggle` handler to switch expanded state.
@@ -458,11 +541,14 @@ const [expanded, setExpanded] = useState(true);
458
541
  ## Notes
459
542
 
460
543
  - `SideBar` is a collapsible navigation shell with a fixed header/footer layout and grouped content in the middle.
544
+ - The expanded and collapsed widths default to the theme (`sideBar.expanded.width` / `sideBar.collapsed.width`). Hosts can override the expanded width by passing the `expandedWidth` prop; the collapsed state always uses the theme value.
461
545
  - `SideBar.Header` needs an `onToggle` handler and should usually render `SideBar.SideBarLogo` inside it.
462
546
  - `SideBar.Footer` is typically used with `Footer.MetaData`; that metadata area is hidden when the sidebar is collapsed.
463
547
  - `SideBar.ScrollContainer` is intended for the middle content when vertical space is constrained, and the docs recommend using only one per sidebar.
464
548
  - `SideBar.Split` can be used either directly under `SideBar` or under `SideBar.ScrollContainer`, but the two patterns should not be mixed.
465
549
  - `SideBar.Divider` supports `noMargin`, `fullWidth`, and `fullWidthWhenExpanded` for layout tuning.
466
- - `SideBar.Item` wraps collapsed items in a tooltip and exposes `Item.Icon`, `Item.Text`, and `Item.Button` for composition.
467
- - `SideBar.Item.Button` only renders while the sidebar is expanded and defaults its size to `M`.
550
+ - `SideBar.Item` wraps collapsed items in a tooltip and exposes `Item.Icon`, `Item.Text`, `Item.Button`, and `Item.Badge` for composition.
551
+ - `SideBar.Item.Button` stays mounted in the DOM in both states and defaults its size to `M`; when collapsed (or mid-transition) it is visually hidden via opacity, gets `pointer-events: none`, and is forced to `tabIndex={-1}` + `aria-hidden={true}` so it is removed from the tab order and hidden from assistive tech (consumer `tabIndex`/`aria-hidden` are intentionally overridden in the hidden state).
468
552
  - `SideBar.Button` is the root collapsible action button, and it defaults to `PlusIcon` when no collapsed icon is provided.
553
+ - `SideBar.Group` wraps a section's `Group.Title` (optional) and items so the title and the items stay together as one logical unit.
554
+ - `SideBar.Group.Title` labels a group of items with a semibold, secondary-color body label. Its row keeps its theme-driven padding in both states so the items below never jump; the label itself fades out via opacity when the sidebar is collapsed (matching `SideBar.Item.Text`). Pair it with `SideBar.Item.Badge` next to `Item.Text` if you need to mark individual items as `NEW`, `BETA`, etc.