box-ui-elements 23.4.0-beta.20 → 23.4.0-beta.22
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/explorer.js +1 -1
- package/dist/preview.js +1 -1
- package/dist/sidebar.js +1 -1
- package/es/elements/content-sidebar/SidebarNavButton.js +49 -1
- package/es/elements/content-sidebar/SidebarNavButton.js.flow +65 -3
- package/es/elements/content-sidebar/SidebarNavButton.js.map +1 -1
- package/es/features/header-flyout/styles/HeaderFlyout.scss +21 -0
- package/package.json +1 -1
- package/src/elements/content-sidebar/SidebarNavButton.js +65 -3
- package/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js +155 -3
- package/src/features/header-flyout/styles/HeaderFlyout.scss +21 -0
|
@@ -18,13 +18,62 @@ const SidebarNavButton = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
18
18
|
'data-testid': dataTestId,
|
|
19
19
|
children,
|
|
20
20
|
elementId = '',
|
|
21
|
+
internalSidebarNavigation,
|
|
22
|
+
internalSidebarNavigationHandler,
|
|
21
23
|
isDisabled,
|
|
22
24
|
isOpen,
|
|
23
25
|
onClick = noop,
|
|
26
|
+
routerDisabled = false,
|
|
24
27
|
sidebarView,
|
|
25
28
|
tooltip
|
|
26
29
|
} = props;
|
|
27
30
|
const sidebarPath = `/${sidebarView}`;
|
|
31
|
+
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
32
|
+
if (routerDisabled) {
|
|
33
|
+
// Mimic router behavior using internalSidebarNavigation
|
|
34
|
+
const isMatch = !!internalSidebarNavigation && internalSidebarNavigation.sidebar === sidebarView;
|
|
35
|
+
const isActiveValue = isMatch && !!isOpen;
|
|
36
|
+
|
|
37
|
+
// Mimic isExactMatch: true when no extra navigation parameters are present
|
|
38
|
+
const hasExtraParams = internalSidebarNavigation && (internalSidebarNavigation.versionId || internalSidebarNavigation.activeFeedEntryType || internalSidebarNavigation.activeFeedEntryId || internalSidebarNavigation.fileVersionId);
|
|
39
|
+
const isExactMatch = isMatch && !hasExtraParams;
|
|
40
|
+
const handleNavButtonClick = event => {
|
|
41
|
+
onClick(sidebarView);
|
|
42
|
+
|
|
43
|
+
// Mimic router navigation behavior
|
|
44
|
+
if (internalSidebarNavigationHandler && !event.defaultPrevented && isLeftClick(event)) {
|
|
45
|
+
const replace = isExactMatch;
|
|
46
|
+
internalSidebarNavigationHandler({
|
|
47
|
+
sidebar: sidebarView,
|
|
48
|
+
open: true
|
|
49
|
+
}, replace);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return /*#__PURE__*/React.createElement(Tooltip, {
|
|
53
|
+
position: "middle-left",
|
|
54
|
+
text: tooltip,
|
|
55
|
+
isTabbable: false
|
|
56
|
+
}, /*#__PURE__*/React.createElement(Button, {
|
|
57
|
+
accessibleWhenDisabled: true,
|
|
58
|
+
"aria-controls": `${id}-content`,
|
|
59
|
+
"aria-label": tooltip,
|
|
60
|
+
"aria-selected": isActiveValue,
|
|
61
|
+
className: classNames('bcs-NavButton', {
|
|
62
|
+
'bcs-is-selected': isActiveValue,
|
|
63
|
+
'bdl-is-disabled': isDisabled
|
|
64
|
+
}),
|
|
65
|
+
"data-resin-target": dataResinTarget,
|
|
66
|
+
"data-testid": dataTestId,
|
|
67
|
+
ref: ref,
|
|
68
|
+
id: id,
|
|
69
|
+
disabled: isDisabled,
|
|
70
|
+
onClick: handleNavButtonClick,
|
|
71
|
+
role: "tab",
|
|
72
|
+
tabIndex: isActiveValue ? '0' : '-1',
|
|
73
|
+
type: "button",
|
|
74
|
+
variant: "tertiary"
|
|
75
|
+
}, children));
|
|
76
|
+
}
|
|
28
77
|
return /*#__PURE__*/React.createElement(Route, {
|
|
29
78
|
path: sidebarPath
|
|
30
79
|
}, ({
|
|
@@ -34,7 +83,6 @@ const SidebarNavButton = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
|
34
83
|
const isMatch = !!match;
|
|
35
84
|
const isActiveValue = isMatch && !!isOpen;
|
|
36
85
|
const isExactMatch = isMatch && match.isExact;
|
|
37
|
-
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
38
86
|
const handleNavButtonClick = event => {
|
|
39
87
|
onClick(sidebarView);
|
|
40
88
|
if (!event.defaultPrevented && isLeftClick(event)) {
|
|
@@ -11,6 +11,7 @@ import classNames from 'classnames';
|
|
|
11
11
|
import { Button } from '@box/blueprint-web';
|
|
12
12
|
import Tooltip from '../../components/tooltip/Tooltip';
|
|
13
13
|
import { isLeftClick } from '../../utils/dom';
|
|
14
|
+
import type { InternalSidebarNavigation, InternalSidebarNavigationHandler, ViewTypeValues } from '../common/types/SidebarNavigation';
|
|
14
15
|
import './SidebarNavButton.scss';
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
@@ -18,10 +19,13 @@ type Props = {
|
|
|
18
19
|
'data-testid'?: string,
|
|
19
20
|
children: React.Node,
|
|
20
21
|
elementId?: string,
|
|
22
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
23
|
+
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
|
|
21
24
|
isDisabled?: boolean,
|
|
22
25
|
isOpen?: boolean,
|
|
23
|
-
onClick?: (sidebarView:
|
|
24
|
-
|
|
26
|
+
onClick?: (sidebarView: ViewTypeValues) => void,
|
|
27
|
+
routerDisabled?: boolean,
|
|
28
|
+
sidebarView: ViewTypeValues,
|
|
25
29
|
tooltip: React.Node,
|
|
26
30
|
};
|
|
27
31
|
|
|
@@ -31,13 +35,72 @@ const SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props,
|
|
|
31
35
|
'data-testid': dataTestId,
|
|
32
36
|
children,
|
|
33
37
|
elementId = '',
|
|
38
|
+
internalSidebarNavigation,
|
|
39
|
+
internalSidebarNavigationHandler,
|
|
34
40
|
isDisabled,
|
|
35
41
|
isOpen,
|
|
36
42
|
onClick = noop,
|
|
43
|
+
routerDisabled = false,
|
|
37
44
|
sidebarView,
|
|
38
45
|
tooltip,
|
|
39
46
|
} = props;
|
|
40
47
|
const sidebarPath = `/${sidebarView}`;
|
|
48
|
+
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
49
|
+
|
|
50
|
+
if (routerDisabled) {
|
|
51
|
+
// Mimic router behavior using internalSidebarNavigation
|
|
52
|
+
const isMatch = !!internalSidebarNavigation && internalSidebarNavigation.sidebar === sidebarView;
|
|
53
|
+
const isActiveValue = isMatch && !!isOpen;
|
|
54
|
+
|
|
55
|
+
// Mimic isExactMatch: true when no extra navigation parameters are present
|
|
56
|
+
const hasExtraParams = internalSidebarNavigation && (
|
|
57
|
+
internalSidebarNavigation.versionId ||
|
|
58
|
+
internalSidebarNavigation.activeFeedEntryType ||
|
|
59
|
+
internalSidebarNavigation.activeFeedEntryId ||
|
|
60
|
+
internalSidebarNavigation.fileVersionId
|
|
61
|
+
);
|
|
62
|
+
const isExactMatch = isMatch && !hasExtraParams;
|
|
63
|
+
|
|
64
|
+
const handleNavButtonClick = event => {
|
|
65
|
+
onClick(sidebarView);
|
|
66
|
+
|
|
67
|
+
// Mimic router navigation behavior
|
|
68
|
+
if (internalSidebarNavigationHandler && !event.defaultPrevented && isLeftClick(event)) {
|
|
69
|
+
const replace = isExactMatch;
|
|
70
|
+
internalSidebarNavigationHandler({
|
|
71
|
+
sidebar: sidebarView,
|
|
72
|
+
open: true,
|
|
73
|
+
}, replace);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Tooltip position="middle-left" text={tooltip} isTabbable={false}>
|
|
79
|
+
<Button
|
|
80
|
+
accessibleWhenDisabled={true}
|
|
81
|
+
aria-controls={`${id}-content`}
|
|
82
|
+
aria-label={tooltip}
|
|
83
|
+
aria-selected={isActiveValue}
|
|
84
|
+
className={classNames('bcs-NavButton', {
|
|
85
|
+
'bcs-is-selected': isActiveValue,
|
|
86
|
+
'bdl-is-disabled': isDisabled,
|
|
87
|
+
})}
|
|
88
|
+
data-resin-target={dataResinTarget}
|
|
89
|
+
data-testid={dataTestId}
|
|
90
|
+
ref={ref}
|
|
91
|
+
id={id}
|
|
92
|
+
disabled={isDisabled}
|
|
93
|
+
onClick={handleNavButtonClick}
|
|
94
|
+
role="tab"
|
|
95
|
+
tabIndex={isActiveValue ? '0' : '-1'}
|
|
96
|
+
type="button"
|
|
97
|
+
variant="tertiary"
|
|
98
|
+
>
|
|
99
|
+
{children}
|
|
100
|
+
</Button>
|
|
101
|
+
</Tooltip>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
41
104
|
|
|
42
105
|
return (
|
|
43
106
|
<Route path={sidebarPath}>
|
|
@@ -45,7 +108,6 @@ const SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props,
|
|
|
45
108
|
const isMatch = !!match;
|
|
46
109
|
const isActiveValue = isMatch && !!isOpen;
|
|
47
110
|
const isExactMatch = isMatch && match.isExact;
|
|
48
|
-
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
49
111
|
|
|
50
112
|
const handleNavButtonClick = event => {
|
|
51
113
|
onClick(sidebarView);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidebarNavButton.js","names":["React","Route","noop","classNames","Button","Tooltip","isLeftClick","SidebarNavButton","forwardRef","props","ref","dataResinTarget","dataTestId","children","elementId","isDisabled","isOpen","onClick","sidebarView","tooltip","sidebarPath","createElement","path","match","history","isMatch","isActiveValue","isExactMatch","isExact","id","handleNavButtonClick","event","defaultPrevented","method","replace","push","pathname","state","open","position","text","isTabbable","accessibleWhenDisabled","className","disabled","role","tabIndex","type","variant"],"sources":["../../../src/elements/content-sidebar/SidebarNavButton.js"],"sourcesContent":["/**\n * @flow\n * @file Preview sidebar nav button component\n * @author Box\n */\n\nimport * as React from 'react';\nimport { Route } from 'react-router-dom';\nimport noop from 'lodash/noop';\nimport classNames from 'classnames';\nimport { Button } from '@box/blueprint-web';\nimport Tooltip from '../../components/tooltip/Tooltip';\nimport { isLeftClick } from '../../utils/dom';\nimport './SidebarNavButton.scss';\n\ntype Props = {\n 'data-resin-target'?: string,\n 'data-testid'?: string,\n children: React.Node,\n elementId?: string,\n isDisabled?: boolean,\n isOpen?: boolean,\n onClick?: (sidebarView: string) => void,\n sidebarView: string,\n tooltip: React.Node,\n};\n\nconst SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props, ref: React.Ref<any>) => {\n const {\n 'data-resin-target': dataResinTarget,\n 'data-testid': dataTestId,\n children,\n elementId = '',\n isDisabled,\n isOpen,\n onClick = noop,\n sidebarView,\n tooltip,\n } = props;\n const sidebarPath = `/${sidebarView}`;\n\n return (\n <Route path={sidebarPath}>\n {({ match, history }) => {\n const isMatch = !!match;\n const isActiveValue = isMatch && !!isOpen;\n const isExactMatch = isMatch && match.isExact;\n const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;\n\n const handleNavButtonClick = event => {\n onClick(sidebarView);\n\n if (!event.defaultPrevented && isLeftClick(event)) {\n const method = isExactMatch ? history.replace : history.push;\n method({\n pathname: sidebarPath,\n state: { open: true },\n });\n }\n };\n\n return (\n <Tooltip position=\"middle-left\" text={tooltip} isTabbable={false}>\n <Button\n accessibleWhenDisabled={true}\n aria-controls={`${id}-content`}\n aria-label={tooltip}\n aria-selected={isActiveValue}\n className={classNames('bcs-NavButton', {\n 'bcs-is-selected': isActiveValue,\n 'bdl-is-disabled': isDisabled,\n })}\n data-resin-target={dataResinTarget}\n data-testid={dataTestId}\n ref={ref}\n id={id}\n disabled={isDisabled}\n onClick={handleNavButtonClick}\n role=\"tab\"\n tabIndex={isActiveValue ? '0' : '-1'}\n type=\"button\"\n variant=\"tertiary\"\n >\n {children}\n </Button>\n </Tooltip>\n );\n }}\n </Route>\n );\n});\n\nexport default SidebarNavButton;\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,KAAK,QAAQ,kBAAkB;AACxC,OAAOC,IAAI,MAAM,aAAa;AAC9B,OAAOC,UAAU,MAAM,YAAY;AACnC,SAASC,MAAM,QAAQ,oBAAoB;AAC3C,OAAOC,OAAO,MAAM,kCAAkC;AACtD,SAASC,WAAW,QAAQ,iBAAiB;AAC7C,OAAO,yBAAyB;AAchC,MAAMC,gBAAgB,gBAAGP,KAAK,CAACQ,UAAU,CAAwB,CAACC,KAAY,EAAEC,GAAmB,KAAK;EACpG,MAAM;IACF,mBAAmB,EAAEC,eAAe;IACpC,aAAa,EAAEC,UAAU;IACzBC,QAAQ;IACRC,SAAS,GAAG,EAAE;IACdC,UAAU;IACVC,MAAM;IACNC,OAAO,GAAGf,IAAI;IACdgB,WAAW;IACXC;EACJ,CAAC,GAAGV,KAAK;EACT,MAAMW,WAAW,GAAG,IAAIF,WAAW,EAAE;EAErC,oBACIlB,KAAA,CAAAqB,aAAA,CAACpB,KAAK;IAACqB,IAAI,EAAEF;EAAY,GACpB,CAAC;IAAEG,KAAK;IAAEC;EAAQ,CAAC,KAAK;IACrB,MAAMC,OAAO,GAAG,CAAC,CAACF,KAAK;IACvB,MAAMG,aAAa,GAAGD,OAAO,IAAI,CAAC,CAACT,MAAM;IACzC,MAAMW,YAAY,GAAGF,OAAO,IAAIF,KAAK,CAACK,OAAO;IAC7C,MAAMC,EAAE,GAAG,GAAGf,SAAS,GAAGA,SAAS,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,GAAGI,WAAW,EAAE;IAErE,MAAMY,oBAAoB,GAAGC,KAAK,IAAI;MAClCd,OAAO,CAACC,WAAW,CAAC;MAEpB,IAAI,CAACa,KAAK,CAACC,gBAAgB,IAAI1B,WAAW,CAACyB,KAAK,CAAC,EAAE;QAC/C,MAAME,MAAM,GAAGN,YAAY,GAAGH,OAAO,CAACU,OAAO,GAAGV,OAAO,CAACW,IAAI;QAC5DF,MAAM,CAAC;UACHG,QAAQ,EAAEhB,WAAW;UACrBiB,KAAK,EAAE;YAAEC,IAAI,EAAE;UAAK;QACxB,CAAC,CAAC;MACN;IACJ,CAAC;IAED,oBACItC,KAAA,CAAAqB,aAAA,CAAChB,OAAO;MAACkC,QAAQ,EAAC,aAAa;MAACC,IAAI,EAAErB,OAAQ;MAACsB,UAAU,EAAE;IAAM,gBAC7DzC,KAAA,CAAAqB,aAAA,CAACjB,MAAM;MACHsC,sBAAsB,EAAE,IAAK;MAC7B,iBAAe,GAAGb,EAAE,UAAW;MAC/B,cAAYV,OAAQ;MACpB,iBAAeO,aAAc;MAC7BiB,SAAS,EAAExC,UAAU,CAAC,eAAe,EAAE;QACnC,iBAAiB,EAAEuB,aAAa;QAChC,iBAAiB,EAAEX;MACvB,CAAC,CAAE;MACH,qBAAmBJ,eAAgB;MACnC,eAAaC,UAAW;MACxBF,GAAG,EAAEA,GAAI;MACTmB,EAAE,EAAEA,EAAG;MACPe,QAAQ,EAAE7B,UAAW;MACrBE,OAAO,EAAEa,oBAAqB;MAC9Be,IAAI,EAAC,KAAK;MACVC,QAAQ,EAAEpB,aAAa,GAAG,GAAG,GAAG,IAAK;MACrCqB,IAAI,EAAC,QAAQ;MACbC,OAAO,EAAC;IAAU,GAEjBnC,QACG,CACH,CAAC;EAElB,CACG,CAAC;AAEhB,CAAC,CAAC;AAEF,eAAeN,gBAAgB","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"SidebarNavButton.js","names":["React","Route","noop","classNames","Button","Tooltip","isLeftClick","SidebarNavButton","forwardRef","props","ref","dataResinTarget","dataTestId","children","elementId","internalSidebarNavigation","internalSidebarNavigationHandler","isDisabled","isOpen","onClick","routerDisabled","sidebarView","tooltip","sidebarPath","id","isMatch","sidebar","isActiveValue","hasExtraParams","versionId","activeFeedEntryType","activeFeedEntryId","fileVersionId","isExactMatch","handleNavButtonClick","event","defaultPrevented","replace","open","createElement","position","text","isTabbable","accessibleWhenDisabled","className","disabled","role","tabIndex","type","variant","path","match","history","isExact","method","push","pathname","state"],"sources":["../../../src/elements/content-sidebar/SidebarNavButton.js"],"sourcesContent":["/**\n * @flow\n * @file Preview sidebar nav button component\n * @author Box\n */\n\nimport * as React from 'react';\nimport { Route } from 'react-router-dom';\nimport noop from 'lodash/noop';\nimport classNames from 'classnames';\nimport { Button } from '@box/blueprint-web';\nimport Tooltip from '../../components/tooltip/Tooltip';\nimport { isLeftClick } from '../../utils/dom';\nimport type { InternalSidebarNavigation, InternalSidebarNavigationHandler, ViewTypeValues } from '../common/types/SidebarNavigation';\nimport './SidebarNavButton.scss';\n\ntype Props = {\n 'data-resin-target'?: string,\n 'data-testid'?: string,\n children: React.Node,\n elementId?: string,\n internalSidebarNavigation?: InternalSidebarNavigation,\n internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,\n isDisabled?: boolean,\n isOpen?: boolean,\n onClick?: (sidebarView: ViewTypeValues) => void,\n routerDisabled?: boolean,\n sidebarView: ViewTypeValues,\n tooltip: React.Node,\n};\n\nconst SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props, ref: React.Ref<any>) => {\n const {\n 'data-resin-target': dataResinTarget,\n 'data-testid': dataTestId,\n children,\n elementId = '',\n internalSidebarNavigation,\n internalSidebarNavigationHandler,\n isDisabled,\n isOpen,\n onClick = noop,\n routerDisabled = false,\n sidebarView,\n tooltip,\n } = props;\n const sidebarPath = `/${sidebarView}`;\n const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;\n\n if (routerDisabled) {\n // Mimic router behavior using internalSidebarNavigation\n const isMatch = !!internalSidebarNavigation && internalSidebarNavigation.sidebar === sidebarView;\n const isActiveValue = isMatch && !!isOpen;\n \n // Mimic isExactMatch: true when no extra navigation parameters are present\n const hasExtraParams = internalSidebarNavigation && (\n internalSidebarNavigation.versionId ||\n internalSidebarNavigation.activeFeedEntryType ||\n internalSidebarNavigation.activeFeedEntryId ||\n internalSidebarNavigation.fileVersionId\n );\n const isExactMatch = isMatch && !hasExtraParams;\n \n const handleNavButtonClick = event => {\n onClick(sidebarView);\n \n // Mimic router navigation behavior\n if (internalSidebarNavigationHandler && !event.defaultPrevented && isLeftClick(event)) {\n const replace = isExactMatch;\n internalSidebarNavigationHandler({\n sidebar: sidebarView,\n open: true,\n }, replace);\n }\n };\n\n return (\n <Tooltip position=\"middle-left\" text={tooltip} isTabbable={false}>\n <Button\n accessibleWhenDisabled={true}\n aria-controls={`${id}-content`}\n aria-label={tooltip}\n aria-selected={isActiveValue}\n className={classNames('bcs-NavButton', {\n 'bcs-is-selected': isActiveValue,\n 'bdl-is-disabled': isDisabled,\n })}\n data-resin-target={dataResinTarget}\n data-testid={dataTestId}\n ref={ref}\n id={id}\n disabled={isDisabled}\n onClick={handleNavButtonClick}\n role=\"tab\"\n tabIndex={isActiveValue ? '0' : '-1'}\n type=\"button\"\n variant=\"tertiary\"\n >\n {children}\n </Button>\n </Tooltip>\n );\n }\n\n return (\n <Route path={sidebarPath}>\n {({ match, history }) => {\n const isMatch = !!match;\n const isActiveValue = isMatch && !!isOpen;\n const isExactMatch = isMatch && match.isExact;\n\n const handleNavButtonClick = event => {\n onClick(sidebarView);\n\n if (!event.defaultPrevented && isLeftClick(event)) {\n const method = isExactMatch ? history.replace : history.push;\n method({\n pathname: sidebarPath,\n state: { open: true },\n });\n }\n };\n\n return (\n <Tooltip position=\"middle-left\" text={tooltip} isTabbable={false}>\n <Button\n accessibleWhenDisabled={true}\n aria-controls={`${id}-content`}\n aria-label={tooltip}\n aria-selected={isActiveValue}\n className={classNames('bcs-NavButton', {\n 'bcs-is-selected': isActiveValue,\n 'bdl-is-disabled': isDisabled,\n })}\n data-resin-target={dataResinTarget}\n data-testid={dataTestId}\n ref={ref}\n id={id}\n disabled={isDisabled}\n onClick={handleNavButtonClick}\n role=\"tab\"\n tabIndex={isActiveValue ? '0' : '-1'}\n type=\"button\"\n variant=\"tertiary\"\n >\n {children}\n </Button>\n </Tooltip>\n );\n }}\n </Route>\n );\n});\n\nexport default SidebarNavButton;\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAC9B,SAASC,KAAK,QAAQ,kBAAkB;AACxC,OAAOC,IAAI,MAAM,aAAa;AAC9B,OAAOC,UAAU,MAAM,YAAY;AACnC,SAASC,MAAM,QAAQ,oBAAoB;AAC3C,OAAOC,OAAO,MAAM,kCAAkC;AACtD,SAASC,WAAW,QAAQ,iBAAiB;AAE7C,OAAO,yBAAyB;AAiBhC,MAAMC,gBAAgB,gBAAGP,KAAK,CAACQ,UAAU,CAAwB,CAACC,KAAY,EAAEC,GAAmB,KAAK;EACpG,MAAM;IACF,mBAAmB,EAAEC,eAAe;IACpC,aAAa,EAAEC,UAAU;IACzBC,QAAQ;IACRC,SAAS,GAAG,EAAE;IACdC,yBAAyB;IACzBC,gCAAgC;IAChCC,UAAU;IACVC,MAAM;IACNC,OAAO,GAAGjB,IAAI;IACdkB,cAAc,GAAG,KAAK;IACtBC,WAAW;IACXC;EACJ,CAAC,GAAGb,KAAK;EACT,MAAMc,WAAW,GAAG,IAAIF,WAAW,EAAE;EACrC,MAAMG,EAAE,GAAG,GAAGV,SAAS,GAAGA,SAAS,KAAK,EAAE,GAAG,EAAE,GAAG,GAAG,GAAGO,WAAW,EAAE;EAErE,IAAID,cAAc,EAAE;IAChB;IACA,MAAMK,OAAO,GAAG,CAAC,CAACV,yBAAyB,IAAIA,yBAAyB,CAACW,OAAO,KAAKL,WAAW;IAChG,MAAMM,aAAa,GAAGF,OAAO,IAAI,CAAC,CAACP,MAAM;;IAEzC;IACA,MAAMU,cAAc,GAAGb,yBAAyB,KAC5CA,yBAAyB,CAACc,SAAS,IACnCd,yBAAyB,CAACe,mBAAmB,IAC7Cf,yBAAyB,CAACgB,iBAAiB,IAC3ChB,yBAAyB,CAACiB,aAAa,CAC1C;IACD,MAAMC,YAAY,GAAGR,OAAO,IAAI,CAACG,cAAc;IAE/C,MAAMM,oBAAoB,GAAGC,KAAK,IAAI;MAClChB,OAAO,CAACE,WAAW,CAAC;;MAEpB;MACA,IAAIL,gCAAgC,IAAI,CAACmB,KAAK,CAACC,gBAAgB,IAAI9B,WAAW,CAAC6B,KAAK,CAAC,EAAE;QACnF,MAAME,OAAO,GAAGJ,YAAY;QAC5BjB,gCAAgC,CAAC;UAC7BU,OAAO,EAAEL,WAAW;UACpBiB,IAAI,EAAE;QACV,CAAC,EAAED,OAAO,CAAC;MACf;IACJ,CAAC;IAED,oBACIrC,KAAA,CAAAuC,aAAA,CAAClC,OAAO;MAACmC,QAAQ,EAAC,aAAa;MAACC,IAAI,EAAEnB,OAAQ;MAACoB,UAAU,EAAE;IAAM,gBAC7D1C,KAAA,CAAAuC,aAAA,CAACnC,MAAM;MACHuC,sBAAsB,EAAE,IAAK;MAC7B,iBAAe,GAAGnB,EAAE,UAAW;MAC/B,cAAYF,OAAQ;MACpB,iBAAeK,aAAc;MAC7BiB,SAAS,EAAEzC,UAAU,CAAC,eAAe,EAAE;QACnC,iBAAiB,EAAEwB,aAAa;QAChC,iBAAiB,EAAEV;MACvB,CAAC,CAAE;MACH,qBAAmBN,eAAgB;MACnC,eAAaC,UAAW;MACxBF,GAAG,EAAEA,GAAI;MACTc,EAAE,EAAEA,EAAG;MACPqB,QAAQ,EAAE5B,UAAW;MACrBE,OAAO,EAAEe,oBAAqB;MAC9BY,IAAI,EAAC,KAAK;MACVC,QAAQ,EAAEpB,aAAa,GAAG,GAAG,GAAG,IAAK;MACrCqB,IAAI,EAAC,QAAQ;MACbC,OAAO,EAAC;IAAU,GAEjBpC,QACG,CACH,CAAC;EAElB;EAEA,oBACIb,KAAA,CAAAuC,aAAA,CAACtC,KAAK;IAACiD,IAAI,EAAE3B;EAAY,GACpB,CAAC;IAAE4B,KAAK;IAAEC;EAAQ,CAAC,KAAK;IACrB,MAAM3B,OAAO,GAAG,CAAC,CAAC0B,KAAK;IACvB,MAAMxB,aAAa,GAAGF,OAAO,IAAI,CAAC,CAACP,MAAM;IACzC,MAAMe,YAAY,GAAGR,OAAO,IAAI0B,KAAK,CAACE,OAAO;IAE7C,MAAMnB,oBAAoB,GAAGC,KAAK,IAAI;MAClChB,OAAO,CAACE,WAAW,CAAC;MAEpB,IAAI,CAACc,KAAK,CAACC,gBAAgB,IAAI9B,WAAW,CAAC6B,KAAK,CAAC,EAAE;QAC/C,MAAMmB,MAAM,GAAGrB,YAAY,GAAGmB,OAAO,CAACf,OAAO,GAAGe,OAAO,CAACG,IAAI;QAC5DD,MAAM,CAAC;UACHE,QAAQ,EAAEjC,WAAW;UACrBkC,KAAK,EAAE;YAAEnB,IAAI,EAAE;UAAK;QACxB,CAAC,CAAC;MACN;IACJ,CAAC;IAED,oBACItC,KAAA,CAAAuC,aAAA,CAAClC,OAAO;MAACmC,QAAQ,EAAC,aAAa;MAACC,IAAI,EAAEnB,OAAQ;MAACoB,UAAU,EAAE;IAAM,gBAC7D1C,KAAA,CAAAuC,aAAA,CAACnC,MAAM;MACHuC,sBAAsB,EAAE,IAAK;MAC7B,iBAAe,GAAGnB,EAAE,UAAW;MAC/B,cAAYF,OAAQ;MACpB,iBAAeK,aAAc;MAC7BiB,SAAS,EAAEzC,UAAU,CAAC,eAAe,EAAE;QACnC,iBAAiB,EAAEwB,aAAa;QAChC,iBAAiB,EAAEV;MACvB,CAAC,CAAE;MACH,qBAAmBN,eAAgB;MACnC,eAAaC,UAAW;MACxBF,GAAG,EAAEA,GAAI;MACTc,EAAE,EAAEA,EAAG;MACPqB,QAAQ,EAAE5B,UAAW;MACrBE,OAAO,EAAEe,oBAAqB;MAC9BY,IAAI,EAAC,KAAK;MACVC,QAAQ,EAAEpB,aAAa,GAAG,GAAG,GAAG,IAAK;MACrCqB,IAAI,EAAC,QAAQ;MACbC,OAAO,EAAC;IAAU,GAEjBpC,QACG,CACH,CAAC;EAElB,CACG,CAAC;AAEhB,CAAC,CAAC;AAEF,eAAeN,gBAAgB","ignoreList":[]}
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
.header-flyout-overlay {
|
|
13
13
|
width: $flyout-list-width;
|
|
14
14
|
height: $flyout-list-height;
|
|
15
|
+
animation: bdl-open-flyout-animation 0.3s cubic-bezier(0.32, 0, 0.33, 1.3);
|
|
16
|
+
animation-fill-mode: both;
|
|
17
|
+
transform-origin: top right;
|
|
18
|
+
|
|
19
|
+
@media (prefers-reduced-motion: reduce) {
|
|
20
|
+
animation: none;
|
|
21
|
+
}
|
|
15
22
|
|
|
16
23
|
.overlay {
|
|
17
24
|
@include bdl-Overlay-container;
|
|
@@ -27,6 +34,18 @@
|
|
|
27
34
|
}
|
|
28
35
|
}
|
|
29
36
|
|
|
37
|
+
@keyframes bdl-open-flyout-animation {
|
|
38
|
+
from {
|
|
39
|
+
opacity: 0;
|
|
40
|
+
transform: translateY(-10px) scale(0.95);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
to {
|
|
44
|
+
opacity: 1;
|
|
45
|
+
transform: translateY(0) scale(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
.header-flyout-list-container {
|
|
31
50
|
.flyout-list-container-body {
|
|
32
51
|
// the overall height, minus the top and bottom padding
|
|
@@ -102,6 +121,8 @@
|
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
.header-flyout-overlay {
|
|
124
|
+
animation: none;
|
|
125
|
+
|
|
105
126
|
.header-flyout-title {
|
|
106
127
|
padding-bottom: 0;
|
|
107
128
|
}
|
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import classNames from 'classnames';
|
|
|
11
11
|
import { Button } from '@box/blueprint-web';
|
|
12
12
|
import Tooltip from '../../components/tooltip/Tooltip';
|
|
13
13
|
import { isLeftClick } from '../../utils/dom';
|
|
14
|
+
import type { InternalSidebarNavigation, InternalSidebarNavigationHandler, ViewTypeValues } from '../common/types/SidebarNavigation';
|
|
14
15
|
import './SidebarNavButton.scss';
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
@@ -18,10 +19,13 @@ type Props = {
|
|
|
18
19
|
'data-testid'?: string,
|
|
19
20
|
children: React.Node,
|
|
20
21
|
elementId?: string,
|
|
22
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
23
|
+
internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
|
|
21
24
|
isDisabled?: boolean,
|
|
22
25
|
isOpen?: boolean,
|
|
23
|
-
onClick?: (sidebarView:
|
|
24
|
-
|
|
26
|
+
onClick?: (sidebarView: ViewTypeValues) => void,
|
|
27
|
+
routerDisabled?: boolean,
|
|
28
|
+
sidebarView: ViewTypeValues,
|
|
25
29
|
tooltip: React.Node,
|
|
26
30
|
};
|
|
27
31
|
|
|
@@ -31,13 +35,72 @@ const SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props,
|
|
|
31
35
|
'data-testid': dataTestId,
|
|
32
36
|
children,
|
|
33
37
|
elementId = '',
|
|
38
|
+
internalSidebarNavigation,
|
|
39
|
+
internalSidebarNavigationHandler,
|
|
34
40
|
isDisabled,
|
|
35
41
|
isOpen,
|
|
36
42
|
onClick = noop,
|
|
43
|
+
routerDisabled = false,
|
|
37
44
|
sidebarView,
|
|
38
45
|
tooltip,
|
|
39
46
|
} = props;
|
|
40
47
|
const sidebarPath = `/${sidebarView}`;
|
|
48
|
+
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
49
|
+
|
|
50
|
+
if (routerDisabled) {
|
|
51
|
+
// Mimic router behavior using internalSidebarNavigation
|
|
52
|
+
const isMatch = !!internalSidebarNavigation && internalSidebarNavigation.sidebar === sidebarView;
|
|
53
|
+
const isActiveValue = isMatch && !!isOpen;
|
|
54
|
+
|
|
55
|
+
// Mimic isExactMatch: true when no extra navigation parameters are present
|
|
56
|
+
const hasExtraParams = internalSidebarNavigation && (
|
|
57
|
+
internalSidebarNavigation.versionId ||
|
|
58
|
+
internalSidebarNavigation.activeFeedEntryType ||
|
|
59
|
+
internalSidebarNavigation.activeFeedEntryId ||
|
|
60
|
+
internalSidebarNavigation.fileVersionId
|
|
61
|
+
);
|
|
62
|
+
const isExactMatch = isMatch && !hasExtraParams;
|
|
63
|
+
|
|
64
|
+
const handleNavButtonClick = event => {
|
|
65
|
+
onClick(sidebarView);
|
|
66
|
+
|
|
67
|
+
// Mimic router navigation behavior
|
|
68
|
+
if (internalSidebarNavigationHandler && !event.defaultPrevented && isLeftClick(event)) {
|
|
69
|
+
const replace = isExactMatch;
|
|
70
|
+
internalSidebarNavigationHandler({
|
|
71
|
+
sidebar: sidebarView,
|
|
72
|
+
open: true,
|
|
73
|
+
}, replace);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<Tooltip position="middle-left" text={tooltip} isTabbable={false}>
|
|
79
|
+
<Button
|
|
80
|
+
accessibleWhenDisabled={true}
|
|
81
|
+
aria-controls={`${id}-content`}
|
|
82
|
+
aria-label={tooltip}
|
|
83
|
+
aria-selected={isActiveValue}
|
|
84
|
+
className={classNames('bcs-NavButton', {
|
|
85
|
+
'bcs-is-selected': isActiveValue,
|
|
86
|
+
'bdl-is-disabled': isDisabled,
|
|
87
|
+
})}
|
|
88
|
+
data-resin-target={dataResinTarget}
|
|
89
|
+
data-testid={dataTestId}
|
|
90
|
+
ref={ref}
|
|
91
|
+
id={id}
|
|
92
|
+
disabled={isDisabled}
|
|
93
|
+
onClick={handleNavButtonClick}
|
|
94
|
+
role="tab"
|
|
95
|
+
tabIndex={isActiveValue ? '0' : '-1'}
|
|
96
|
+
type="button"
|
|
97
|
+
variant="tertiary"
|
|
98
|
+
>
|
|
99
|
+
{children}
|
|
100
|
+
</Button>
|
|
101
|
+
</Tooltip>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
41
104
|
|
|
42
105
|
return (
|
|
43
106
|
<Route path={sidebarPath}>
|
|
@@ -45,7 +108,6 @@ const SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props,
|
|
|
45
108
|
const isMatch = !!match;
|
|
46
109
|
const isActiveValue = isMatch && !!isOpen;
|
|
47
110
|
const isExactMatch = isMatch && match.isExact;
|
|
48
|
-
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
49
111
|
|
|
50
112
|
const handleNavButtonClick = event => {
|
|
51
113
|
onClick(sidebarView);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { MemoryRouter, Router } from 'react-router-dom';
|
|
3
|
+
// Using fireEvent for all click interactions instead of userEvent because
|
|
4
|
+
// userEvent.pointer with right-click doesn't reliably trigger onClick handlers
|
|
3
5
|
import { render, screen, fireEvent } from '../../../test-utils/testing-library';
|
|
4
6
|
import SidebarNavButton from '../SidebarNavButton';
|
|
5
7
|
|
|
@@ -197,7 +199,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
197
199
|
renderWithRouter({ onClick: mockOnClick }, mockHistoryWithDifferentPath);
|
|
198
200
|
|
|
199
201
|
const button = screen.getByText('Activity');
|
|
200
|
-
fireEvent.click(button
|
|
202
|
+
fireEvent.click(button);
|
|
201
203
|
|
|
202
204
|
expect(mockOnClick).toBeCalledWith('activity');
|
|
203
205
|
expect(mockHistoryPush).toBeCalledWith({
|
|
@@ -213,7 +215,7 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
213
215
|
renderWithRouter({ onClick: mockOnClick });
|
|
214
216
|
|
|
215
217
|
const button = screen.getByText('Activity');
|
|
216
|
-
fireEvent.click(button
|
|
218
|
+
fireEvent.click(button);
|
|
217
219
|
|
|
218
220
|
expect(mockOnClick).toBeCalledWith('activity');
|
|
219
221
|
expect(mockHistoryReplace).toBeCalledWith({
|
|
@@ -243,7 +245,6 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
243
245
|
|
|
244
246
|
const button = screen.getByText('Activity');
|
|
245
247
|
|
|
246
|
-
// Prevent default on the button click
|
|
247
248
|
button.addEventListener('click', e => e.preventDefault());
|
|
248
249
|
fireEvent.click(button, { button: 0 });
|
|
249
250
|
|
|
@@ -253,3 +254,154 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
253
254
|
});
|
|
254
255
|
});
|
|
255
256
|
});
|
|
257
|
+
|
|
258
|
+
describe('elements/content-sidebar/SidebarNavButton - Router Disabled', () => {
|
|
259
|
+
beforeEach(() => {
|
|
260
|
+
jest.clearAllMocks();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
const defaultProps = {
|
|
264
|
+
routerDisabled: true,
|
|
265
|
+
tooltip: 'foo',
|
|
266
|
+
sidebarView: 'activity',
|
|
267
|
+
internalSidebarNavigation: { sidebar: 'skills' },
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
const renderWithoutRouter = ({ children = 'test button', ref, ...props }) =>
|
|
271
|
+
render(
|
|
272
|
+
<SidebarNavButton ref={ref} {...defaultProps} {...props}>
|
|
273
|
+
{children}
|
|
274
|
+
</SidebarNavButton>,
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
test('should render nav button properly', () => {
|
|
278
|
+
renderWithoutRouter({});
|
|
279
|
+
const button = screen.getByRole('tab');
|
|
280
|
+
|
|
281
|
+
expect(button).toHaveAttribute('aria-label', 'foo');
|
|
282
|
+
expect(button).toHaveAttribute('aria-selected', 'false');
|
|
283
|
+
expect(button).toHaveAttribute('aria-controls', 'activity-content');
|
|
284
|
+
expect(button).toHaveAttribute('role', 'tab');
|
|
285
|
+
expect(button).toHaveAttribute('tabindex', '-1');
|
|
286
|
+
expect(button).toHaveAttribute('type', 'button');
|
|
287
|
+
expect(button).toHaveAttribute('id', 'activity');
|
|
288
|
+
expect(button).toHaveClass('bcs-NavButton');
|
|
289
|
+
expect(button).not.toHaveClass('bcs-is-selected');
|
|
290
|
+
expect(button).toHaveTextContent('test button');
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test.each`
|
|
294
|
+
internalSidebarNavigation | expected
|
|
295
|
+
${null} | ${false}
|
|
296
|
+
${undefined} | ${false}
|
|
297
|
+
${{ sidebar: 'skills' }} | ${false}
|
|
298
|
+
${{ sidebar: 'activity' }} | ${true}
|
|
299
|
+
${{ sidebar: 'activity', versionId: '123' }} | ${true}
|
|
300
|
+
`('should reflect active state ($expected) correctly based on internal navigation', ({ expected, internalSidebarNavigation }) => {
|
|
301
|
+
renderWithoutRouter({
|
|
302
|
+
internalSidebarNavigation,
|
|
303
|
+
isOpen: true,
|
|
304
|
+
});
|
|
305
|
+
const button = screen.getByRole('tab');
|
|
306
|
+
|
|
307
|
+
if (expected) {
|
|
308
|
+
expect(button).toHaveClass('bcs-is-selected');
|
|
309
|
+
expect(button).toHaveAttribute('aria-selected', 'true');
|
|
310
|
+
expect(button).toHaveAttribute('tabindex', '0');
|
|
311
|
+
} else {
|
|
312
|
+
expect(button).not.toHaveClass('bcs-is-selected');
|
|
313
|
+
expect(button).toHaveAttribute('aria-selected', 'false');
|
|
314
|
+
expect(button).toHaveAttribute('tabindex', '-1');
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test('should call onClick with sidebarView when clicked', () => {
|
|
319
|
+
const mockOnClick = jest.fn();
|
|
320
|
+
const mockSidebarView = 'activity';
|
|
321
|
+
|
|
322
|
+
renderWithoutRouter({
|
|
323
|
+
onClick: mockOnClick,
|
|
324
|
+
sidebarView: mockSidebarView,
|
|
325
|
+
});
|
|
326
|
+
const button = screen.getByRole('tab');
|
|
327
|
+
|
|
328
|
+
fireEvent.click(button);
|
|
329
|
+
expect(mockOnClick).toBeCalledWith(mockSidebarView);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe('navigation on click', () => {
|
|
333
|
+
const mockInternalSidebarNavigationHandler = jest.fn();
|
|
334
|
+
|
|
335
|
+
test('calls onClick handler and internalSidebarNavigationHandler with replace=false when not exact match', () => {
|
|
336
|
+
const mockOnClick = jest.fn();
|
|
337
|
+
|
|
338
|
+
renderWithoutRouter({
|
|
339
|
+
onClick: mockOnClick,
|
|
340
|
+
internalSidebarNavigation: { sidebar: 'activity', versionId: '123' },
|
|
341
|
+
internalSidebarNavigationHandler: mockInternalSidebarNavigationHandler,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
const button = screen.getByRole('tab');
|
|
345
|
+
fireEvent.click(button);
|
|
346
|
+
|
|
347
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
348
|
+
expect(mockInternalSidebarNavigationHandler).toBeCalledWith({
|
|
349
|
+
sidebar: 'activity',
|
|
350
|
+
open: true,
|
|
351
|
+
}, false);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('calls internalSidebarNavigationHandler with replace=true when exact match', () => {
|
|
355
|
+
const mockOnClick = jest.fn();
|
|
356
|
+
|
|
357
|
+
renderWithoutRouter({
|
|
358
|
+
onClick: mockOnClick,
|
|
359
|
+
internalSidebarNavigation: { sidebar: 'activity' },
|
|
360
|
+
internalSidebarNavigationHandler: mockInternalSidebarNavigationHandler,
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
const button = screen.getByRole('tab');
|
|
364
|
+
fireEvent.click(button);
|
|
365
|
+
|
|
366
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
367
|
+
expect(mockInternalSidebarNavigationHandler).toBeCalledWith({
|
|
368
|
+
sidebar: 'activity',
|
|
369
|
+
open: true,
|
|
370
|
+
}, true);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test('does not call internalSidebarNavigationHandler on right click', () => {
|
|
374
|
+
const mockOnClick = jest.fn();
|
|
375
|
+
|
|
376
|
+
renderWithoutRouter({
|
|
377
|
+
onClick: mockOnClick,
|
|
378
|
+
internalSidebarNavigation: { sidebar: 'activity' },
|
|
379
|
+
internalSidebarNavigationHandler: mockInternalSidebarNavigationHandler,
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
const button = screen.getByRole('tab');
|
|
383
|
+
fireEvent.click(button, { button: 1 });
|
|
384
|
+
|
|
385
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
386
|
+
expect(mockInternalSidebarNavigationHandler).not.toBeCalled();
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
test('does not call internalSidebarNavigationHandler on prevented event', () => {
|
|
390
|
+
const mockOnClick = jest.fn();
|
|
391
|
+
|
|
392
|
+
renderWithoutRouter({
|
|
393
|
+
onClick: mockOnClick,
|
|
394
|
+
internalSidebarNavigation: { sidebar: 'activity' },
|
|
395
|
+
internalSidebarNavigationHandler: mockInternalSidebarNavigationHandler,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
const button = screen.getByRole('tab');
|
|
399
|
+
|
|
400
|
+
button.addEventListener('click', e => e.preventDefault());
|
|
401
|
+
fireEvent.click(button, { button: 0 });
|
|
402
|
+
|
|
403
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
404
|
+
expect(mockInternalSidebarNavigationHandler).not.toBeCalled();
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
});
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
.header-flyout-overlay {
|
|
13
13
|
width: $flyout-list-width;
|
|
14
14
|
height: $flyout-list-height;
|
|
15
|
+
animation: bdl-open-flyout-animation 0.3s cubic-bezier(0.32, 0, 0.33, 1.3);
|
|
16
|
+
animation-fill-mode: both;
|
|
17
|
+
transform-origin: top right;
|
|
18
|
+
|
|
19
|
+
@media (prefers-reduced-motion: reduce) {
|
|
20
|
+
animation: none;
|
|
21
|
+
}
|
|
15
22
|
|
|
16
23
|
.overlay {
|
|
17
24
|
@include bdl-Overlay-container;
|
|
@@ -27,6 +34,18 @@
|
|
|
27
34
|
}
|
|
28
35
|
}
|
|
29
36
|
|
|
37
|
+
@keyframes bdl-open-flyout-animation {
|
|
38
|
+
from {
|
|
39
|
+
opacity: 0;
|
|
40
|
+
transform: translateY(-10px) scale(0.95);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
to {
|
|
44
|
+
opacity: 1;
|
|
45
|
+
transform: translateY(0) scale(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
30
49
|
.header-flyout-list-container {
|
|
31
50
|
.flyout-list-container-body {
|
|
32
51
|
// the overall height, minus the top and bottom padding
|
|
@@ -102,6 +121,8 @@
|
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
.header-flyout-overlay {
|
|
124
|
+
animation: none;
|
|
125
|
+
|
|
105
126
|
.header-flyout-title {
|
|
106
127
|
padding-bottom: 0;
|
|
107
128
|
}
|