orcs-design-system 3.3.75 → 3.3.76

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.
@@ -11,10 +11,16 @@ import sharedNavItemHoverStyles, { sharedNavItemActiveStylesProps } from "./styl
11
11
  // Icon column width for consistent grid layout
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  const ICON_COLUMN_WIDTH = "12px";
14
+
15
+ // Constrain icon width to prevent alignment issues with variable-width icons
16
+ const IconWrapper = /*#__PURE__*/styled.span.withConfig({
17
+ displayName: "IconWrapper",
18
+ componentId: "sc-1qz1q0h-0"
19
+ })(["display:inline-flex;align-items:center;justify-content:center;width:", ";flex-shrink:0;> *{width:", " !important;max-width:", ";}"], ICON_COLUMN_WIDTH, ICON_COLUMN_WIDTH, ICON_COLUMN_WIDTH);
14
20
  const sharedNavItemStyles = /*#__PURE__*/styledCss(["cursor:pointer;text-decoration:none;border-radius:", ";width:100%;position:relative;border:none;path{transition:", ";fill:", ";}font-family:", ";display:grid;grid-template-columns:", ";place-items:center;transition:", ";background-color:transparent;font-size:1.4rem;font-weight:", ";", " @media screen and (max-width:", "px){width:auto;max-height:30px;height:30px;}&:focus{outline:0;}"], themeGet("radii.2"), themeGet("transition.transitionDefault"), themeGet("colors.greyDarker"), themeGet("fonts.main"), ICON_COLUMN_WIDTH, themeGet("transition.transitionDefault"), themeGet("fontWeights.1"), sharedNavItemHoverStyles, BREAKPOINTS.SMALL_SCREEN);
