orcs-design-system 3.2.40 → 3.2.42
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/ActionsMenu/index.js +40 -4
- package/es/components/SideNav/index.js +1 -1
- package/es/components/Tabs/Tabs.stories.js +67 -0
- package/es/components/Tabs/index.js +189 -178
- package/es/components.test.js +1 -2
- package/es/index.js +1 -1
- package/package.json +16 -8
- package/es/components/Tabs/Tab.stories.js +0 -91
- package/es/components/Tabs/TabsContainer.stories.js +0 -48
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useState, useImperativeHandle, createContext, useContext, useMemo, useId, useLayoutEffect } from "react";
|
|
2
|
-
import styled, { keyframes, ThemeProvider } from "styled-components";
|
|
2
|
+
import styled, { css, keyframes, ThemeProvider } from "styled-components";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { space, layout } from "styled-system";
|
|
5
5
|
import { themeGet } from "@styled-system/theme-get";
|
|
@@ -88,6 +88,11 @@ export const ActionsMenuItem = styled(props => {
|
|
|
88
88
|
["data-action-menu-id"]: id
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
+
if (props.Component) return /*#__PURE__*/_jsx(props.Component, {
|
|
92
|
+
...newProps,
|
|
93
|
+
onClick: onClick,
|
|
94
|
+
disabled: disabled
|
|
95
|
+
});
|
|
91
96
|
return /*#__PURE__*/_jsx(Component, {
|
|
92
97
|
...newProps,
|
|
93
98
|
onClick: onClick,
|
|
@@ -98,8 +103,13 @@ export const ActionsMenuItem = styled(props => {
|
|
|
98
103
|
}).withConfig({
|
|
99
104
|
displayName: "ActionsMenu__ActionsMenuItem",
|
|
100
105
|
componentId: "sc-yvbni2-6"
|
|
101
|
-
})(["
|
|
102
|
-
|
|
106
|
+
})(["", ""], _ref => {
|
|
107
|
+
let {
|
|
108
|
+
Component
|
|
109
|
+
} = _ref;
|
|
110
|
+
return Component ? "" : css(["white-space:nowrap;display:block;width:100%;text-align:left;cursor:pointer;margin:0;padding:8px;appearance:none;background-color:", ";border:none;border-bottom:solid 1px ", ";border-radius:0;color:", ";font-size:", ";line-height:", ";font-family:", ";font-weight:", ";text-decoration:none;transition:", ";&:hover,&:focus{outline:0;background-color:", ";}&:first-child{border-radius:", " ", " 0 0;}&:last-child{border:0;border-radius:0 0 ", " ", ";}&:only-child{border-radius:", ";}"], props => props.selected ? themeGet("colors.successDark")(props) : "transparent", props => themeGet("colors.greyDarkest")(props), props => themeGet("colors.white")(props), props => themeGet("fontSizes.1")(props), props => themeGet("fontSizes.1")(props), props => themeGet("fonts.main")(props), props => themeGet("fontWeights.2")(props), props => themeGet("transition.transitionDefault")(props), props => themeGet("colors.primaryDark")(props), props => themeGet("radii.2")(props), props => themeGet("radii.2")(props), props => themeGet("radii.2")(props), props => themeGet("radii.2")(props), props => themeGet("radii.2")(props));
|
|
111
|
+
});
|
|
112
|
+
export const ActionsMenuBody = _ref2 => {
|
|
103
113
|
let {
|
|
104
114
|
theme,
|
|
105
115
|
onToggle,
|
|
@@ -108,6 +118,7 @@ export const ActionsMenuBody = _ref => {
|
|
|
108
118
|
direction = "right-start",
|
|
109
119
|
menuWidth,
|
|
110
120
|
customTriggerComponent,
|
|
121
|
+
renderTrigger,
|
|
111
122
|
children,
|
|
112
123
|
ariaLabel = "Options Menu",
|
|
113
124
|
onTriggerFocus,
|
|
@@ -115,7 +126,7 @@ export const ActionsMenuBody = _ref => {
|
|
|
115
126
|
closeOnClick = false,
|
|
116
127
|
"data-testid": dataTestId = "ActionsMenu",
|
|
117
128
|
...props
|
|
118
|
-
} =
|
|
129
|
+
} = _ref2;
|
|
119
130
|
const id = useId();
|
|
120
131
|
const actionMenu = useActionMenu({
|
|
121
132
|
placement: direction,
|
|
@@ -148,8 +159,12 @@ export const ActionsMenuBody = _ref => {
|
|
|
148
159
|
className: "action-menu-icon"
|
|
149
160
|
})
|
|
150
161
|
});
|
|
162
|
+
if (renderTrigger) {
|
|
163
|
+
triggerComponent = renderTrigger(triggerProps);
|
|
164
|
+
}
|
|
151
165
|
if (customTriggerComponent) {
|
|
152
166
|
triggerComponent = /*#__PURE__*/_jsx("div", {
|
|
167
|
+
role: "button",
|
|
153
168
|
...triggerProps,
|
|
154
169
|
children: customTriggerComponent
|
|
155
170
|
});
|
|
@@ -234,6 +249,8 @@ ActionsMenuBody.propTypes = {
|
|
|
234
249
|
menuRightPosition: PropTypes.string,
|
|
235
250
|
menuWidth: PropTypes.string,
|
|
236
251
|
customTriggerComponent: PropTypes.node,
|
|
252
|
+
renderTrigger: PropTypes.func,
|
|
253
|
+
"data-testid": PropTypes.string,
|
|
237
254
|
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
|
238
255
|
theme: PropTypes.object,
|
|
239
256
|
ariaLabel: PropTypes.string
|
|
@@ -261,6 +278,7 @@ ActionsMenu.propTypes = {
|
|
|
261
278
|
isOpen: PropTypes.bool,
|
|
262
279
|
direction: PropTypes.oneOf(["left", "right", "top", "bottom", "top-start", "top-end", "bottom-start", "bottom-end", "left-start", "left-end", "right-start", "right-end"]),
|
|
263
280
|
customTriggerComponent: PropTypes.node,
|
|
281
|
+
renderTrigger: PropTypes.func,
|
|
264
282
|
closeOnClick: PropTypes.bool,
|
|
265
283
|
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
|
266
284
|
/** Specifies the colour theme */
|
|
@@ -331,6 +349,13 @@ ActionsMenu.__docgenInfo = {
|
|
|
331
349
|
},
|
|
332
350
|
"required": false
|
|
333
351
|
},
|
|
352
|
+
"renderTrigger": {
|
|
353
|
+
"description": "",
|
|
354
|
+
"type": {
|
|
355
|
+
"name": "func"
|
|
356
|
+
},
|
|
357
|
+
"required": false
|
|
358
|
+
},
|
|
334
359
|
"closeOnClick": {
|
|
335
360
|
"description": "",
|
|
336
361
|
"type": {
|
|
@@ -413,6 +438,10 @@ ActionsMenuBody.__docgenInfo = {
|
|
|
413
438
|
"value": "\"ActionsMenu\"",
|
|
414
439
|
"computed": false
|
|
415
440
|
},
|
|
441
|
+
"description": "",
|
|
442
|
+
"type": {
|
|
443
|
+
"name": "string"
|
|
444
|
+
},
|
|
416
445
|
"required": false
|
|
417
446
|
},
|
|
418
447
|
"onTriggerFocus": {
|
|
@@ -485,6 +514,13 @@ ActionsMenuBody.__docgenInfo = {
|
|
|
485
514
|
},
|
|
486
515
|
"required": false
|
|
487
516
|
},
|
|
517
|
+
"renderTrigger": {
|
|
518
|
+
"description": "",
|
|
519
|
+
"type": {
|
|
520
|
+
"name": "func"
|
|
521
|
+
},
|
|
522
|
+
"required": false
|
|
523
|
+
},
|
|
488
524
|
"children": {
|
|
489
525
|
"description": "",
|
|
490
526
|
"type": {
|
|
@@ -91,7 +91,7 @@ const SideNavExpanded = styled("div").withConfig({
|
|
|
91
91
|
maxWidth: props.large ? "calc(" + themeGet("appScale.sidebarMaxWidthLarge")(props) + " - " + themeGet("appScale.navBarSize")(props) + ")" : "calc(" + themeGet("appScale.sidebarMaxWidth")(props) + " - " + themeGet("appScale.navBarSize")(props) + ")",
|
|
92
92
|
height: "inherit",
|
|
93
93
|
overflowY: "auto",
|
|
94
|
-
padding: "
|
|
94
|
+
padding: "16px",
|
|
95
95
|
borderLeft: `solid 1px ${themeGet("colors.greyLighter")(props)}`,
|
|
96
96
|
"&:focus": {
|
|
97
97
|
outline: "0"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Tabs from ".";
|
|
3
|
+
import { BrowserRouter, Route, Switch } from "react-router-dom";
|
|
4
|
+
import Box from "../Box";
|
|
5
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
export default {
|
|
7
|
+
title: "Components/Tabs",
|
|
8
|
+
decorators: [storyFn => /*#__PURE__*/_jsx(Box, {
|
|
9
|
+
bg: "greyLightest",
|
|
10
|
+
p: "xl",
|
|
11
|
+
pb: "300px",
|
|
12
|
+
children: storyFn()
|
|
13
|
+
})],
|
|
14
|
+
component: Tabs
|
|
15
|
+
};
|
|
16
|
+
const tabsList = [{
|
|
17
|
+
label: "Details",
|
|
18
|
+
path: "/details"
|
|
19
|
+
}, {
|
|
20
|
+
label: "Strategy",
|
|
21
|
+
path: "/strategy"
|
|
22
|
+
}, {
|
|
23
|
+
label: "Associations",
|
|
24
|
+
path: "/associations"
|
|
25
|
+
}, {
|
|
26
|
+
label: "Visualisation",
|
|
27
|
+
path: "/visualisation"
|
|
28
|
+
}, {
|
|
29
|
+
label: "Principles",
|
|
30
|
+
path: "/principles"
|
|
31
|
+
}, {
|
|
32
|
+
label: "Planner",
|
|
33
|
+
path: "/planner"
|
|
34
|
+
}, {
|
|
35
|
+
label: "Forecast",
|
|
36
|
+
path: "/forecast"
|
|
37
|
+
}, {
|
|
38
|
+
label: "Team Builder",
|
|
39
|
+
path: "/teambuilder"
|
|
40
|
+
}, {
|
|
41
|
+
label: "History",
|
|
42
|
+
path: "/history",
|
|
43
|
+
isVisible: false
|
|
44
|
+
}];
|
|
45
|
+
export const defaultTabs = () => /*#__PURE__*/_jsxs(BrowserRouter, {
|
|
46
|
+
children: [/*#__PURE__*/_jsx(Tabs, {
|
|
47
|
+
tabsList: tabsList
|
|
48
|
+
}), /*#__PURE__*/_jsx(Switch, {
|
|
49
|
+
children: tabsList.map(tab => /*#__PURE__*/_jsx(Route, {
|
|
50
|
+
path: tab.path,
|
|
51
|
+
children: /*#__PURE__*/_jsxs(Box, {
|
|
52
|
+
bg: "white",
|
|
53
|
+
borderRadius: 2,
|
|
54
|
+
boxBorder: "default",
|
|
55
|
+
p: "l",
|
|
56
|
+
mt: "l",
|
|
57
|
+
children: ["ROUTE RENDERED: ", tab.label]
|
|
58
|
+
})
|
|
59
|
+
}, tab.path))
|
|
60
|
+
})]
|
|
61
|
+
});
|
|
62
|
+
defaultTabs.storyName = "Default";
|
|
63
|
+
defaultTabs.__docgenInfo = {
|
|
64
|
+
"description": "",
|
|
65
|
+
"methods": [],
|
|
66
|
+
"displayName": "defaultTabs"
|
|
67
|
+
};
|
|
@@ -1,196 +1,207 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import React, { useState, useRef, useEffect, useCallback } from "react";
|
|
2
|
+
import styled, { css } from "styled-components";
|
|
3
|
+
import { NavLink, useLocation } from "react-router-dom";
|
|
4
|
+
import { isEqual } from "lodash";
|
|
5
|
+
import ActionsMenu, { ActionsMenuItem } from "../ActionsMenu";
|
|
6
|
+
import Icon from "../Icon";
|
|
7
|
+
import FlexItem from "../Flex";
|
|
4
8
|
import { themeGet } from "@styled-system/theme-get";
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
displayName: "Tabs__TabsContainerItem",
|
|
9
|
+
import PropTypes from "prop-types";
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
const TabsContainer = styled.div.withConfig({
|
|
12
|
+
displayName: "Tabs__TabsContainer",
|
|
10
13
|
componentId: "sc-15tpvnt-0"
|
|
11
|
-
})(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
alignItems: "center",
|
|
15
|
-
flexWrap: "wrap",
|
|
16
|
-
bg: "transparent"
|
|
17
|
-
}), space);
|
|
18
|
-
export const TabItem = styled("div").withConfig({
|
|
19
|
-
displayName: "Tabs__TabItem",
|
|
14
|
+
})(["position:relative;"]);
|
|
15
|
+
const TabWrapper = styled.div.withConfig({
|
|
16
|
+
displayName: "Tabs__TabWrapper",
|
|
20
17
|
componentId: "sc-15tpvnt-1"
|
|
21
|
-
})(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
color: themeGet("colors.greyDarker")(props),
|
|
32
|
-
display: "flex",
|
|
33
|
-
alignItems: "center",
|
|
34
|
-
position: "relative",
|
|
35
|
-
whiteSpace: "nowrap",
|
|
36
|
-
textDecoration: "none",
|
|
37
|
-
textAlign: "center",
|
|
38
|
-
textTransform: "uppercase",
|
|
39
|
-
cursor: "pointer",
|
|
40
|
-
"&:hover": {
|
|
41
|
-
bg: themeGet("colors.greyLight")(props),
|
|
42
|
-
color: themeGet("colors.greyDarker")(props),
|
|
43
|
-
outline: "0"
|
|
44
|
-
},
|
|
45
|
-
"&:focus": {
|
|
46
|
-
color: themeGet("colors.greyDarker")(props),
|
|
47
|
-
outline: "0",
|
|
48
|
-
boxShadow: themeGet("shadows.thinOutline")(props) + " " + themeGet("colors.grey")(props)
|
|
49
|
-
},
|
|
50
|
-
button: {
|
|
51
|
-
marginLeft: 2
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
"&.active": {
|
|
55
|
-
a: {
|
|
56
|
-
color: themeGet("colors.primary")(props),
|
|
57
|
-
bg: themeGet("colors.white")(props),
|
|
58
|
-
"&:hover": {
|
|
59
|
-
cursor: "default"
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
"&.notification": {
|
|
64
|
-
a: {
|
|
65
|
-
"&::after": {
|
|
66
|
-
position: "absolute",
|
|
67
|
-
top: "calc(8px * -1)",
|
|
68
|
-
right: "calc(4px * -2)",
|
|
69
|
-
display: "flex",
|
|
70
|
-
alignItems: "center",
|
|
71
|
-
justifyContent: "center",
|
|
72
|
-
width: "20px",
|
|
73
|
-
height: "20px",
|
|
74
|
-
borderRadius: "50%",
|
|
75
|
-
fontSize: themeGet("fontSizes.0")(props),
|
|
76
|
-
fontWeight: themeGet("fontWeights.2")(props),
|
|
77
|
-
content: `"${props.notification}"`,
|
|
78
|
-
bg: themeGet("colors.danger")(props),
|
|
79
|
-
color: themeGet("colors.white")(props),
|
|
80
|
-
zIndex: 4
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}), space, color);
|
|
85
|
-
export const Tab = _ref => {
|
|
18
|
+
})(["position:relative;"]);
|
|
19
|
+
const VisibleTabs = styled.div.withConfig({
|
|
20
|
+
displayName: "Tabs__VisibleTabs",
|
|
21
|
+
componentId: "sc-15tpvnt-2"
|
|
22
|
+
})(["flex-shrink:1;display:flex;align-items:center;overflow:hidden;"]);
|
|
23
|
+
const activeTabStyle = css(["background-color:", ";color:", ";cursor:default;&:hover{background-color:", ";color:", ";}&:focus{color:", ";}"], themeGet("colors.white"), themeGet("colors.primary"), themeGet("colors.white"), themeGet("colors.primary"), themeGet("colors.primary"));
|
|
24
|
+
const Tab = styled(NavLink).withConfig({
|
|
25
|
+
displayName: "Tabs__Tab",
|
|
26
|
+
componentId: "sc-15tpvnt-3"
|
|
27
|
+
})(["width:", ";display:block;border-radius:", ";transition:background 200ms ease-in-out,color 200ms ease-in-out;padding:", " ", ";font-size:", ";font-weight:", ";position:relative;white-space:nowrap;text-decoration:none;text-align:center;text-transform:uppercase;background-color:", ";color:", ";cursor:pointer;", " &:hover{outline:0;background-color:", ";color:", ";}&:focus{outline:0;color:", ";box-shadow:inset ", " ", ";}&.active{", "}"], _ref => {
|
|
86
28
|
let {
|
|
87
|
-
|
|
88
|
-
children,
|
|
89
|
-
active,
|
|
90
|
-
notification,
|
|
91
|
-
...props
|
|
29
|
+
fullWidth
|
|
92
30
|
} = _ref;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
notification: notification,
|
|
96
|
-
role: "presentation",
|
|
97
|
-
className: `${active ? "active" : ""} ${notification ? "notification notification-" + notification : ""}`,
|
|
98
|
-
...props,
|
|
99
|
-
children: React.Children.map(children, child => /*#__PURE__*/React.cloneElement(child, {
|
|
100
|
-
role: "tab",
|
|
101
|
-
"aria-selected": `${active}`
|
|
102
|
-
}))
|
|
103
|
-
});
|
|
104
|
-
return theme ? /*#__PURE__*/_jsx(ThemeProvider, {
|
|
105
|
-
theme: theme,
|
|
106
|
-
children: component
|
|
107
|
-
}) : component;
|
|
108
|
-
};
|
|
109
|
-
Tab.propTypes = {
|
|
110
|
-
/** Specifies whether the tab is the active tab */
|
|
111
|
-
active: PropTypes.bool,
|
|
112
|
-
/** Specifies any notifications attached to the Tab */
|
|
113
|
-
notification: PropTypes.string,
|
|
114
|
-
/** Specifies the colour theme */
|
|
115
|
-
theme: PropTypes.object,
|
|
116
|
-
/** The content of the Tab is passed as a child. */
|
|
117
|
-
children: PropTypes.node
|
|
118
|
-
};
|
|
119
|
-
export const TabsContainer = _ref2 => {
|
|
31
|
+
return fullWidth ? "100%" : "fit-content";
|
|
32
|
+
}, themeGet("radii.2"), themeGet("space.3"), themeGet("space.4"), themeGet("fontSizes.1"), themeGet("fontWeights.2"), themeGet("colors.greyLighter"), themeGet("colors.greyDarker"), _ref2 => {
|
|
120
33
|
let {
|
|
121
|
-
|
|
122
|
-
children,
|
|
123
|
-
...props
|
|
34
|
+
tabInShowMore
|
|
124
35
|
} = _ref2;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
36
|
+
return tabInShowMore ? css(["position:absolute;visibility:hidden;"]) : "";
|
|
37
|
+
}, themeGet("colors.greyLight"), themeGet("colors.greyDarker"), themeGet("colors.greyDarker"), themeGet("shadows.thinOutline"), themeGet("colors.grey"), activeTabStyle);
|
|
38
|
+
const ShowMoreButton = styled.button.withConfig({
|
|
39
|
+
displayName: "Tabs__ShowMoreButton",
|
|
40
|
+
componentId: "sc-15tpvnt-4"
|
|
41
|
+
})(["appearance:none;border:none;font-family:", ";font-size:", ";font-weight:", ";border-radius:", ";background-color:", ";transition:", ";padding:", " ", ";color:", ";display:", ";align-items:center;&:hover{background-color:", ";color:", ";outline:0;}&:focus{color:", ";outline:0;box-shadow:inset ", " ", ";}&.hasActive{", "}"], themeGet("fonts.main"), themeGet("fontSizes.1"), themeGet("fontWeights.2"), themeGet("radii.2"), themeGet("colors.greyLighter"), themeGet("transition.transitionDefault"), themeGet("space.3"), themeGet("space.4"), themeGet("colors.greyDarker"), _ref3 => {
|
|
42
|
+
let {
|
|
43
|
+
showMoreVisible
|
|
44
|
+
} = _ref3;
|
|
45
|
+
return showMoreVisible ? "flex" : "none";
|
|
46
|
+
}, themeGet("colors.greyLight"), themeGet("colors.greyDarker"), themeGet("colors.greyDarker"), themeGet("shadows.thinOutline"), themeGet("colors.grey"), activeTabStyle);
|
|
47
|
+
const ShowMoreTabs = styled.div.withConfig({
|
|
48
|
+
displayName: "Tabs__ShowMoreTabs",
|
|
49
|
+
componentId: "sc-15tpvnt-5"
|
|
50
|
+
})(["border-radius:", ";background-color:", ";min-width:84px;display:flex;flex-direction:column;align-items:center;gap:6px;padding:6px;box-shadow:inset ", " ", ",", ";"], themeGet("radii.2"), themeGet("colors.white"), themeGet("shadows.thinOutline"), themeGet("colors.greyLighter"), themeGet("shadows.boxDefault"));
|
|
51
|
+
const tabsGap = 6;
|
|
52
|
+
const Tabs = _ref4 => {
|
|
53
|
+
let {
|
|
54
|
+
tabsList
|
|
55
|
+
} = _ref4;
|
|
56
|
+
const [isMounted, setIsMounted] = useState(false);
|
|
57
|
+
const containerRef = useRef(null);
|
|
58
|
+
const containerVisibleWidth = useRef(0);
|
|
59
|
+
const [showMoreTabs, setShowMoreTabs] = useState([]);
|
|
60
|
+
const calculateVisibility = useCallback(actionElements => {
|
|
61
|
+
const showMoreButton = document.getElementById("show-more-button");
|
|
62
|
+
const showMoreButtonWidth = showMoreButton?.offsetWidth ?? 0;
|
|
63
|
+
// as we loop through the tabs, we need to calculate the width of the visible tabs.
|
|
64
|
+
let calculatedWidth = showMoreTabs.length ? showMoreButtonWidth : 0;
|
|
65
|
+
|
|
66
|
+
// variable for the list of hidden tabs which will be put to react state
|
|
67
|
+
const newShowMoreTabs = [];
|
|
68
|
+
[...actionElements].filter(el => el.tagName === "A") // this ensures that the ShowMore button is not included in this logic
|
|
69
|
+
.forEach((actionEl, i) => {
|
|
70
|
+
// visibleElementsWidth will be increased by
|
|
71
|
+
// the corresponding width of the element + gapWidth
|
|
72
|
+
calculatedWidth += actionEl.offsetWidth + tabsGap;
|
|
73
|
+
|
|
74
|
+
// compare computed widths and push into newShowMoreTabs if current tab width is bigger than container width
|
|
75
|
+
if (calculatedWidth >= containerVisibleWidth.current) {
|
|
76
|
+
newShowMoreTabs.push(i);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
if (!isEqual(showMoreTabs, newShowMoreTabs)) {
|
|
80
|
+
// update React state with the list of hidden tabs
|
|
81
|
+
setShowMoreTabs(newShowMoreTabs);
|
|
82
|
+
}
|
|
83
|
+
}, [showMoreTabs]);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const actionElements = containerRef.current?.children || [];
|
|
86
|
+
const resizeObserver = new ResizeObserver(entries => {
|
|
87
|
+
for (const entry of entries) {
|
|
88
|
+
if (entry.contentBoxSize) {
|
|
89
|
+
const contentBoxSize = entry.contentBoxSize[0];
|
|
90
|
+
|
|
91
|
+
// Math.ceil is necessary to round up and return
|
|
92
|
+
// the smallest integer for the size of observed element
|
|
93
|
+
containerVisibleWidth.current = Math.ceil(contentBoxSize.inlineSize);
|
|
94
|
+
|
|
95
|
+
// invoke the functions which calculates tabs visibility
|
|
96
|
+
// and sets data to the list of hidden tabs
|
|
97
|
+
calculateVisibility(actionElements);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// This is to help in cases where useEffect callback is triggered before React repaint.
|
|
103
|
+
if (!isMounted) {
|
|
104
|
+
setTimeout(() => {
|
|
105
|
+
setIsMounted(true);
|
|
106
|
+
calculateVisibility(actionElements);
|
|
107
|
+
}, 500);
|
|
108
|
+
} else {
|
|
109
|
+
// adding ResizeObserver to the observed container
|
|
110
|
+
resizeObserver.observe(containerRef.current);
|
|
111
|
+
}
|
|
112
|
+
}, [calculateVisibility, isMounted]);
|
|
113
|
+
const visibleTabsList = tabsList.filter(tab => tab.isVisible ?? true);
|
|
114
|
+
const showMoreTabsList = visibleTabsList.filter((_tab, i) => showMoreTabs.includes(i));
|
|
115
|
+
const location = useLocation();
|
|
116
|
+
const showMoreItemActive = showMoreTabsList.find(action => location.pathname.endsWith(action.path));
|
|
117
|
+
return /*#__PURE__*/_jsx(TabsContainer, {
|
|
118
|
+
children: /*#__PURE__*/_jsx(TabWrapper, {
|
|
119
|
+
children: /*#__PURE__*/_jsxs(VisibleTabs, {
|
|
120
|
+
style: {
|
|
121
|
+
gap: tabsGap
|
|
122
|
+
},
|
|
123
|
+
ref: containerRef,
|
|
124
|
+
children: [visibleTabsList.map((tab, i) => /*#__PURE__*/_jsx(Tab, {
|
|
125
|
+
className: tab.className,
|
|
126
|
+
id: tab.id,
|
|
127
|
+
"data-testid": tab["data-testid"],
|
|
128
|
+
tabInShowMore: showMoreTabs.includes(i),
|
|
129
|
+
to: tab.path,
|
|
130
|
+
children: tab.label
|
|
131
|
+
}, tab.path)), /*#__PURE__*/_jsx(ActionsMenu, {
|
|
132
|
+
direction: "bottom-end",
|
|
133
|
+
renderTrigger: props => /*#__PURE__*/_jsxs(ShowMoreButton, {
|
|
134
|
+
...props,
|
|
135
|
+
showMoreVisible: showMoreTabsList.length,
|
|
136
|
+
id: "show-more-button",
|
|
137
|
+
className: showMoreItemActive && "hasActive",
|
|
138
|
+
children: [/*#__PURE__*/_jsx(FlexItem, {
|
|
139
|
+
flex: "0 0 auto",
|
|
140
|
+
children: "More"
|
|
141
|
+
}), /*#__PURE__*/_jsx(FlexItem, {
|
|
142
|
+
flex: "0 0 auto",
|
|
143
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
144
|
+
icon: ["fas", "chevron-down"],
|
|
145
|
+
title: "Down",
|
|
146
|
+
ml: "s",
|
|
147
|
+
size: "sm"
|
|
148
|
+
})
|
|
149
|
+
})]
|
|
150
|
+
}),
|
|
151
|
+
closeOnClick: true,
|
|
152
|
+
children: /*#__PURE__*/_jsx(ShowMoreTabs, {
|
|
153
|
+
children: showMoreTabsList.map(tab => /*#__PURE__*/_jsx(ActionsMenuItem, {
|
|
154
|
+
className: tab.className,
|
|
155
|
+
id: tab.id,
|
|
156
|
+
"data-testid": tab["data-testid"],
|
|
157
|
+
Component: Tab,
|
|
158
|
+
fullWidth: true,
|
|
159
|
+
to: tab.path,
|
|
160
|
+
children: tab.label
|
|
161
|
+
}, tab.path))
|
|
162
|
+
})
|
|
163
|
+
})]
|
|
164
|
+
})
|
|
165
|
+
})
|
|
129
166
|
});
|
|
130
|
-
return theme ? /*#__PURE__*/_jsx(ThemeProvider, {
|
|
131
|
-
theme: theme,
|
|
132
|
-
children: component
|
|
133
|
-
}) : component;
|
|
134
167
|
};
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
168
|
+
Tabs.propTypes = {
|
|
169
|
+
/** isVisible defaults to true if not passed */
|
|
170
|
+
tabsList: PropTypes.arrayOf(PropTypes.shape({
|
|
171
|
+
label: PropTypes.string.isRequired,
|
|
172
|
+
path: PropTypes.string.isRequired,
|
|
173
|
+
isVisible: PropTypes.bool
|
|
174
|
+
})).isRequired
|
|
140
175
|
};
|
|
141
|
-
|
|
176
|
+
Tabs.__docgenInfo = {
|
|
142
177
|
"description": "",
|
|
143
178
|
"methods": [],
|
|
144
|
-
"displayName": "
|
|
179
|
+
"displayName": "Tabs",
|
|
145
180
|
"props": {
|
|
146
|
-
"
|
|
147
|
-
"description": "
|
|
148
|
-
"type": {
|
|
149
|
-
"name": "bool"
|
|
150
|
-
},
|
|
151
|
-
"required": false
|
|
152
|
-
},
|
|
153
|
-
"notification": {
|
|
154
|
-
"description": "Specifies any notifications attached to the Tab",
|
|
155
|
-
"type": {
|
|
156
|
-
"name": "string"
|
|
157
|
-
},
|
|
158
|
-
"required": false
|
|
159
|
-
},
|
|
160
|
-
"theme": {
|
|
161
|
-
"description": "Specifies the colour theme",
|
|
162
|
-
"type": {
|
|
163
|
-
"name": "object"
|
|
164
|
-
},
|
|
165
|
-
"required": false
|
|
166
|
-
},
|
|
167
|
-
"children": {
|
|
168
|
-
"description": "The content of the Tab is passed as a child.",
|
|
181
|
+
"tabsList": {
|
|
182
|
+
"description": "isVisible defaults to true if not passed",
|
|
169
183
|
"type": {
|
|
170
|
-
"name": "
|
|
184
|
+
"name": "arrayOf",
|
|
185
|
+
"value": {
|
|
186
|
+
"name": "shape",
|
|
187
|
+
"value": {
|
|
188
|
+
"label": {
|
|
189
|
+
"name": "string",
|
|
190
|
+
"required": true
|
|
191
|
+
},
|
|
192
|
+
"path": {
|
|
193
|
+
"name": "string",
|
|
194
|
+
"required": true
|
|
195
|
+
},
|
|
196
|
+
"isVisible": {
|
|
197
|
+
"name": "bool",
|
|
198
|
+
"required": false
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
171
202
|
},
|
|
172
|
-
"required":
|
|
203
|
+
"required": true
|
|
173
204
|
}
|
|
174
205
|
}
|
|
175
206
|
};
|
|
176
|
-
|
|
177
|
-
"description": "",
|
|
178
|
-
"methods": [],
|
|
179
|
-
"displayName": "TabsContainer",
|
|
180
|
-
"props": {
|
|
181
|
-
"children": {
|
|
182
|
-
"description": "The contents of the TabsContainer are passed as a child.",
|
|
183
|
-
"type": {
|
|
184
|
-
"name": "node"
|
|
185
|
-
},
|
|
186
|
-
"required": false
|
|
187
|
-
},
|
|
188
|
-
"theme": {
|
|
189
|
-
"description": "Specifies the colour theme of the container",
|
|
190
|
-
"type": {
|
|
191
|
-
"name": "object"
|
|
192
|
-
},
|
|
193
|
-
"required": false
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
};
|
|
207
|
+
export default Tabs;
|
package/es/components.test.js
CHANGED
package/es/index.js
CHANGED
|
@@ -37,7 +37,7 @@ export { default as Spacer } from "./components/Spacer";
|
|
|
37
37
|
export { default as StatusDot } from "./components/StatusDot";
|
|
38
38
|
export { default as StyledLink, styleLink } from "./components/StyledLink";
|
|
39
39
|
export { default as Table } from "./components/Table";
|
|
40
|
-
export {
|
|
40
|
+
export { default as Tabs } from "./components/Tabs";
|
|
41
41
|
export { default as Tag } from "./components/Tag";
|
|
42
42
|
export { default as TextInput } from "./components/TextInput";
|
|
43
43
|
export { default as TextArea } from "./components/TextArea";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orcs-design-system",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.42",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": "20.12.2"
|
|
6
6
|
},
|
|
@@ -47,16 +47,15 @@
|
|
|
47
47
|
"@emotion/react": "^11.11.4",
|
|
48
48
|
"@emotion/styled": "^11.11.5",
|
|
49
49
|
"@floating-ui/react": "^0.26.19",
|
|
50
|
-
"@mui/icons-material": "^
|
|
51
|
-
"@mui/material": "^
|
|
52
|
-
"@mui/
|
|
53
|
-
"@mui/x-date-pickers": "^7.16.0",
|
|
50
|
+
"@mui/icons-material": "^5.16.7",
|
|
51
|
+
"@mui/material": "^5.16.7",
|
|
52
|
+
"@mui/x-date-pickers": "^7.14.0",
|
|
54
53
|
"@styled-system/css": "^5.1.5",
|
|
55
54
|
"@styled-system/prop-types": "^5.1.5",
|
|
56
55
|
"@styled-system/should-forward-prop": "^5.1.5",
|
|
57
56
|
"@styled-system/theme-get": "^5.1.2",
|
|
58
57
|
"focus-trap-react": "^10.2.3",
|
|
59
|
-
"material-react-table": "^2.13.
|
|
58
|
+
"material-react-table": "^2.13.2",
|
|
60
59
|
"polished": "^3.7.1",
|
|
61
60
|
"prop-types": "^15.6.2",
|
|
62
61
|
"react-app-polyfill": "^2.0.0",
|
|
@@ -97,7 +96,7 @@
|
|
|
97
96
|
"@storybook/core-events": "^8.1.7",
|
|
98
97
|
"@storybook/manager-api": "^8.1.7",
|
|
99
98
|
"@storybook/mdx1-csf": "^1.0.0",
|
|
100
|
-
"@storybook/preset-create-react-app": "^8.
|
|
99
|
+
"@storybook/preset-create-react-app": "^8.3.3",
|
|
101
100
|
"@storybook/react": "^8.1.7",
|
|
102
101
|
"@storybook/react-webpack5": "^8.2.9",
|
|
103
102
|
"@storybook/storybook-deployer": "2.8.16",
|
|
@@ -161,7 +160,16 @@
|
|
|
161
160
|
"path-to-regexp": "0.1.10"
|
|
162
161
|
},
|
|
163
162
|
"send": "0.19.0",
|
|
164
|
-
"redux": "4.2.1"
|
|
163
|
+
"redux": "4.2.1",
|
|
164
|
+
"workbox-build": {
|
|
165
|
+
"rollup": ">=3.29.5"
|
|
166
|
+
},
|
|
167
|
+
"@rollup/plugin-babel": {
|
|
168
|
+
"rollup": ">=3.29.5"
|
|
169
|
+
},
|
|
170
|
+
"@rollup/plugin-replace": {
|
|
171
|
+
"rollup": ">=3.29.5"
|
|
172
|
+
}
|
|
165
173
|
},
|
|
166
174
|
"browserslist": [
|
|
167
175
|
">0.2%",
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import Box from "../Box";
|
|
3
|
-
import { TabsContainer, Tab } from ".";
|
|
4
|
-
import Popover from "../Popover";
|
|
5
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
-
export default {
|
|
7
|
-
title: "Components/Tabs/Tab",
|
|
8
|
-
decorators: [storyFn => /*#__PURE__*/_jsx(Box, {
|
|
9
|
-
bg: "greyLightest",
|
|
10
|
-
p: "xl",
|
|
11
|
-
children: storyFn()
|
|
12
|
-
})],
|
|
13
|
-
component: Tab
|
|
14
|
-
};
|
|
15
|
-
export const activeTab = () => /*#__PURE__*/_jsxs(TabsContainer, {
|
|
16
|
-
children: [/*#__PURE__*/_jsx(Tab, {
|
|
17
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
18
|
-
href: "#",
|
|
19
|
-
children: "Details"
|
|
20
|
-
})
|
|
21
|
-
}), /*#__PURE__*/_jsx(Tab, {
|
|
22
|
-
active: true,
|
|
23
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
24
|
-
href: "#",
|
|
25
|
-
children: "Planning"
|
|
26
|
-
})
|
|
27
|
-
})]
|
|
28
|
-
});
|
|
29
|
-
activeTab.story = {
|
|
30
|
-
name: "Active Tab"
|
|
31
|
-
};
|
|
32
|
-
export const withNotificationsTab = () => /*#__PURE__*/_jsxs(TabsContainer, {
|
|
33
|
-
children: [/*#__PURE__*/_jsx(Tab, {
|
|
34
|
-
notification: "1",
|
|
35
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
36
|
-
href: "#",
|
|
37
|
-
children: "Details"
|
|
38
|
-
})
|
|
39
|
-
}), /*#__PURE__*/_jsx(Tab, {
|
|
40
|
-
notification: "7",
|
|
41
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
42
|
-
href: "#",
|
|
43
|
-
children: "Planning"
|
|
44
|
-
})
|
|
45
|
-
})]
|
|
46
|
-
});
|
|
47
|
-
activeTab.story = {
|
|
48
|
-
name: "With Notifications Tab"
|
|
49
|
-
};
|
|
50
|
-
export const withPopoverTab = () => /*#__PURE__*/_jsxs(TabsContainer, {
|
|
51
|
-
children: [/*#__PURE__*/_jsx(Popover, {
|
|
52
|
-
direction: "right",
|
|
53
|
-
text: "Example with tooltip explaining tab",
|
|
54
|
-
width: "218px",
|
|
55
|
-
children: /*#__PURE__*/_jsx(Tab, {
|
|
56
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
57
|
-
href: "#",
|
|
58
|
-
children: "Details"
|
|
59
|
-
})
|
|
60
|
-
})
|
|
61
|
-
}), /*#__PURE__*/_jsx(Popover, {
|
|
62
|
-
direction: "top",
|
|
63
|
-
text: "Example with tooltip explaining tab",
|
|
64
|
-
width: "218px",
|
|
65
|
-
children: /*#__PURE__*/_jsx(Tab, {
|
|
66
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
67
|
-
href: "#",
|
|
68
|
-
tabIndex: "-1",
|
|
69
|
-
children: "Additional information"
|
|
70
|
-
})
|
|
71
|
-
})
|
|
72
|
-
})]
|
|
73
|
-
});
|
|
74
|
-
withPopoverTab.story = {
|
|
75
|
-
name: "With Popover Tab"
|
|
76
|
-
};
|
|
77
|
-
activeTab.__docgenInfo = {
|
|
78
|
-
"description": "",
|
|
79
|
-
"methods": [],
|
|
80
|
-
"displayName": "activeTab"
|
|
81
|
-
};
|
|
82
|
-
withNotificationsTab.__docgenInfo = {
|
|
83
|
-
"description": "",
|
|
84
|
-
"methods": [],
|
|
85
|
-
"displayName": "withNotificationsTab"
|
|
86
|
-
};
|
|
87
|
-
withPopoverTab.__docgenInfo = {
|
|
88
|
-
"description": "",
|
|
89
|
-
"methods": [],
|
|
90
|
-
"displayName": "withPopoverTab"
|
|
91
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import Box from "../Box";
|
|
3
|
-
import Popover from "../Popover";
|
|
4
|
-
import { TabsContainer, Tab } from ".";
|
|
5
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
-
export default {
|
|
7
|
-
title: "Components/Tabs",
|
|
8
|
-
decorators: [storyFn => /*#__PURE__*/_jsx(Box, {
|
|
9
|
-
bg: "greyLightest",
|
|
10
|
-
p: "xl",
|
|
11
|
-
children: storyFn()
|
|
12
|
-
})],
|
|
13
|
-
component: TabsContainer
|
|
14
|
-
};
|
|
15
|
-
export const defaultTabs = () => /*#__PURE__*/_jsxs(TabsContainer, {
|
|
16
|
-
children: [/*#__PURE__*/_jsx(Tab, {
|
|
17
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
18
|
-
href: "#",
|
|
19
|
-
children: "Details"
|
|
20
|
-
})
|
|
21
|
-
}), /*#__PURE__*/_jsx(Popover, {
|
|
22
|
-
direction: "top",
|
|
23
|
-
text: "Example with tooltip explaining tab",
|
|
24
|
-
width: "218px",
|
|
25
|
-
children: /*#__PURE__*/_jsx(Tab, {
|
|
26
|
-
active: true,
|
|
27
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
28
|
-
href: "#",
|
|
29
|
-
tabIndex: "-1",
|
|
30
|
-
children: "Additional information"
|
|
31
|
-
})
|
|
32
|
-
})
|
|
33
|
-
}), /*#__PURE__*/_jsx(Tab, {
|
|
34
|
-
notification: "97",
|
|
35
|
-
children: /*#__PURE__*/_jsx("a", {
|
|
36
|
-
href: "#",
|
|
37
|
-
children: "Planning"
|
|
38
|
-
})
|
|
39
|
-
})]
|
|
40
|
-
});
|
|
41
|
-
defaultTabs.story = {
|
|
42
|
-
name: "Default Tabs"
|
|
43
|
-
};
|
|
44
|
-
defaultTabs.__docgenInfo = {
|
|
45
|
-
"description": "",
|
|
46
|
-
"methods": [],
|
|
47
|
-
"displayName": "defaultTabs"
|
|
48
|
-
};
|