@kaizen/components 1.68.11 → 1.68.12
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/dist/cjs/__future__/Tabs/constants.cjs +4 -0
- package/dist/cjs/__future__/Tabs/subcomponents/Tab/Tab.cjs +3 -1
- package/dist/cjs/__future__/Tabs/subcomponents/TabList/TabList.cjs +117 -3
- package/dist/cjs/__future__/Tabs/subcomponents/TabList/TabList.module.css.cjs +4 -1
- package/dist/cjs/__utilities__/isRTL/isRTL.cjs +11 -0
- package/dist/esm/__future__/Tabs/constants.mjs +2 -0
- package/dist/esm/__future__/Tabs/subcomponents/Tab/Tab.mjs +3 -1
- package/dist/esm/__future__/Tabs/subcomponents/TabList/TabList.mjs +121 -5
- package/dist/esm/__future__/Tabs/subcomponents/TabList/TabList.module.css.mjs +4 -1
- package/dist/esm/__utilities__/isRTL/isRTL.mjs +9 -0
- package/dist/styles.css +130 -78
- package/dist/types/__future__/Tabs/constants.d.ts +1 -0
- package/dist/types/__future__/Tabs/subcomponents/TabList/TabList.d.ts +1 -0
- package/dist/types/__utilities__/isRTL/index.d.ts +1 -0
- package/dist/types/__utilities__/isRTL/isRTL.d.ts +5 -0
- package/package.json +3 -3
- package/src/__future__/Tabs/_docs/Tabs.spec.stories.tsx +118 -0
- package/src/__future__/Tabs/_docs/Tabs.stickersheet.stories.tsx +84 -0
- package/src/__future__/Tabs/_docs/Tabs.stories.tsx +12 -1
- package/src/__future__/Tabs/constants.ts +1 -0
- package/src/__future__/Tabs/subcomponents/Tab/Tab.tsx +1 -1
- package/src/__future__/Tabs/subcomponents/TabList/TabList.module.css +53 -1
- package/src/__future__/Tabs/subcomponents/TabList/TabList.tsx +138 -10
- package/src/__utilities__/isRTL/index.ts +1 -0
- package/src/__utilities__/isRTL/isRTL.spec.tsx +38 -0
- package/src/__utilities__/isRTL/isRTL.ts +6 -0
|
@@ -25,7 +25,9 @@ var Tab = function (props) {
|
|
|
25
25
|
var tabProps = tslib.__assign({
|
|
26
26
|
className: classnames__default.default(Tab_module.tab, className)
|
|
27
27
|
}, restProps);
|
|
28
|
-
return React__default.default.createElement(reactAriaComponents.Tab, tslib.__assign({
|
|
28
|
+
return React__default.default.createElement(reactAriaComponents.Tab, tslib.__assign({
|
|
29
|
+
"data-kz-tab": true
|
|
30
|
+
}, tabProps), function (_a) {
|
|
29
31
|
var isSelected = _a.isSelected,
|
|
30
32
|
isFocusVisible = _a.isFocusVisible,
|
|
31
33
|
isHovered = _a.isHovered;
|
|
@@ -4,6 +4,9 @@ var tslib = require('tslib');
|
|
|
4
4
|
var React = require('react');
|
|
5
5
|
var classnames = require('classnames');
|
|
6
6
|
var reactAriaComponents = require('react-aria-components');
|
|
7
|
+
var Icon = require('../../../Icon/Icon.cjs');
|
|
8
|
+
var isRTL = require('../../../../__utilities__/isRTL/isRTL.cjs');
|
|
9
|
+
var constants = require('../../constants.cjs');
|
|
7
10
|
var TabList_module = require('./TabList.module.css.cjs');
|
|
8
11
|
function _interopDefault(e) {
|
|
9
12
|
return e && e.__esModule ? e : {
|
|
@@ -22,10 +25,121 @@ var TabList = function (props) {
|
|
|
22
25
|
noPadding = _a === void 0 ? false : _a,
|
|
23
26
|
children = props.children,
|
|
24
27
|
className = props.className,
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
testId = props["data-testid"],
|
|
29
|
+
restProps = tslib.__rest(props, ['aria-label', "noPadding", "children", "className", 'data-testid']);
|
|
30
|
+
var _b = React.useState(false),
|
|
31
|
+
isDocumentReady = _b[0],
|
|
32
|
+
setIsDocumentReady = _b[1];
|
|
33
|
+
var _c = React.useState(false),
|
|
34
|
+
leftArrowEnabled = _c[0],
|
|
35
|
+
setLeftArrowEnabled = _c[1];
|
|
36
|
+
var _d = React.useState(false),
|
|
37
|
+
rightArrowEnabled = _d[0],
|
|
38
|
+
setRightArrowEnabled = _d[1];
|
|
39
|
+
var tabListRef = React.useRef(null);
|
|
40
|
+
var tabListId = React.useId();
|
|
41
|
+
var _e = React.useState(false),
|
|
42
|
+
isRTL$1 = _e[0],
|
|
43
|
+
setIsRTL = _e[1];
|
|
44
|
+
var _f = React.useState(),
|
|
45
|
+
containerElement = _f[0],
|
|
46
|
+
setContainerElement = _f[1];
|
|
47
|
+
var tabListContext = React.useContext(reactAriaComponents.TabListStateContext);
|
|
48
|
+
var selectedKey = tabListContext === null || tabListContext === void 0 ? void 0 : tabListContext.selectedKey;
|
|
49
|
+
React.useEffect(function () {
|
|
50
|
+
if (!isDocumentReady) {
|
|
51
|
+
setIsDocumentReady(true);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
var container = document.getElementById(tabListId);
|
|
55
|
+
setContainerElement(container);
|
|
56
|
+
setIsRTL(container ? isRTL.isRTL(container) : false);
|
|
57
|
+
}, [isDocumentReady, tabListId]);
|
|
58
|
+
React.useEffect(function () {
|
|
59
|
+
if (!isDocumentReady) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
var tabs = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelectorAll('[data-kz-tab]');
|
|
63
|
+
if (!tabs) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
var firstTabObserver = new IntersectionObserver(function (entries) {
|
|
67
|
+
if (!entries[0].isIntersecting) {
|
|
68
|
+
setLeftArrowEnabled(true);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
setLeftArrowEnabled(false);
|
|
72
|
+
}, {
|
|
73
|
+
threshold: 0.75,
|
|
74
|
+
root: containerElement
|
|
75
|
+
});
|
|
76
|
+
firstTabObserver.observe(isRTL$1 ? tabs[tabs.length - 1] : tabs[0]);
|
|
77
|
+
var lastTabObserver = new IntersectionObserver(function (entries) {
|
|
78
|
+
if (!entries[0].isIntersecting) {
|
|
79
|
+
setRightArrowEnabled(true);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
setRightArrowEnabled(false);
|
|
83
|
+
}, {
|
|
84
|
+
threshold: 0.75,
|
|
85
|
+
root: containerElement
|
|
86
|
+
});
|
|
87
|
+
lastTabObserver.observe(isRTL$1 ? tabs[0] : tabs[tabs.length - 1]);
|
|
88
|
+
return function () {
|
|
89
|
+
firstTabObserver.disconnect();
|
|
90
|
+
lastTabObserver.disconnect();
|
|
91
|
+
};
|
|
92
|
+
}, [isDocumentReady, containerElement, isRTL$1]);
|
|
93
|
+
React.useEffect(function () {
|
|
94
|
+
var _a;
|
|
95
|
+
if (!isDocumentReady) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Scroll selected tab into view
|
|
99
|
+
(_a = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector('[role="tab"][data-selected=true]')) === null || _a === void 0 ? void 0 : _a.scrollIntoView({
|
|
100
|
+
block: 'nearest',
|
|
101
|
+
inline: 'center'
|
|
102
|
+
});
|
|
103
|
+
}, [selectedKey, containerElement, isDocumentReady]);
|
|
104
|
+
var handleArrowPress = function (direction) {
|
|
105
|
+
if (tabListRef.current) {
|
|
106
|
+
var tabListScrollPos = tabListRef.current.scrollLeft;
|
|
107
|
+
var newSpot = direction === 'left' ? tabListScrollPos - constants.SCROLL_AMOUNT : tabListScrollPos + constants.SCROLL_AMOUNT;
|
|
108
|
+
tabListRef.current.scrollLeft = newSpot;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
return React__default.default.createElement("div", {
|
|
112
|
+
className: TabList_module.container,
|
|
113
|
+
id: tabListId
|
|
114
|
+
}, leftArrowEnabled &&
|
|
115
|
+
// making a conscious decision to use <div onClick> over <button> here, because:
|
|
116
|
+
// - <button> would add pointless noise for a screen reader user
|
|
117
|
+
// - keyboard only user can toggle through tabs with left/right arrow keys already
|
|
118
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
119
|
+
React__default.default.createElement("div", {
|
|
120
|
+
onClick: function () {
|
|
121
|
+
return handleArrowPress('left');
|
|
122
|
+
},
|
|
123
|
+
className: TabList_module.leftArrow,
|
|
124
|
+
"data-testid": testId ? "".concat(testId, "-kz-tablist-left-arrow") : undefined
|
|
125
|
+
}, React__default.default.createElement(Icon.Icon, {
|
|
126
|
+
name: "chevron_left",
|
|
127
|
+
isPresentational: true
|
|
128
|
+
})), React__default.default.createElement(reactAriaComponents.TabList, tslib.__assign({
|
|
27
129
|
"aria-label": ariaLabel,
|
|
130
|
+
ref: tabListRef,
|
|
28
131
|
className: classnames__default.default(TabList_module.tabList, className, noPadding && TabList_module.noPadding)
|
|
29
|
-
}, restProps), children)
|
|
132
|
+
}, restProps), children), rightArrowEnabled &&
|
|
133
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
134
|
+
React__default.default.createElement("div", {
|
|
135
|
+
onClick: function () {
|
|
136
|
+
return handleArrowPress('right');
|
|
137
|
+
},
|
|
138
|
+
className: TabList_module.rightArrow,
|
|
139
|
+
"data-testid": testId ? "".concat(testId, "-kz-tablist-right-arrow") : undefined
|
|
140
|
+
}, React__default.default.createElement(Icon.Icon, {
|
|
141
|
+
name: "chevron_right",
|
|
142
|
+
isPresentational: true
|
|
143
|
+
})));
|
|
30
144
|
};
|
|
31
145
|
exports.TabList = TabList;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var styles = {
|
|
4
|
+
"container": "TabList-module_container__Z8JCa",
|
|
4
5
|
"tabList": "TabList-module_tabList__e1qAi",
|
|
5
|
-
"noPadding": "TabList-module_noPadding__YM23K"
|
|
6
|
+
"noPadding": "TabList-module_noPadding__YM23K",
|
|
7
|
+
"leftArrow": "TabList-module_leftArrow__CPchY",
|
|
8
|
+
"rightArrow": "TabList-module_rightArrow__0xcW1"
|
|
6
9
|
};
|
|
7
10
|
module.exports = styles;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Finds the first ancestor with a `dir` property on it
|
|
5
|
+
* Returning true is that is `dir=rtl` and returning false in all other cases
|
|
6
|
+
*/
|
|
7
|
+
var isRTL = function (element) {
|
|
8
|
+
var _a;
|
|
9
|
+
return !!((_a = element.closest('[dir]')) === null || _a === void 0 ? void 0 : _a.matches('[dir="rtl"]'));
|
|
10
|
+
};
|
|
11
|
+
exports.isRTL = isRTL;
|
|
@@ -16,7 +16,9 @@ var Tab = function (props) {
|
|
|
16
16
|
var tabProps = __assign({
|
|
17
17
|
className: classnames(styles.tab, className)
|
|
18
18
|
}, restProps);
|
|
19
|
-
return /*#__PURE__*/React.createElement(Tab$1, __assign({
|
|
19
|
+
return /*#__PURE__*/React.createElement(Tab$1, __assign({
|
|
20
|
+
"data-kz-tab": true
|
|
21
|
+
}, tabProps), function (_a) {
|
|
20
22
|
var isSelected = _a.isSelected,
|
|
21
23
|
isFocusVisible = _a.isFocusVisible,
|
|
22
24
|
isHovered = _a.isHovered;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { __rest, __assign } from 'tslib';
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import React, { useState, useRef, useId, useContext, useEffect } from 'react';
|
|
3
3
|
import classnames from 'classnames';
|
|
4
|
-
import { TabList as TabList$1 } from 'react-aria-components';
|
|
4
|
+
import { TabListStateContext, TabList as TabList$1 } from 'react-aria-components';
|
|
5
|
+
import { Icon } from '../../../Icon/Icon.mjs';
|
|
6
|
+
import { isRTL } from '../../../../__utilities__/isRTL/isRTL.mjs';
|
|
7
|
+
import { SCROLL_AMOUNT } from '../../constants.mjs';
|
|
5
8
|
import styles from './TabList.module.css.mjs';
|
|
6
9
|
|
|
7
10
|
/**
|
|
@@ -13,10 +16,123 @@ var TabList = function (props) {
|
|
|
13
16
|
noPadding = _a === void 0 ? false : _a,
|
|
14
17
|
children = props.children,
|
|
15
18
|
className = props.className,
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
testId = props["data-testid"],
|
|
20
|
+
restProps = __rest(props, ['aria-label', "noPadding", "children", "className", 'data-testid']);
|
|
21
|
+
var _b = useState(false),
|
|
22
|
+
isDocumentReady = _b[0],
|
|
23
|
+
setIsDocumentReady = _b[1];
|
|
24
|
+
var _c = useState(false),
|
|
25
|
+
leftArrowEnabled = _c[0],
|
|
26
|
+
setLeftArrowEnabled = _c[1];
|
|
27
|
+
var _d = useState(false),
|
|
28
|
+
rightArrowEnabled = _d[0],
|
|
29
|
+
setRightArrowEnabled = _d[1];
|
|
30
|
+
var tabListRef = useRef(null);
|
|
31
|
+
var tabListId = useId();
|
|
32
|
+
var _e = useState(false),
|
|
33
|
+
isRTL$1 = _e[0],
|
|
34
|
+
setIsRTL = _e[1];
|
|
35
|
+
var _f = useState(),
|
|
36
|
+
containerElement = _f[0],
|
|
37
|
+
setContainerElement = _f[1];
|
|
38
|
+
var tabListContext = useContext(TabListStateContext);
|
|
39
|
+
var selectedKey = tabListContext === null || tabListContext === void 0 ? void 0 : tabListContext.selectedKey;
|
|
40
|
+
useEffect(function () {
|
|
41
|
+
if (!isDocumentReady) {
|
|
42
|
+
setIsDocumentReady(true);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
var container = document.getElementById(tabListId);
|
|
46
|
+
setContainerElement(container);
|
|
47
|
+
setIsRTL(container ? isRTL(container) : false);
|
|
48
|
+
}, [isDocumentReady, tabListId]);
|
|
49
|
+
useEffect(function () {
|
|
50
|
+
if (!isDocumentReady) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
var tabs = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelectorAll('[data-kz-tab]');
|
|
54
|
+
if (!tabs) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
var firstTabObserver = new IntersectionObserver(function (entries) {
|
|
58
|
+
if (!entries[0].isIntersecting) {
|
|
59
|
+
setLeftArrowEnabled(true);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
setLeftArrowEnabled(false);
|
|
63
|
+
}, {
|
|
64
|
+
threshold: 0.75,
|
|
65
|
+
root: containerElement
|
|
66
|
+
});
|
|
67
|
+
firstTabObserver.observe(isRTL$1 ? tabs[tabs.length - 1] : tabs[0]);
|
|
68
|
+
var lastTabObserver = new IntersectionObserver(function (entries) {
|
|
69
|
+
if (!entries[0].isIntersecting) {
|
|
70
|
+
setRightArrowEnabled(true);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
setRightArrowEnabled(false);
|
|
74
|
+
}, {
|
|
75
|
+
threshold: 0.75,
|
|
76
|
+
root: containerElement
|
|
77
|
+
});
|
|
78
|
+
lastTabObserver.observe(isRTL$1 ? tabs[0] : tabs[tabs.length - 1]);
|
|
79
|
+
return function () {
|
|
80
|
+
firstTabObserver.disconnect();
|
|
81
|
+
lastTabObserver.disconnect();
|
|
82
|
+
};
|
|
83
|
+
}, [isDocumentReady, containerElement, isRTL$1]);
|
|
84
|
+
useEffect(function () {
|
|
85
|
+
var _a;
|
|
86
|
+
if (!isDocumentReady) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Scroll selected tab into view
|
|
90
|
+
(_a = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector('[role="tab"][data-selected=true]')) === null || _a === void 0 ? void 0 : _a.scrollIntoView({
|
|
91
|
+
block: 'nearest',
|
|
92
|
+
inline: 'center'
|
|
93
|
+
});
|
|
94
|
+
}, [selectedKey, containerElement, isDocumentReady]);
|
|
95
|
+
var handleArrowPress = function (direction) {
|
|
96
|
+
if (tabListRef.current) {
|
|
97
|
+
var tabListScrollPos = tabListRef.current.scrollLeft;
|
|
98
|
+
var newSpot = direction === 'left' ? tabListScrollPos - SCROLL_AMOUNT : tabListScrollPos + SCROLL_AMOUNT;
|
|
99
|
+
tabListRef.current.scrollLeft = newSpot;
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
103
|
+
className: styles.container,
|
|
104
|
+
id: tabListId
|
|
105
|
+
}, leftArrowEnabled && (
|
|
106
|
+
/*#__PURE__*/
|
|
107
|
+
// making a conscious decision to use <div onClick> over <button> here, because:
|
|
108
|
+
// - <button> would add pointless noise for a screen reader user
|
|
109
|
+
// - keyboard only user can toggle through tabs with left/right arrow keys already
|
|
110
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
111
|
+
React.createElement("div", {
|
|
112
|
+
onClick: function () {
|
|
113
|
+
return handleArrowPress('left');
|
|
114
|
+
},
|
|
115
|
+
className: styles.leftArrow,
|
|
116
|
+
"data-testid": testId ? "".concat(testId, "-kz-tablist-left-arrow") : undefined
|
|
117
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
118
|
+
name: "chevron_left",
|
|
119
|
+
isPresentational: true
|
|
120
|
+
}))), /*#__PURE__*/React.createElement(TabList$1, __assign({
|
|
18
121
|
"aria-label": ariaLabel,
|
|
122
|
+
ref: tabListRef,
|
|
19
123
|
className: classnames(styles.tabList, className, noPadding && styles.noPadding)
|
|
20
|
-
}, restProps), children)
|
|
124
|
+
}, restProps), children), rightArrowEnabled && (
|
|
125
|
+
/*#__PURE__*/
|
|
126
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
127
|
+
React.createElement("div", {
|
|
128
|
+
onClick: function () {
|
|
129
|
+
return handleArrowPress('right');
|
|
130
|
+
},
|
|
131
|
+
className: styles.rightArrow,
|
|
132
|
+
"data-testid": testId ? "".concat(testId, "-kz-tablist-right-arrow") : undefined
|
|
133
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
134
|
+
name: "chevron_right",
|
|
135
|
+
isPresentational: true
|
|
136
|
+
}))));
|
|
21
137
|
};
|
|
22
138
|
export { TabList };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
var styles = {
|
|
2
|
+
"container": "TabList-module_container__Z8JCa",
|
|
2
3
|
"tabList": "TabList-module_tabList__e1qAi",
|
|
3
|
-
"noPadding": "TabList-module_noPadding__YM23K"
|
|
4
|
+
"noPadding": "TabList-module_noPadding__YM23K",
|
|
5
|
+
"leftArrow": "TabList-module_leftArrow__CPchY",
|
|
6
|
+
"rightArrow": "TabList-module_rightArrow__0xcW1"
|
|
4
7
|
};
|
|
5
8
|
export { styles as default };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finds the first ancestor with a `dir` property on it
|
|
3
|
+
* Returning true is that is `dir=rtl` and returning false in all other cases
|
|
4
|
+
*/
|
|
5
|
+
var isRTL = function (element) {
|
|
6
|
+
var _a;
|
|
7
|
+
return !!((_a = element.closest('[dir]')) === null || _a === void 0 ? void 0 : _a.matches('[dir="rtl"]'));
|
|
8
|
+
};
|
|
9
|
+
export { isRTL };
|
package/dist/styles.css
CHANGED
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
@layer tokens, normalize, reset;@layer tokens{:root{--theme-key:heart;--animation-easing-function-ease-in-out:cubic-bezier(0.455,0.03,0.515,0.955);--animation-easing-function-ease-in:cubic-bezier(0.55,0.085,0.68,0.53);--animation-easing-function-ease-out:cubic-bezier(0.25,0.46,0.45,0.94);--animation-easing-function-linear:linear;--animation-easing-function-bounce-in:cubic-bezier(0.485,0.155,0.24,1.245);--animation-easing-function-bounce-out:cubic-bezier(0.485,0.155,0.515,0.845);--animation-easing-function-bounce-in-out:cubic-bezier(0.76,-0.245,0.24,1.245);--animation-duration-instant:0ms;--animation-duration-immediate:100ms;--animation-duration-rapid:200ms;--animation-duration-fast:300ms;--animation-duration-slow:400ms;--animation-duration-deliberate:700ms;--border-solid-border-width:2px;--border-solid-border-radius:7px;--border-solid-border-style:solid;--border-solid-border-color:#e1e2ea;--border-solid-border-color-rgb:225,226,234;--border-dashed-border-width:2px;--border-dashed-border-radius:7px;--border-dashed-border-style:dashed;--border-borderless-border-width:2px;--border-borderless-border-radius:7px;--border-borderless-border-style:solid;--border-borderless-border-color:transparent;--border-borderless-border-color-rgb:0,0,0;--border-focus-ring-border-width:2px;--border-focus-ring-border-radius:10px;--border-focus-ring-border-style:solid;--border-width-1:1px;--color-purple-100:#f4edf8;--color-purple-100-rgb:244,237,248;--color-purple-200:#dfc9ea;--color-purple-200-rgb:223,201,234;--color-purple-300:#c9a5dd;--color-purple-300-rgb:201,165,221;--color-purple-400:#ae67b1;--color-purple-400-rgb:174,103,177;--color-purple-500:#844587;--color-purple-500-rgb:132,69,135;--color-purple-600:#5f3361;--color-purple-600-rgb:95,51,97;--color-purple-700:#4a234d;--color-purple-700-rgb:74,35,77;--color-purple-800:#2f2438;--color-purple-800-rgb:47,36,56;--color-blue-100:#e6f6ff;--color-blue-100-rgb:230,246,255;--color-blue-200:#bde2f5;--color-blue-200-rgb:189,226,245;--color-blue-300:#73c0e8;--color-blue-300-rgb:115,192,232;--color-blue-400:#008bd6;--color-blue-400-rgb:0,139,214;--color-blue-500:#0168b3;--color-blue-500-rgb:1,104,179;--color-blue-600:#004970;--color-blue-600-rgb:0,73,112;--color-blue-700:#003157;--color-blue-700-rgb:0,49,87;--color-green-100:#e8f8f4;--color-green-100-rgb:232,248,244;--color-green-200:#c4ede2;--color-green-200-rgb:196,237,226;--color-green-300:#8fdbc7;--color-green-300-rgb:143,219,199;--color-green-400:#5dcaad;--color-green-400-rgb:93,202,173;--color-green-500:#3f9a86;--color-green-500-rgb:63,154,134;--color-green-600:#2c7d67;--color-green-600-rgb:44,125,103;--color-green-700:#22594a;--color-green-700-rgb:34,89,74;--color-yellow-100:#fff9e4;--color-yellow-100-rgb:255,249,228;--color-yellow-200:#ffeeb3;--color-yellow-200-rgb:255,238,179;--color-yellow-300:#ffe36e;--color-yellow-300-rgb:255,227,110;--color-yellow-400:#ffca4d;--color-yellow-400-rgb:255,202,77;--color-yellow-500:#ffb600;--color-yellow-500-rgb:255,182,0;--color-yellow-600:#c68600;--color-yellow-600-rgb:198,134,0;--color-yellow-700:#876400;--color-yellow-700-rgb:135,100,0;--color-red-100:#fdeaee;--color-red-100-rgb:253,234,238;--color-red-200:#f9c2cb;--color-red-200-rgb:249,194,203;--color-red-300:#f597a8;--color-red-300-rgb:245,151,168;--color-red-400:#e0707d;--color-red-400-rgb:224,112,125;--color-red-500:#c93b55;--color-red-500-rgb:201,59,85;--color-red-600:#a82433;--color-red-600-rgb:168,36,51;--color-red-700:#6c1e20;--color-red-700-rgb:108,30,32;--color-orange-100:#fff0e8;--color-orange-100-rgb:255,240,232;--color-orange-200:#ffd1b9;--color-orange-200-rgb:255,209,185;--color-orange-300:#ffb08a;--color-orange-300-rgb:255,176,138;--color-orange-400:#ff9461;--color-orange-400-rgb:255,148,97;--color-orange-500:#e96c2f;--color-orange-500-rgb:233,108,47;--color-orange-600:#b74302;--color-orange-600-rgb:183,67,2;--color-orange-700:#903c00;--color-orange-700-rgb:144,60,0;--color-gray-100:#f9f9f9;--color-gray-100-rgb:249,249,249;--color-gray-200:#f4f4f5;--color-gray-200-rgb:244,244,245;--color-gray-300:#eaeaec;--color-gray-300-rgb:234,234,236;--color-gray-400:#cdcdd0;--color-gray-400-rgb:205,205,208;--color-gray-500:#878792;--color-gray-500-rgb:135,135,146;--color-gray-600:#524e56;--color-gray-600-rgb:82,78,86;--color-white:#fff;--color-white-rgb:255,255,255;--color-black:#000;--color-black-rgb:0,0,0;--data-viz-favorable:#7dd5bd;--data-viz-favorable-rgb:125,213,189;--data-viz-unfavorable:#e68d97;--data-viz-unfavorable-rgb:230,141,151;--layout-content-max-width:1392px;--layout-content-max-width-with-sidebar:1080px;--layout-content-side-margin:72px;--layout-mobile-actions-drawer-height:60px;--layout-navigation-bar-height:72px;--layout-breakpoints-medium:768px;--layout-breakpoints-large:1080px;--shadow-small-box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 3px 16px 0 rgba(0,0,0,.06);--shadow-large-box-shadow:0 3px 9px 0 rgba(0,0,0,.1),0 8px 40px 0 rgba(0,0,0,.08);--spacing-0:0;--spacing-1:.0625rem;--spacing-2:.125rem;--spacing-4:.25rem;--spacing-6:.375rem;--spacing-8:.5rem;--spacing-12:.75rem;--spacing-16:1rem;--spacing-20:1.25rem;--spacing-24:1.5rem;--spacing-32:2rem;--spacing-40:2.5rem;--spacing-48:3rem;--spacing-56:3.5rem;--spacing-64:4rem;--spacing-72:4.5rem;--spacing-80:5rem;--spacing-96:6rem;--spacing-112:7rem;--spacing-128:8rem;--spacing-160:10rem;--spacing-200:12.5rem;--spacing-240:15rem;--spacing-280:17.5rem;--spacing-320:20rem;--spacing-xs:0.375rem;--spacing-sm:0.75rem;--spacing-md:1.5rem;--spacing-lg:2.25rem;--spacing-xl:3rem;--spacing-xxl:3.75rem;--spacing-xxxl:4.5rem;--spacing-xxxxl:5.25rem;--spacing-xxxxxl:6rem;--typography-data-large-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-large-font-weight:700;--typography-data-large-font-size:5.25rem;--typography-data-large-line-height:5.25rem;--typography-data-large-letter-spacing:normal;--typography-data-large-units-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-large-units-font-weight:700;--typography-data-large-units-font-size:2.625rem;--typography-data-large-units-line-height:5.25rem;--typography-data-large-units-letter-spacing:normal;--typography-data-medium-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-medium-font-weight:700;--typography-data-medium-font-size:3rem;--typography-data-medium-line-height:5rem;--typography-data-medium-letter-spacing:normal;--typography-data-medium-units-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-medium-units-font-weight:700;--typography-data-medium-units-font-size:1.5rem;--typography-data-medium-units-line-height:5rem;--typography-data-medium-units-letter-spacing:normal;--typography-data-small-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-small-font-weight:700;--typography-data-small-font-size:1.5rem;--typography-data-small-line-height:1.5rem;--typography-data-small-letter-spacing:normal;--typography-data-small-units-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-data-small-units-font-weight:700;--typography-data-small-units-font-size:1.125rem;--typography-data-small-units-line-height:1.5rem;--typography-data-small-units-letter-spacing:normal;--typography-display-0-font-family:"Tiempos Headline",Georgia,serif;--typography-display-0-font-weight:800;--typography-display-0-font-size:4.5rem;--typography-display-0-line-height:5.25rem;--typography-display-0-letter-spacing:0em;--typography-heading-1-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-1-font-weight:500;--typography-heading-1-font-size:2.125rem;--typography-heading-1-line-height:2.625rem;--typography-heading-1-letter-spacing:normal;--typography-heading-2-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-2-font-weight:600;--typography-heading-2-font-size:1.75rem;--typography-heading-2-line-height:2.25rem;--typography-heading-2-letter-spacing:normal;--typography-heading-3-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-3-font-weight:600;--typography-heading-3-font-size:1.375rem;--typography-heading-3-line-height:1.875rem;--typography-heading-3-letter-spacing:normal;--typography-heading-4-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-4-font-weight:600;--typography-heading-4-font-size:1.125rem;--typography-heading-4-line-height:1.5rem;--typography-heading-4-letter-spacing:normal;--typography-heading-5-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-5-font-weight:600;--typography-heading-5-font-size:1rem;--typography-heading-5-line-height:1.5rem;--typography-heading-5-letter-spacing:normal;--typography-heading-6-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-heading-6-font-weight:600;--typography-heading-6-font-size:0.875rem;--typography-heading-6-line-height:1.5rem;--typography-heading-6-letter-spacing:normal;--typography-paragraph-intro-lede-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-paragraph-intro-lede-font-weight:400;--typography-paragraph-intro-lede-font-size:1.25rem;--typography-paragraph-intro-lede-line-height:1.875rem;--typography-paragraph-intro-lede-letter-spacing:0;--typography-paragraph-intro-lede-max-width:975px;--typography-paragraph-body-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-paragraph-body-font-weight:400;--typography-paragraph-body-font-size:1rem;--typography-paragraph-body-line-height:1.5rem;--typography-paragraph-body-letter-spacing:normal;--typography-paragraph-body-max-width:780px;--typography-paragraph-small-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-paragraph-small-font-weight:400;--typography-paragraph-small-font-size:0.875rem;--typography-paragraph-small-line-height:1.125rem;--typography-paragraph-small-letter-spacing:normal;--typography-paragraph-small-max-width:680px;--typography-paragraph-extra-small-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-paragraph-extra-small-font-weight:400;--typography-paragraph-extra-small-font-size:0.75rem;--typography-paragraph-extra-small-line-height:1.125rem;--typography-paragraph-extra-small-letter-spacing:normal;--typography-paragraph-extra-small-max-width:600px;--typography-paragraph-bold-font-weight:600;--typography-button-primary-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-button-primary-font-weight:500;--typography-button-primary-font-size:1.125rem;--typography-button-primary-line-height:1.5rem;--typography-button-primary-letter-spacing:normal;--typography-button-secondary-font-family:"Inter","Noto Sans",Helvetica,Arial,sans-serif;--typography-button-secondary-font-weight:500;--typography-button-secondary-font-size:1rem;--typography-button-secondary-line-height:1.5rem;--typography-button-secondary-letter-spacing:normal}}@layer normalize{html{text-size-adjust:100%;line-height:1.15}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{appearance:none}::-webkit-file-upload-button{appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}}@layer reset{@font-face{font-family:Tiempos Headline;font-weight:800;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/tiempos/tiempos-headline-bold.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/tiempos/tiempos-headline-bold.woff)}@font-face{font-family:Tiempos Headline;font-weight:500;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/tiempos/tiempos-headline-medium.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/tiempos/tiempos-headline-medium.woff)}@font-face{font-family:Greycliff CF;font-weight:300;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-light.woff) format("woff")}@font-face{font-family:Greycliff CF;font-weight:400;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-regular.woff) format("woff")}@font-face{font-family:Greycliff CF;font-weight:500;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-medium.woff) format("woff")}@font-face{font-family:Greycliff CF;font-weight:600;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-demi-bold.woff) format("woff")}@font-face{font-family:Greycliff CF;font-weight:700;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-bold.woff) format("woff")}@font-face{font-family:Greycliff CF;font-weight:800;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/greycliff/greycliff-cf-extra-bold.woff) format("woff")}@font-face{font-family:Inter;font-weight:300;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-light.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-light.woff)}@font-face{font-family:Inter;font-weight:400;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-regular.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-regular.woff)}@font-face{font-family:Inter;font-weight:500;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-medium.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-medium.woff)}@font-face{font-family:Inter;font-weight:600;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-demi-bold.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-demi-bold.woff)}@font-face{font-family:Inter;font-weight:700;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-bold.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-bold.woff)}@font-face{font-family:Inter;font-weight:800;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-extra-bold.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/inter/inter-extra-bold.woff)}@font-face{font-family:IBM Plex Mono;src:url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/ibm-plex-mono/ibm-plex-mono-regular.woff2),url(https://d1e7r7b0lb8p4d.cloudfront.net/fonts/ibm-plex-mono/ibm-plex-mono-regular.woff)}}@layer reset{*,:after,:before{border-color:var(--border-solid-border-color,"currentColor");border-style:solid;border-width:0}}
|
|
2
|
+
.Menu-module_menu__AowD8 {
|
|
3
|
+
background-color: var(--color-white);
|
|
4
|
+
color: var(--color-purple-800);
|
|
5
|
+
width: 248px;
|
|
6
|
+
max-height: 22rem;
|
|
7
|
+
overflow: auto;
|
|
8
|
+
padding-block: var(--spacing-6);
|
|
9
|
+
outline: none;
|
|
10
|
+
border-radius: var(--border-solid-border-radius);
|
|
11
|
+
box-shadow: var(--shadow-large-box-shadow);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.Menu-module_menu__AowD8 .react-aria-Header {
|
|
15
|
+
font-family: var(--typography-heading-6-font-family);
|
|
16
|
+
font-size: var(--typography-heading-6-font-size);
|
|
17
|
+
letter-spacing: var(--typography-heading-6-letter-spacing);
|
|
18
|
+
font-weight: var(--typography-heading-6-font-weight);
|
|
19
|
+
line-height: var(--typography-heading-6-line-height);
|
|
20
|
+
padding: var(--spacing-6) 10px;
|
|
21
|
+
margin-inline: var(--spacing-6);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.Menu-module_menu__AowD8 section:not(:last-of-type) {
|
|
25
|
+
&::after {
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 1px;
|
|
28
|
+
background-color: var(--border-solid-border-color);
|
|
29
|
+
content: '';
|
|
30
|
+
display: block;
|
|
31
|
+
margin-block: var(--spacing-6);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
2
35
|
.MenuItem-module_item__uImZI {
|
|
3
36
|
display: block;
|
|
4
37
|
font-family: var(--typography-paragraph-body-font-family);
|
|
@@ -46,39 +79,6 @@
|
|
|
46
79
|
opacity: 0.3;
|
|
47
80
|
}
|
|
48
81
|
|
|
49
|
-
.Menu-module_menu__AowD8 {
|
|
50
|
-
background-color: var(--color-white);
|
|
51
|
-
color: var(--color-purple-800);
|
|
52
|
-
width: 248px;
|
|
53
|
-
max-height: 22rem;
|
|
54
|
-
overflow: auto;
|
|
55
|
-
padding-block: var(--spacing-6);
|
|
56
|
-
outline: none;
|
|
57
|
-
border-radius: var(--border-solid-border-radius);
|
|
58
|
-
box-shadow: var(--shadow-large-box-shadow);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.Menu-module_menu__AowD8 .react-aria-Header {
|
|
62
|
-
font-family: var(--typography-heading-6-font-family);
|
|
63
|
-
font-size: var(--typography-heading-6-font-size);
|
|
64
|
-
letter-spacing: var(--typography-heading-6-letter-spacing);
|
|
65
|
-
font-weight: var(--typography-heading-6-font-weight);
|
|
66
|
-
line-height: var(--typography-heading-6-line-height);
|
|
67
|
-
padding: var(--spacing-6) 10px;
|
|
68
|
-
margin-inline: var(--spacing-6);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.Menu-module_menu__AowD8 section:not(:last-of-type) {
|
|
72
|
-
&::after {
|
|
73
|
-
width: 100%;
|
|
74
|
-
height: 1px;
|
|
75
|
-
background-color: var(--border-solid-border-color);
|
|
76
|
-
content: '';
|
|
77
|
-
display: block;
|
|
78
|
-
margin-block: var(--spacing-6);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
82
|
.Button-module_button__vlUCI {
|
|
83
83
|
/* RESET */
|
|
84
84
|
appearance: none;
|
|
@@ -312,26 +312,6 @@
|
|
|
312
312
|
visibility: hidden;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
.ButtonContent-module_buttonContent__v5mHZ {
|
|
316
|
-
display: inline-flex;
|
|
317
|
-
align-items: center;
|
|
318
|
-
gap: var(--button-icon-gap, var(--spacing-6));
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
.ButtonContent-module_large__mLOdb {
|
|
322
|
-
--button-icon-gap: var(--spacing-8);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
.ButtonContent-module_buttonLabel__T5XAq {
|
|
326
|
-
display: inline-flex;
|
|
327
|
-
align-items: center;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
.ButtonContent-module_buttonIcon__qkAX- {
|
|
331
|
-
display: inline-flex;
|
|
332
|
-
align-items: center;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
315
|
.PendingContent-module_pendingContent__c4IFS {
|
|
336
316
|
display: inline-flex;
|
|
337
317
|
align-items: center;
|
|
@@ -349,34 +329,26 @@
|
|
|
349
329
|
transform: translate(-50%, -50%);
|
|
350
330
|
}
|
|
351
331
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
padding: 8px;
|
|
357
|
-
}
|
|
358
|
-
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=top], .OverlayArrow-module_overlayArrow__hoDyK[data-placement=bottom] {
|
|
359
|
-
padding: 0 8px;
|
|
360
|
-
}
|
|
361
|
-
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=left], .OverlayArrow-module_overlayArrow__hoDyK[data-placement=right] {
|
|
362
|
-
padding: 8px 0;
|
|
363
|
-
}
|
|
364
|
-
.OverlayArrow-module_overlayArrow__hoDyK path {
|
|
365
|
-
fill: var(--color-purple-800, #2f2438);
|
|
366
|
-
box-shadow: var(--shadow-small-box-shadow, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06));
|
|
367
|
-
}
|
|
368
|
-
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=right] svg {
|
|
369
|
-
transform: rotate(90deg);
|
|
332
|
+
.ButtonContent-module_buttonContent__v5mHZ {
|
|
333
|
+
display: inline-flex;
|
|
334
|
+
align-items: center;
|
|
335
|
+
gap: var(--button-icon-gap, var(--spacing-6));
|
|
370
336
|
}
|
|
371
|
-
|
|
372
|
-
|
|
337
|
+
|
|
338
|
+
.ButtonContent-module_large__mLOdb {
|
|
339
|
+
--button-icon-gap: var(--spacing-8);
|
|
373
340
|
}
|
|
374
|
-
|
|
375
|
-
|
|
341
|
+
|
|
342
|
+
.ButtonContent-module_buttonLabel__T5XAq {
|
|
343
|
+
display: inline-flex;
|
|
344
|
+
align-items: center;
|
|
376
345
|
}
|
|
377
|
-
|
|
378
|
-
|
|
346
|
+
|
|
347
|
+
.ButtonContent-module_buttonIcon__qkAX- {
|
|
348
|
+
display: inline-flex;
|
|
349
|
+
align-items: center;
|
|
379
350
|
}
|
|
351
|
+
|
|
380
352
|
.Focusable-module_focusableWrapper__NfuIi {
|
|
381
353
|
display: inline-flex;
|
|
382
354
|
}
|
|
@@ -436,6 +408,34 @@
|
|
|
436
408
|
opacity: 1;
|
|
437
409
|
}
|
|
438
410
|
}
|
|
411
|
+
/** THIS IS AN AUTOGENERATED FILE **/
|
|
412
|
+
/** THIS IS AN AUTOGENERATED FILE **/
|
|
413
|
+
.OverlayArrow-module_overlayArrow__hoDyK {
|
|
414
|
+
display: flex;
|
|
415
|
+
padding: 8px;
|
|
416
|
+
}
|
|
417
|
+
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=top], .OverlayArrow-module_overlayArrow__hoDyK[data-placement=bottom] {
|
|
418
|
+
padding: 0 8px;
|
|
419
|
+
}
|
|
420
|
+
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=left], .OverlayArrow-module_overlayArrow__hoDyK[data-placement=right] {
|
|
421
|
+
padding: 8px 0;
|
|
422
|
+
}
|
|
423
|
+
.OverlayArrow-module_overlayArrow__hoDyK path {
|
|
424
|
+
fill: var(--color-purple-800, #2f2438);
|
|
425
|
+
box-shadow: var(--shadow-small-box-shadow, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 3px 16px 0 rgba(0, 0, 0, 0.06));
|
|
426
|
+
}
|
|
427
|
+
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=right] svg {
|
|
428
|
+
transform: rotate(90deg);
|
|
429
|
+
}
|
|
430
|
+
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=bottom] svg {
|
|
431
|
+
transform: rotate(180deg);
|
|
432
|
+
}
|
|
433
|
+
.OverlayArrow-module_overlayArrow__hoDyK[data-placement=left] svg {
|
|
434
|
+
transform: rotate(270deg);
|
|
435
|
+
}
|
|
436
|
+
.OverlayArrow-module_overlayArrow__hoDyK.OverlayArrow-module_reversed__-WGcR path {
|
|
437
|
+
fill: var(--color-white, #ffffff);
|
|
438
|
+
}
|
|
439
439
|
/*
|
|
440
440
|
* This is taken from the Material Symbols CDN
|
|
441
441
|
* font-weight & font-size removed as overridden in .icon
|
|
@@ -5657,15 +5657,67 @@ input[type=range].InputRange-module_ratingScaleRange__gI-rs::-ms-thumb:not(:disa
|
|
|
5657
5657
|
}
|
|
5658
5658
|
}
|
|
5659
5659
|
|
|
5660
|
+
.TabList-module_container__Z8JCa {
|
|
5661
|
+
position: relative;
|
|
5662
|
+
}
|
|
5663
|
+
|
|
5660
5664
|
.TabList-module_tabList__e1qAi {
|
|
5661
5665
|
border-bottom: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
5662
|
-
padding: var(--spacing-
|
|
5666
|
+
padding: var(--spacing-6) 0 0;
|
|
5667
|
+
width: 100%;
|
|
5668
|
+
height: 100%;
|
|
5669
|
+
overflow-x: scroll;
|
|
5670
|
+
white-space: nowrap;
|
|
5671
|
+
scrollbar-width: none;
|
|
5672
|
+
scroll-behavior: smooth;
|
|
5663
5673
|
}
|
|
5664
5674
|
|
|
5665
5675
|
.TabList-module_noPadding__YM23K {
|
|
5666
5676
|
padding: 0;
|
|
5667
5677
|
}
|
|
5668
5678
|
|
|
5679
|
+
.TabList-module_leftArrow__CPchY,
|
|
5680
|
+
.TabList-module_rightArrow__0xcW1 {
|
|
5681
|
+
--icon-size: 24;
|
|
5682
|
+
|
|
5683
|
+
display: flex;
|
|
5684
|
+
align-items: center;
|
|
5685
|
+
justify-content: center;
|
|
5686
|
+
position: absolute;
|
|
5687
|
+
z-index: 10000;
|
|
5688
|
+
background: var(--color-white);
|
|
5689
|
+
inset-block: 0 1px;
|
|
5690
|
+
width: 48px;
|
|
5691
|
+
cursor: default;
|
|
5692
|
+
user-select: none;
|
|
5693
|
+
}
|
|
5694
|
+
|
|
5695
|
+
/*
|
|
5696
|
+
* Note: we're purposefully using directional properties instead of start/end for positioning and styling related to the carousel arrows
|
|
5697
|
+
*/
|
|
5698
|
+
.TabList-module_leftArrow__CPchY {
|
|
5699
|
+
left: 0;
|
|
5700
|
+
}
|
|
5701
|
+
|
|
5702
|
+
.TabList-module_leftArrow__CPchY,
|
|
5703
|
+
.TabList-module_leftArrow__CPchY:hover {
|
|
5704
|
+
border-right: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
5705
|
+
}
|
|
5706
|
+
|
|
5707
|
+
.TabList-module_rightArrow__0xcW1 {
|
|
5708
|
+
right: 0;
|
|
5709
|
+
}
|
|
5710
|
+
|
|
5711
|
+
.TabList-module_rightArrow__0xcW1,
|
|
5712
|
+
.TabList-module_rightArrow__0xcW1:hover {
|
|
5713
|
+
border-left: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
5714
|
+
}
|
|
5715
|
+
|
|
5716
|
+
.TabList-module_leftArrow__CPchY:hover,
|
|
5717
|
+
.TabList-module_rightArrow__0xcW1:hover {
|
|
5718
|
+
background: var(--color-gray-200);
|
|
5719
|
+
}
|
|
5720
|
+
|
|
5669
5721
|
.TabPanel-module_tabPanel__ae5Rx {
|
|
5670
5722
|
border: 2px solid transparent;
|
|
5671
5723
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SCROLL_AMOUNT = 120;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isRTL';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaizen/components",
|
|
3
|
-
"version": "1.68.
|
|
3
|
+
"version": "1.68.12",
|
|
4
4
|
"description": "Kaizen component library",
|
|
5
5
|
"author": "Geoffrey Chong <geoff.chong@cultureamp.com>",
|
|
6
6
|
"homepage": "https://cultureamp.design",
|
|
@@ -117,8 +117,8 @@
|
|
|
117
117
|
"svgo": "^3.3.2",
|
|
118
118
|
"tslib": "^2.8.1",
|
|
119
119
|
"tsx": "^4.19.2",
|
|
120
|
-
"@kaizen/
|
|
121
|
-
"@kaizen/
|
|
120
|
+
"@kaizen/package-bundler": "2.0.3",
|
|
121
|
+
"@kaizen/design-tokens": "10.8.6"
|
|
122
122
|
},
|
|
123
123
|
"devDependenciesComments": {
|
|
124
124
|
"sass": "Prevent deprecation warnings introduced in 1.80 as we plan to move away from sass",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Meta, StoryObj } from '@storybook/react'
|
|
3
|
+
import { within, userEvent, expect } from '@storybook/test'
|
|
4
|
+
import { Text } from '~components/Text'
|
|
5
|
+
import { Tab, TabList, TabPanel, Tabs } from '../index'
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: 'Components/Tabs/Tabs (Future)/Tests',
|
|
9
|
+
parameters: {
|
|
10
|
+
controls: { disable: true },
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
children: (
|
|
14
|
+
<>
|
|
15
|
+
<TabList aria-label="Tabs" data-testid="sb-arrows">
|
|
16
|
+
<Tab id="one">Tab 1</Tab>
|
|
17
|
+
<Tab id="two">Tab 2</Tab>
|
|
18
|
+
<Tab id="three" badge="3">
|
|
19
|
+
Tab 3
|
|
20
|
+
</Tab>
|
|
21
|
+
<Tab id="disabled" isDisabled>
|
|
22
|
+
Disabled Tab
|
|
23
|
+
</Tab>
|
|
24
|
+
<Tab id="four">Tab 4</Tab>
|
|
25
|
+
<Tab id="five">Tab 5</Tab>
|
|
26
|
+
</TabList>
|
|
27
|
+
<TabPanel id="one" className="p-24">
|
|
28
|
+
<Text variant="body">Content 1</Text>
|
|
29
|
+
</TabPanel>
|
|
30
|
+
<TabPanel id="two" className="p-24">
|
|
31
|
+
<Text variant="body">Content 2</Text>
|
|
32
|
+
</TabPanel>
|
|
33
|
+
<TabPanel id="three" className="p-24">
|
|
34
|
+
<Text variant="body">Content 3</Text>
|
|
35
|
+
</TabPanel>
|
|
36
|
+
<TabPanel id="disabled" className="p-24">
|
|
37
|
+
<Text variant="body">Disabled content</Text>
|
|
38
|
+
</TabPanel>
|
|
39
|
+
<TabPanel id="four" className="p-24">
|
|
40
|
+
<Text variant="body">Content 4</Text>
|
|
41
|
+
</TabPanel>
|
|
42
|
+
<TabPanel id="five" className="p-24">
|
|
43
|
+
<Text variant="body">Content 5</Text>
|
|
44
|
+
</TabPanel>
|
|
45
|
+
</>
|
|
46
|
+
),
|
|
47
|
+
},
|
|
48
|
+
} satisfies Meta<typeof Tabs>
|
|
49
|
+
|
|
50
|
+
export default meta
|
|
51
|
+
|
|
52
|
+
type Story = StoryObj<typeof meta>
|
|
53
|
+
|
|
54
|
+
export const ArrowsShowingAndHiding: Story = {
|
|
55
|
+
render: (args) => {
|
|
56
|
+
return (
|
|
57
|
+
<div style={{ maxWidth: '500px' }}>
|
|
58
|
+
<Tabs {...args} />
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
},
|
|
62
|
+
play: async ({ canvasElement }) => {
|
|
63
|
+
const canvas = within(canvasElement.parentElement!)
|
|
64
|
+
|
|
65
|
+
expect(canvas.queryByTestId('kz-tablist-left-arrow')).not.toBeInTheDocument()
|
|
66
|
+
|
|
67
|
+
const rightArrow = await canvas.findByTestId('sb-arrows-kz-tablist-right-arrow')
|
|
68
|
+
|
|
69
|
+
await userEvent.click(rightArrow)
|
|
70
|
+
await new Promise((r) => setTimeout(r, 500))
|
|
71
|
+
|
|
72
|
+
const leftArrow = await canvas.findByTestId('sb-arrows-kz-tablist-left-arrow')
|
|
73
|
+
|
|
74
|
+
expect(leftArrow).toBeInTheDocument()
|
|
75
|
+
expect(rightArrow).toBeInTheDocument()
|
|
76
|
+
|
|
77
|
+
await userEvent.click(rightArrow)
|
|
78
|
+
await new Promise((r) => setTimeout(r, 500))
|
|
79
|
+
|
|
80
|
+
expect(leftArrow).toBeInTheDocument()
|
|
81
|
+
expect(rightArrow).not.toBeInTheDocument()
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const ArrowsShowingAndHidingRTL: Story = {
|
|
86
|
+
name: 'Arrows Showing and Hiding (RTL)',
|
|
87
|
+
parameters: {
|
|
88
|
+
textDirection: 'rtl',
|
|
89
|
+
},
|
|
90
|
+
render: (args) => {
|
|
91
|
+
return (
|
|
92
|
+
<div style={{ maxWidth: '500px' }}>
|
|
93
|
+
<Tabs {...args} />
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
play: async ({ canvasElement }) => {
|
|
98
|
+
const canvas = within(canvasElement.parentElement!)
|
|
99
|
+
|
|
100
|
+
expect(canvas.queryByTestId('kz-tablist-right-arrow')).not.toBeInTheDocument()
|
|
101
|
+
|
|
102
|
+
const leftArrow = await canvas.findByTestId('sb-arrows-kz-tablist-left-arrow')
|
|
103
|
+
|
|
104
|
+
await userEvent.click(leftArrow)
|
|
105
|
+
await new Promise((r) => setTimeout(r, 500))
|
|
106
|
+
|
|
107
|
+
const rightArrow = await canvas.findByTestId('sb-arrows-kz-tablist-right-arrow')
|
|
108
|
+
|
|
109
|
+
expect(leftArrow).toBeInTheDocument()
|
|
110
|
+
expect(rightArrow).toBeInTheDocument()
|
|
111
|
+
|
|
112
|
+
await userEvent.click(leftArrow)
|
|
113
|
+
await new Promise((r) => setTimeout(r, 500))
|
|
114
|
+
|
|
115
|
+
expect(rightArrow).toBeInTheDocument()
|
|
116
|
+
expect(leftArrow).not.toBeInTheDocument()
|
|
117
|
+
},
|
|
118
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Meta } from '@storybook/react'
|
|
3
|
+
import { Text } from '~components/Text'
|
|
4
|
+
import { StickerSheet, StickerSheetStory } from '~storybook/components/StickerSheet'
|
|
5
|
+
import { Tab, TabList, TabPanel, Tabs } from '../index'
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Components/Tabs/Tabs (Future)',
|
|
9
|
+
parameters: {
|
|
10
|
+
chromatic: { disable: false },
|
|
11
|
+
controls: { disable: true },
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta
|
|
14
|
+
|
|
15
|
+
const ExampleTabs = ({ id }: { id: string }): JSX.Element => (
|
|
16
|
+
<Tabs>
|
|
17
|
+
<TabList aria-label="Tabs">
|
|
18
|
+
<Tab id={`${id}-1`}>Tab 1</Tab>
|
|
19
|
+
<Tab id={`${id}-2`}>Tab 2</Tab>
|
|
20
|
+
<Tab id={`${id}-3`} badge="3">
|
|
21
|
+
Tab 3
|
|
22
|
+
</Tab>
|
|
23
|
+
<Tab id={`${id}-disabled`} isDisabled>
|
|
24
|
+
Disabled Tab
|
|
25
|
+
</Tab>
|
|
26
|
+
<Tab id={`${id}-4`}>Tab 4</Tab>
|
|
27
|
+
<Tab id={`${id}-5`}>Tab 5</Tab>
|
|
28
|
+
</TabList>
|
|
29
|
+
<TabPanel id={`${id}-1`} className="p-24">
|
|
30
|
+
<Text variant="body">Content 1</Text>
|
|
31
|
+
</TabPanel>
|
|
32
|
+
<TabPanel id={`${id}-2`} className="p-24">
|
|
33
|
+
<Text variant="body">Content 2</Text>
|
|
34
|
+
</TabPanel>
|
|
35
|
+
<TabPanel id={`${id}-3`} className="p-24">
|
|
36
|
+
<Text variant="body">Content 3</Text>
|
|
37
|
+
</TabPanel>
|
|
38
|
+
<TabPanel id={`${id}-disabled`} className="p-24">
|
|
39
|
+
<Text variant="body">Disabled content</Text>
|
|
40
|
+
</TabPanel>
|
|
41
|
+
<TabPanel id={`${id}-4`} className="p-24">
|
|
42
|
+
<Text variant="body">Content 4</Text>
|
|
43
|
+
</TabPanel>
|
|
44
|
+
<TabPanel id={`${id}-5`} className="p-24">
|
|
45
|
+
<Text variant="body">Content 5</Text>
|
|
46
|
+
</TabPanel>
|
|
47
|
+
</Tabs>
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
const StickerSheetTemplate: StickerSheetStory = {
|
|
51
|
+
render: () => {
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<StickerSheet title="Tabs" layout="stretch">
|
|
55
|
+
<StickerSheet.Row>
|
|
56
|
+
<ExampleTabs id="fullwidth" />
|
|
57
|
+
</StickerSheet.Row>
|
|
58
|
+
</StickerSheet>
|
|
59
|
+
|
|
60
|
+
<StickerSheet title="Overflow (container 500px)" layout="stretch">
|
|
61
|
+
<StickerSheet.Row>
|
|
62
|
+
<div style={{ maxWidth: '500px' }}>
|
|
63
|
+
<ExampleTabs id="overflow" />
|
|
64
|
+
</div>
|
|
65
|
+
</StickerSheet.Row>
|
|
66
|
+
</StickerSheet>
|
|
67
|
+
</>
|
|
68
|
+
)
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const StickerSheetDefault: StickerSheetStory = {
|
|
73
|
+
...StickerSheetTemplate,
|
|
74
|
+
name: 'Sticker Sheet (Default)',
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const StickerSheetRTL: StickerSheetStory = {
|
|
78
|
+
...StickerSheetTemplate,
|
|
79
|
+
name: 'Sticker Sheet (RTL)',
|
|
80
|
+
parameters: {
|
|
81
|
+
...StickerSheetTemplate.parameters,
|
|
82
|
+
textDirection: 'rtl',
|
|
83
|
+
},
|
|
84
|
+
}
|
|
@@ -16,9 +16,11 @@ const meta = {
|
|
|
16
16
|
<Tab id="three" badge="3">
|
|
17
17
|
Tab 3
|
|
18
18
|
</Tab>
|
|
19
|
-
<Tab id="
|
|
19
|
+
<Tab id="disabled" isDisabled>
|
|
20
20
|
Disabled Tab
|
|
21
21
|
</Tab>
|
|
22
|
+
<Tab id="four">Tab 4</Tab>
|
|
23
|
+
<Tab id="five">Tab 5</Tab>
|
|
22
24
|
</TabList>
|
|
23
25
|
<TabPanel id="one" className="p-24">
|
|
24
26
|
<Text variant="body">Content 1</Text>
|
|
@@ -29,6 +31,15 @@ const meta = {
|
|
|
29
31
|
<TabPanel id="three" className="p-24">
|
|
30
32
|
<Text variant="body">Content 3</Text>
|
|
31
33
|
</TabPanel>
|
|
34
|
+
<TabPanel id="disabled" className="p-24">
|
|
35
|
+
<Text variant="body">Content 4</Text>
|
|
36
|
+
</TabPanel>
|
|
37
|
+
<TabPanel id="four" className="p-24">
|
|
38
|
+
<Text variant="body">Content 4</Text>
|
|
39
|
+
</TabPanel>
|
|
40
|
+
<TabPanel id="five" className="p-24">
|
|
41
|
+
<Text variant="body">Content 5</Text>
|
|
42
|
+
</TabPanel>
|
|
32
43
|
</>
|
|
33
44
|
),
|
|
34
45
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SCROLL_AMOUNT = 120
|
|
@@ -1,8 +1,60 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
position: relative;
|
|
3
|
+
}
|
|
4
|
+
|
|
1
5
|
.tabList {
|
|
2
6
|
border-bottom: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
3
|
-
padding: var(--spacing-
|
|
7
|
+
padding: var(--spacing-6) 0 0;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
overflow-x: scroll;
|
|
11
|
+
white-space: nowrap;
|
|
12
|
+
scrollbar-width: none;
|
|
13
|
+
scroll-behavior: smooth;
|
|
4
14
|
}
|
|
5
15
|
|
|
6
16
|
.noPadding {
|
|
7
17
|
padding: 0;
|
|
8
18
|
}
|
|
19
|
+
|
|
20
|
+
.leftArrow,
|
|
21
|
+
.rightArrow {
|
|
22
|
+
--icon-size: 24;
|
|
23
|
+
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: center;
|
|
27
|
+
position: absolute;
|
|
28
|
+
z-index: 10000;
|
|
29
|
+
background: var(--color-white);
|
|
30
|
+
inset-block: 0 1px;
|
|
31
|
+
width: 48px;
|
|
32
|
+
cursor: default;
|
|
33
|
+
user-select: none;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/*
|
|
37
|
+
* Note: we're purposefully using directional properties instead of start/end for positioning and styling related to the carousel arrows
|
|
38
|
+
*/
|
|
39
|
+
.leftArrow {
|
|
40
|
+
left: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.leftArrow,
|
|
44
|
+
.leftArrow:hover {
|
|
45
|
+
border-right: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.rightArrow {
|
|
49
|
+
right: 0;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.rightArrow,
|
|
53
|
+
.rightArrow:hover {
|
|
54
|
+
border-left: 1px solid rgba(var(--color-gray-600-rgb), 0.1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.leftArrow:hover,
|
|
58
|
+
.rightArrow:hover {
|
|
59
|
+
background: var(--color-gray-200);
|
|
60
|
+
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import React, { ReactNode } from 'react'
|
|
1
|
+
import React, { ReactNode, useContext, useEffect, useId, useRef, useState } from 'react'
|
|
2
2
|
import classnames from 'classnames'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
TabList as RACTabList,
|
|
5
|
+
TabListProps as RACTabListProps,
|
|
6
|
+
TabListStateContext,
|
|
7
|
+
} from 'react-aria-components'
|
|
8
|
+
import { Icon } from '~components/__future__/Icon'
|
|
9
|
+
import { isRTL as isRTLCheck } from '~components/__utilities__/isRTL'
|
|
10
|
+
import { SCROLL_AMOUNT } from '../../constants'
|
|
4
11
|
import styles from './TabList.module.css'
|
|
5
12
|
|
|
6
13
|
export type TabListProps = {
|
|
@@ -13,20 +20,141 @@ export type TabListProps = {
|
|
|
13
20
|
*/
|
|
14
21
|
'noPadding'?: boolean
|
|
15
22
|
'children': ReactNode
|
|
23
|
+
'data-testid'?: string
|
|
16
24
|
} & RACTabListProps<HTMLElement>
|
|
17
25
|
|
|
18
26
|
/**
|
|
19
27
|
* Wrapper for the tabs themselves
|
|
20
28
|
*/
|
|
21
29
|
export const TabList = (props: TabListProps): JSX.Element => {
|
|
22
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
'aria-label': ariaLabel,
|
|
32
|
+
noPadding = false,
|
|
33
|
+
children,
|
|
34
|
+
className,
|
|
35
|
+
'data-testid': testId,
|
|
36
|
+
...restProps
|
|
37
|
+
} = props
|
|
38
|
+
const [isDocumentReady, setIsDocumentReady] = useState<boolean>(false)
|
|
39
|
+
const [leftArrowEnabled, setLeftArrowEnabled] = useState<boolean>(false)
|
|
40
|
+
const [rightArrowEnabled, setRightArrowEnabled] = useState<boolean>(false)
|
|
41
|
+
const tabListRef = useRef<HTMLDivElement | null>(null)
|
|
42
|
+
const tabListId = useId()
|
|
43
|
+
const [isRTL, setIsRTL] = useState<boolean>(false)
|
|
44
|
+
const [containerElement, setContainerElement] = useState<HTMLElement | null>()
|
|
45
|
+
const tabListContext = useContext(TabListStateContext)
|
|
46
|
+
const selectedKey = tabListContext?.selectedKey
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!isDocumentReady) {
|
|
50
|
+
setIsDocumentReady(true)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const container = document.getElementById(tabListId)
|
|
55
|
+
setContainerElement(container)
|
|
56
|
+
setIsRTL(container ? isRTLCheck(container) : false)
|
|
57
|
+
}, [isDocumentReady, tabListId])
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!isDocumentReady) {
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const tabs = containerElement?.querySelectorAll('[data-kz-tab]')
|
|
65
|
+
if (!tabs) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const firstTabObserver = new IntersectionObserver(
|
|
70
|
+
(entries) => {
|
|
71
|
+
if (!entries[0].isIntersecting) {
|
|
72
|
+
setLeftArrowEnabled(true)
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
setLeftArrowEnabled(false)
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
threshold: 0.75,
|
|
79
|
+
root: containerElement,
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
firstTabObserver.observe(isRTL ? tabs[tabs.length - 1] : tabs[0])
|
|
83
|
+
|
|
84
|
+
const lastTabObserver = new IntersectionObserver(
|
|
85
|
+
(entries) => {
|
|
86
|
+
if (!entries[0].isIntersecting) {
|
|
87
|
+
setRightArrowEnabled(true)
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
setRightArrowEnabled(false)
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
threshold: 0.75,
|
|
94
|
+
root: containerElement,
|
|
95
|
+
},
|
|
96
|
+
)
|
|
97
|
+
lastTabObserver.observe(isRTL ? tabs[0] : tabs[tabs.length - 1])
|
|
98
|
+
|
|
99
|
+
return () => {
|
|
100
|
+
firstTabObserver.disconnect()
|
|
101
|
+
lastTabObserver.disconnect()
|
|
102
|
+
}
|
|
103
|
+
}, [isDocumentReady, containerElement, isRTL])
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (!isDocumentReady) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Scroll selected tab into view
|
|
111
|
+
containerElement
|
|
112
|
+
?.querySelector('[role="tab"][data-selected=true]')
|
|
113
|
+
?.scrollIntoView({ block: 'nearest', inline: 'center' })
|
|
114
|
+
}, [selectedKey, containerElement, isDocumentReady])
|
|
115
|
+
|
|
116
|
+
const handleArrowPress = (direction: 'left' | 'right'): void => {
|
|
117
|
+
if (tabListRef.current) {
|
|
118
|
+
const tabListScrollPos = tabListRef.current.scrollLeft
|
|
119
|
+
const newSpot =
|
|
120
|
+
direction === 'left' ? tabListScrollPos - SCROLL_AMOUNT : tabListScrollPos + SCROLL_AMOUNT
|
|
121
|
+
tabListRef.current.scrollLeft = newSpot
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
23
125
|
return (
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
126
|
+
<div className={styles.container} id={tabListId}>
|
|
127
|
+
{leftArrowEnabled && (
|
|
128
|
+
// making a conscious decision to use <div onClick> over <button> here, because:
|
|
129
|
+
// - <button> would add pointless noise for a screen reader user
|
|
130
|
+
// - keyboard only user can toggle through tabs with left/right arrow keys already
|
|
131
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
132
|
+
<div
|
|
133
|
+
onClick={() => handleArrowPress('left')}
|
|
134
|
+
className={styles.leftArrow}
|
|
135
|
+
data-testid={testId ? `${testId}-kz-tablist-left-arrow` : undefined}
|
|
136
|
+
>
|
|
137
|
+
<Icon name="chevron_left" isPresentational />
|
|
138
|
+
</div>
|
|
139
|
+
)}
|
|
140
|
+
<RACTabList
|
|
141
|
+
aria-label={ariaLabel}
|
|
142
|
+
ref={tabListRef}
|
|
143
|
+
className={classnames(styles.tabList, className, noPadding && styles.noPadding)}
|
|
144
|
+
{...restProps}
|
|
145
|
+
>
|
|
146
|
+
{children}
|
|
147
|
+
</RACTabList>
|
|
148
|
+
{rightArrowEnabled && (
|
|
149
|
+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
|
|
150
|
+
<div
|
|
151
|
+
onClick={() => handleArrowPress('right')}
|
|
152
|
+
className={styles.rightArrow}
|
|
153
|
+
data-testid={testId ? `${testId}-kz-tablist-right-arrow` : undefined}
|
|
154
|
+
>
|
|
155
|
+
<Icon name="chevron_right" isPresentational />
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
</div>
|
|
31
159
|
)
|
|
32
160
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isRTL'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import { isRTL } from './isRTL'
|
|
4
|
+
|
|
5
|
+
describe('isRTL', () => {
|
|
6
|
+
it('returns false when no element with dir found', () => {
|
|
7
|
+
const Example = (): JSX.Element => <button type="button">Test</button>
|
|
8
|
+
render(<Example />)
|
|
9
|
+
const button = screen.getByRole('button')
|
|
10
|
+
expect(isRTL(button)).toBe(false)
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('returns false when greater parent is dir=rtl, but closer parent is dir=ltr', () => {
|
|
14
|
+
const Example = (): JSX.Element => (
|
|
15
|
+
<div dir="rtl">
|
|
16
|
+
<div dir="ltr">
|
|
17
|
+
<button type="button">Test</button>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
render(<Example />)
|
|
22
|
+
const button = screen.getByRole('button')
|
|
23
|
+
expect(isRTL(button)).toBe(false)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('returns true when greater parent is dir=ltr, but closer parent is dir=rtl', () => {
|
|
27
|
+
const Example = (): JSX.Element => (
|
|
28
|
+
<div dir="ltr">
|
|
29
|
+
<div dir="rtl">
|
|
30
|
+
<button type="button">Test</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
34
|
+
render(<Example />)
|
|
35
|
+
const button = screen.getByRole('button')
|
|
36
|
+
expect(isRTL(button)).toBe(true)
|
|
37
|
+
})
|
|
38
|
+
})
|