15
- const expandedNavItemStyles = props => styledCss(["grid-template-columns:", " 1fr;gap:8px;justify-items:start;align-items:center;padding-left:0;.nav-item-text{font-size:", ";line-height:1;font-weight:", ";color:", ";text-align:left;justify-self:start;}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}"], ICON_COLUMN_WIDTH, themeGet("fontSizes.1"), themeGet("fontWeights.1"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.greyDarker"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.primary"));
21
+ const expandedNavItemStyles = props => styledCss(["grid-template-columns:", " 1fr;gap:", ";justify-items:start;align-items:center;padding-left:0;.nav-item-text{font-size:", ";line-height:1;font-weight:", ";color:", ";text-align:left;justify-self:start;padding-left:", ";}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}"], ICON_COLUMN_WIDTH, themeGet("space.s"), themeGet("fontSizes.1"), themeGet("fontWeights.1"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.greyDarker"), themeGet("space.s"), props.active ? themeGet("colors.greyDarkest") : themeGet("colors.primary"));
16
22
  const variantActiveStyles = {
17
- expandableItem: props => styledCss(["color:", ";path{fill:", ";}:after{height:100%;position:absolute;right:0;transform:", ";content:\"\";border-right:3px solid ", ";z-index:5;}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}@media screen and (max-width:", "px){:after{border-top:3px solid ", ";border-right:none;transform:translateY(-10px);right:auto;width:100%;}}"], themeGet("colors.greyDarkest"), themeGet("colors.greyDarkest"), props.isExpanded ? "translateX(9px)" : "translateX(8px)", themeGet("colors.primary"), themeGet("colors.primary"), BREAKPOINTS.SMALL_SCREEN, themeGet("colors.primary")),
23
+ expandableItem: () => styledCss(["color:", ";path{fill:", ";}:after{height:calc(100% + ", " + ", ");position:absolute;right:-", ";top:-", ";content:\"\";border-right:3px solid ", ";z-index:5;}&:hover .nav-item-text,&:focus .nav-item-text{color:", ";}@media screen and (max-width:", "px){:after{border-top:3px solid ", ";border-right:none;transform:translateY(-10px);right:auto;width:100%;}}"], themeGet("colors.greyDarkest"), themeGet("colors.greyDarkest"), themeGet("space.xs"), themeGet("space.xs"), themeGet("space.xs"), themeGet("space.xs"), themeGet("colors.primary"), themeGet("colors.primary"), BREAKPOINTS.SMALL_SCREEN, themeGet("colors.primary")),
18
24
  default: styledCss(["", ""], props => sharedNavItemActiveStylesProps(props))
19
25
  };
20
26
  const getActiveStyles = props => {
@@ -26,15 +32,15 @@ const getActiveStyles = props => {
26
32
  };
27
33
  const SideNavItemLink = /*#__PURE__*/styled.div.withConfig({
28
34
  displayName: "SideNavItemLink",
29
- componentId: "sc-1qz1q0h-0"
35
+ componentId: "sc-1qz1q0h-1"
30
36
  })(["& > a{", " ", " ", "}"], sharedNavItemStyles, props => props.isExpanded ? expandedNavItemStyles(props) : "", getActiveStyles);
31
37
  const SideNavItem = /*#__PURE__*/styled("button").withConfig({
32
38
  displayName: "SideNavItem",
33
- componentId: "sc-1qz1q0h-1"
39
+ componentId: "sc-1qz1q0h-2"
34
40
  })(["", " ", " ", ""], sharedNavItemStyles, props => props.isExpanded ? expandedNavItemStyles(props) : "", getActiveStyles);
35
41
  const BadgeNumber = /*#__PURE__*/styled("div").withConfig({
36
42
  displayName: "BadgeNumber",
37
- componentId: "sc-1qz1q0h-2"
43
+ componentId: "sc-1qz1q0h-3"
38
44
  })(props => css({
39
45
  position: "absolute",
40
46
  height: "16px",
@@ -53,7 +59,7 @@ const BadgeNumber = /*#__PURE__*/styled("div").withConfig({
53
59
  }));
54
60
  const BadgeDot = /*#__PURE__*/styled("div").withConfig({
55
61
  displayName: "BadgeDot",
56
- componentId: "sc-1qz1q0h-3"
62
+ componentId: "sc-1qz1q0h-4"
57
63
  })(props => css({
58
64
  position: "absolute",
59
65
  height: "8px",
@@ -66,9 +72,9 @@ const BadgeDot = /*#__PURE__*/styled("div").withConfig({
66
72
  }));
67
73
  const SideNavItemWrapper = /*#__PURE__*/styled.div.withConfig({
68
74
  displayName: "SideNavItemWrapper",
69
- componentId: "sc-1qz1q0h-4"
75
+ componentId: "sc-1qz1q0h-5"
70
76
  })(props => css({
71
- padding: themeGet("space.m")(props),
77
+ padding: themeGet("space.xs")(props),
72
78
  borderRadius: themeGet("radii.2")(props),
73
79
  width: "100%",
74
80
  "&:nth-child(1 of .bottom-aligned) ": {
@@ -77,11 +83,11 @@ const SideNavItemWrapper = /*#__PURE__*/styled.div.withConfig({
77
83
  "&:has(button:hover), &:has(a:hover)": {
78
84
  backgroundColor: themeGet("colors.greyLightest")(props)
79
85
  },
80
- "&:has(button.active), &:has(a.active)": {
86
+ ...(props.isActive && props.isLink && {
81
87
  backgroundColor: themeGet("colors.primaryLightest")(props)
82
- },
88
+ }),
83
89
  [`@media screen and (max-width: ${BREAKPOINTS.SMALL_SCREEN}px)`]: {
84
- padding: themeGet("space.m")(props)
90
+ padding: themeGet("space.xs")(props)
85
91
  }
86
92
  }));
87
93
 
@@ -131,8 +137,11 @@ const NavItem = _ref => {
131
137
  ref: el => navItemRefs.current[item.index] = el,
132
138
  children: /*#__PURE__*/_jsxs(Component, {
133
139
  item: item,
134
- children: [/*#__PURE__*/_jsx(Icon, {
135
- icon: ["far", item.iconName]
140
+ children: [/*#__PURE__*/_jsx(IconWrapper, {
141
+ children: /*#__PURE__*/_jsx(Icon, {
142
+ icon: ["far", item.iconName],
143
+ fixedWidth: true
144
+ })
136
145
  }), isExpanded && !isSmallScreen && /*#__PURE__*/_jsx("span", {
137
146
  className: "nav-item-text",
138
147
  children: item.name
@@ -152,8 +161,11 @@ const NavItem = _ref => {
152
161
  children: item.badgeNumber
153
162
  }), item.badgeDot && /*#__PURE__*/_jsx(BadgeDot, {
154
163
  isExpanded: isExpanded
155
- }), /*#__PURE__*/_jsx(Icon, {
156
- icon: ["far", item.iconName]
164
+ }), /*#__PURE__*/_jsx(IconWrapper, {
165
+ children: /*#__PURE__*/_jsx(Icon, {
166
+ icon: ["far", item.iconName],
167
+ fixedWidth: true
168
+ })
157
169
  }), isExpanded && !isSmallScreen && /*#__PURE__*/_jsx("span", {
158
170
  className: "nav-item-text",
159
171
  children: item.name
@@ -171,6 +183,8 @@ const NavItem = _ref => {
171
183
  }) : /*#__PURE__*/_jsx(SideNavItemWrapper, {
172
184
  className: item.bottomAligned && "bottom-aligned",
173
185
  bottomAligned: item.bottomAligned,
186
+ isActive: isActive,
187
+ isLink: item.actionType === "link",
174
188
  children: renderedNavItem
175
189
  });
176
190
  };
@@ -0,0 +1,90 @@
1
+ import React from "react";
2
+ import { BrowserRouter as Router } from "react-router-dom";
3
+ import PanelLink from "./components/PanelLink";
4
+ import Box from "../Box";
5
+ import { H5 } from "../Typography";
6
+ import Divider from "../Divider";
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ export default {
9
+ title: "Components/SideNavV2/PanelLink",
10
+ component: PanelLink,
11
+ decorators: [Story => /*#__PURE__*/_jsx(Router, {
12
+ children: /*#__PURE__*/_jsx(Story, {})
13
+ })]
14
+ };
15
+ const Template = args => /*#__PURE__*/_jsx(PanelLink, {
16
+ ...args
17
+ });
18
+ export const Default = Template.bind({});
19
+ Default.args = {
20
+ to: "/settings",
21
+ children: "Settings Link"
22
+ };
23
+ export const Active = Template.bind({});
24
+ Active.args = {
25
+ to: "#",
26
+ children: "Active Link",
27
+ className: "active"
28
+ };
29
+ export const MenuExample = () => /*#__PURE__*/_jsxs(Box, {
30
+ width: "300px",
31
+ p: "r",
32
+ bg: "white",
33
+ boxBorder: "default",
34
+ borderRadius: 2,
35
+ children: [/*#__PURE__*/_jsx(H5, {
36
+ fontWeight: "bold",
37
+ mb: "r",
38
+ children: "Settings"
39
+ }), /*#__PURE__*/_jsx(Divider, {
40
+ light: true,
41
+ mb: "s"
42
+ }), /*#__PURE__*/_jsx(PanelLink, {
43
+ to: "/settings/workspace",
44
+ children: "Workspace settings"
45
+ }), /*#__PURE__*/_jsx(PanelLink, {
46
+ to: "/settings/org-structure",
47
+ children: "Org structure"
48
+ }), /*#__PURE__*/_jsx(PanelLink, {
49
+ to: "/settings/tags",
50
+ className: "active",
51
+ children: "Manage tags"
52
+ }), /*#__PURE__*/_jsx(PanelLink, {
53
+ to: "/settings/allocation",
54
+ children: "Allocation config"
55
+ }), /*#__PURE__*/_jsx(PanelLink, {
56
+ to: "/settings/planner",
57
+ children: "Planner config"
58
+ }), /*#__PURE__*/_jsx(Divider, {
59
+ light: true,
60
+ my: "s"
61
+ }), /*#__PURE__*/_jsx(H5, {
62
+ fontSize: "1.4rem",
63
+ fontWeight: "bold",
64
+ color: "greyDark",
65
+ uppercase: true,
66
+ mb: "s",
67
+ children: "Configure workspace"
68
+ }), /*#__PURE__*/_jsx(PanelLink, {
69
+ to: "/settings/forecast",
70
+ children: "Forecast config"
71
+ }), /*#__PURE__*/_jsx(PanelLink, {
72
+ to: "/settings/strategy",
73
+ children: "Strategy config"
74
+ }), /*#__PURE__*/_jsx(PanelLink, {
75
+ to: "/settings/group-access",
76
+ children: "Group access"
77
+ })]
78
+ });
79
+ MenuExample.parameters = {
80
+ docs: {
81
+ description: {
82
+ story: "Example of PanelLink used in a menu structure. Shows grey hover state and blue active state."
83
+ }
84
+ }
85
+ };
86
+ MenuExample.__docgenInfo = {
87
+ "description": "",
88
+ "methods": [],
89
+ "displayName": "MenuExample"
90
+ };
@@ -0,0 +1,29 @@
1
+ import styled from "styled-components";
2
+ import { NavLink } from "react-router-dom";
3
+ import themeGet from "@styled-system/theme-get";
4
+ import sharedNavItemHoverStyles, { sharedNavItemActiveStyles, sharedNavItemBaseStyles } from "../styles/sharedHoverStyles";
5
+
6
+ /**
7
+ * PanelLink - A reusable link component for expandable panel menus
8
+ *
9
+ * Provides consistent styling for links within SideNav expandable panels:
10
+ * - Grey background on hover
11
+ * - Blue background when active
12
+ * - Consistent padding and spacing
13
+ * - Proper border radius
14
+ *
15
+ * Use this for all navigation links within expandable panels (Settings, Tags, Teams, etc.)
16
+ * to ensure visual consistency across the application.
17
+ *
18
+ * @example
19
+ * ```jsx
20
+ * <PanelLink to="/settings/workspace">
21
+ * Workspace Settings
22
+ * </PanelLink>
23
+ * ```
24
+ */
25
+ const PanelLink = /*#__PURE__*/styled(NavLink).withConfig({
26
+ displayName: "PanelLink",
27
+ componentId: "sc-1awj6t8-0"
28
+ })(["font-size:", ";cursor:pointer;padding:", ";text-decoration:none;display:block;width:100%;", " ", " ", ""], themeGet("fontSizes.1"), themeGet("space.xs"), sharedNavItemBaseStyles, sharedNavItemHoverStyles, sharedNavItemActiveStyles);
29
+ export default PanelLink;
@@ -1,4 +1,5 @@
1
1
  export { SideNavStateProvider, useSideNavStateContext } from "./context/SideNavStateProvider";
2
2
  export { default as RenderCurrentViewSection } from "./components/RenderCurrentViewSection";
3
+ export { default as PanelLink } from "./components/PanelLink";
3
4
  export { default as SideNavV2 } from "./SideNav";
4
5
  export { default } from "./SideNav";
@@ -13,11 +13,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
13
  const SubNavList = /*#__PURE__*/styled.ul.withConfig({
14
14
  displayName: "SubNavList",
15
15
  componentId: "sc-12clz4a-0"
16
- })(["list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:2px;width:100%;"]);
16
+ })(["list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:", ";width:100%;"], themeGet("space.xs"));
17
17
  const StyledNavLink = /*#__PURE__*/styled(NavLink).withConfig({
18
18
  displayName: "StyledNavLink",
19
19
  componentId: "sc-12clz4a-1"
20
- })(["font-size:", ";cursor:pointer;padding:5px 7px;text-decoration:none;", " ", " ", ""], themeGet("fontSizes.1"), sharedNavItemBaseStyles, sharedNavItemHoverStyles, sharedNavItemActiveStyles);
20
+ })(["font-size:", ";cursor:pointer;padding:", ";text-decoration:none;display:block;width:100%;", " ", " ", ""], themeGet("fontSizes.1"), themeGet("space.xs"), sharedNavItemBaseStyles, sharedNavItemHoverStyles, sharedNavItemActiveStyles);
21
21
  const UnstyledNavLink = /*#__PURE__*/styled(NavLink).withConfig({
22
22
  displayName: "UnstyledNavLink",
23
23
  componentId: "sc-12clz4a-2"
@@ -51,7 +51,7 @@ export const SideNavItems = /*#__PURE__*/styled("div").withConfig({
51
51
  flexShrink: "0",
52
52
  flexGrow: "1",
53
53
  padding: "10px 10px 10px 10px",
54
- gap: "xs",
54
+ gap: "s",
55
55
  alignItems: "center",
56
56
  justifyContent: "flex-start",
57
57
  textAlign: "center",
@@ -41,6 +41,7 @@ test("all components exported", () => {
41
41
  "Modal",
42
42
  "Notification",
43
43
  "P",
44
+ "PanelLink",
44
45
  "Popover",
45
46
  "ProgressBar",
46
47
  "Quote",
package/es/index.js CHANGED
@@ -35,7 +35,7 @@ export { default as ProgressBar } from "./components/ProgressBar";
35
35
  export { default as RadioButton } from "./components/RadioButton";
36
36
  export { default as Range } from "./components/Range";
37
37
  export { default as Select } from "./components/Select";
38
- export { default as SideNavV2, SideNavStateProvider, useSideNavStateContext, RenderCurrentViewSection } from "./components/SideNavV2";
38
+ export { default as SideNavV2, SideNavStateProvider, useSideNavStateContext, RenderCurrentViewSection, PanelLink } from "./components/SideNavV2";
39
39
  export { default as Spacer } from "./components/Spacer";
40
40
  export { default as StatusDot } from "./components/StatusDot";
41
41
  export { default as StyledLink, styleLink } from "./components/StyledLink";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orcs-design-system",
3
- "version": "3.3.75",
3
+ "version": "3.3.76",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },