@madie/madie-design-system 1.2.62 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -1
- package/.storybook/.babelrc +2 -1
- package/.storybook/main.js +3 -11
- package/components/AutoComplete/AutoComplete.jsx +1 -1
- package/components/Button/Button.stories.js +0 -2
- package/components/DateField/DateField.jsx +1 -1
- package/components/DateField/DateField.stories.jsx +23 -10
- package/components/DateTimeField/DateTimeField.jsx +6 -2
- package/components/DateTimeField/DateTimeField.stories.jsx +29 -19
- package/components/Instant/Instant.stories.js +14 -6
- package/components/MadieAlert/MadieAlert.stories.js +35 -29
- package/components/MadieAlert/index.jsx +5 -5
- package/components/MadieConfirmDialog/MadieConfirmDialog.stories.js +17 -27
- package/components/MadieDeleteDialog/MadieDeleteDialog.stories.js +9 -18
- package/components/MadieDialog/MadieDialog.stories.js +45 -116
- package/components/MadieDialog/index.jsx +4 -2
- package/components/MadieDiscardDialog/MadieDiscardDialog.stories.js +5 -7
- package/components/MadieSpinner/MadieSpinner.stories.js +1 -3
- package/components/MadieTooltip/MadieTooltip.stories.js +7 -2
- package/components/Modal/Modal.stories.js +18 -89
- package/components/NotificationBanner/NotificationBanner.stories.js +17 -11
- package/components/NotificationBanner/index.js +3 -3
- package/components/NumberInput/NumberInput.stories.js +51 -63
- package/components/Popover/Popover.stories.js +6 -14
- package/components/Popover/index.js +2 -2
- package/components/RadioButton/RadioButton.jsx +4 -2
- package/components/RadioButton/RadioButton.stories.jsx +6 -2
- package/components/ReadOnlyTextField/ReadOnlyTextField.stories.js +4 -3
- package/components/ReadOnlyTextField/index.jsx +1 -1
- package/components/RichTextEditor/RichTextEditor.stories.js +10 -8
- package/components/RichTextEditor/index.jsx +14 -15
- package/components/Search/Search.stories.js +2 -4
- package/components/Select/Select.stories.js +59 -160
- package/components/Select/index.jsx +1 -1
- package/components/Tabs/Tabs.stories.js +78 -210
- package/components/TextArea/TextArea.stories.js +88 -108
- package/components/TextArea/index.jsx +1 -1
- package/components/TextField/TextField.stories.js +101 -124
- package/components/TextField/index.jsx +1 -1
- package/components/TimeField/TimeField.stories.js +18 -8
- package/components/Toast/Toast.stories.js +42 -102
- package/components/TruncateText/TruncateText.stories.js +22 -17
- package/components/hooks/useGetConfig.js +2 -2
- package/components/index.js +0 -24
- package/dist/browser.js +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +182 -51
- package/dist/react/index.js.LICENSE.txt +27 -24
- package/dist/react/index.js.map +1 -1
- package/eslint.config.js +56 -0
- package/index.js +7 -9
- package/package.json +43 -75
- package/test/components/Accordion.test.js +1 -1
- package/test/components/AutoComplete.test.js +11 -6
- package/test/components/Button.test.js +7 -3
- package/test/components/DateField.test.js +25 -29
- package/test/components/DateTimeField.test.js +21 -25
- package/test/components/Instant.test.js +1 -1
- package/test/components/MadieAlert.test.js +22 -22
- package/test/components/MadieConfirmDialog.test.js +42 -64
- package/test/components/MadieDeleteDialog.test.js +51 -69
- package/test/components/MadieDialog.test.js +13 -13
- package/test/components/MadieDiscardDialog.test.js +28 -45
- package/test/components/MadieSpinner.test.js +12 -17
- package/test/components/Modal.test.js +115 -0
- package/test/components/Pagination.test.js +2 -2
- package/test/components/RadioButton.test.js +7 -7
- package/test/components/ReadOnlyTextField.test.js +4 -2
- package/test/components/RichTextEditor.test.js +90 -6
- package/test/components/Search.test.js +75 -0
- package/test/components/Select.test.js +97 -107
- package/test/components/Tabs.test.js +22 -24
- package/test/components/TextArea.test.js +78 -92
- package/test/components/TextField.test.js +128 -147
- package/test/components/Toast.test.js +67 -78
- package/test/components/TruncateText.test.js +75 -0
- package/test/components/index.test.js +23 -0
- package/webpack.config.js +0 -1
- package/.eslintignore +0 -5
- package/components/Alert/Alert.stories.js +0 -70
- package/components/Alert/index.js +0 -55
- package/components/Breadcrumb/Breadcrumb.md +0 -28
- package/components/Breadcrumb/Breadcrumb.stories.js +0 -76
- package/components/Breadcrumb/index.js +0 -92
- package/components/CalloutBox/CalloutBox.stories.js +0 -94
- package/components/CalloutBox/index.js +0 -109
- package/components/Card/Card.stories.js +0 -163
- package/components/Card/index.js +0 -144
- package/components/Dropdown/Dropdown.stories.js +0 -94
- package/components/Dropdown/index.js +0 -85
- package/components/Error/Collapsible.jsx +0 -93
- package/components/Error/ErrorUI.jsx +0 -31
- package/components/Error/error.js +0 -26
- package/components/FlashNotification/FlashNotificationUI.jsx +0 -91
- package/components/FlashNotification/index.js +0 -30
- package/components/Footer/Footer.stories.js +0 -20
- package/components/Footer/FooterUI.jsx +0 -137
- package/components/Footer/LegacyFooterUI.jsx +0 -204
- package/components/Footer/SocialLinks.jsx +0 -63
- package/components/Footer/Subscribe.jsx +0 -34
- package/components/Footer/footer.js +0 -30
- package/components/Infotip/Infotip.jsx +0 -75
- package/components/Infotip/Infotip.stories.js +0 -52
- package/components/Infotip/InfotipIcon.jsx +0 -41
- package/components/Infotip/index.js +0 -3
- package/components/Link/Link.stories.js +0 -82
- package/components/Link/index.js +0 -61
- package/components/Spinner/index.js +0 -9
- package/components/TextInput/TextInput.stories.js +0 -118
- package/components/TextInput/index.js +0 -137
- package/components/Tooltip/Tooltip.jsx +0 -88
- package/components/Tooltip/Tooltip.stories.js +0 -80
- package/components/Tooltip/index.js +0 -3
- package/components/Tooltip/position.js +0 -76
- package/test/components/ErrorUI.test.js +0 -32
- package/test/components/FooterUI.test.js +0 -122
- package/test/components/Infotip.test.js +0 -76
- package/test/components/Tooltip.test.js +0 -147
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import DSLink from "./index";
|
|
3
|
-
import { withKnobs } from "@storybook/addon-knobs";
|
|
4
|
-
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
title: "Link",
|
|
8
|
-
component: DSLink,
|
|
9
|
-
decorators: [withKnobs],
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export const LinkLabel = () => <DSLink href="#">Link Label</DSLink>;
|
|
13
|
-
|
|
14
|
-
export const LinkColorVariants = () => (
|
|
15
|
-
<>
|
|
16
|
-
<div className=" qpp-dark-background qpp-u-padding--16">
|
|
17
|
-
<DSLink href="#" variant="white">
|
|
18
|
-
Link Label
|
|
19
|
-
</DSLink>
|
|
20
|
-
</div>
|
|
21
|
-
<p>
|
|
22
|
-
<DSLink href="#" variant="gray">
|
|
23
|
-
Link Label
|
|
24
|
-
</DSLink>
|
|
25
|
-
</p>
|
|
26
|
-
</>
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
export const inlineLinks = () => (
|
|
30
|
-
<div className="qpp-u-padding--16">
|
|
31
|
-
<p className="qpp-u-width--60">
|
|
32
|
-
Aenean lacinia <DSLink href="#">inline link</DSLink> nulla sed{" "}
|
|
33
|
-
<DSLink href="#">inline link</DSLink>. Integer posuere erat a ante
|
|
34
|
-
venenatis dapibus posuere velit aliquet. Integer posuere erat a ante
|
|
35
|
-
venenatis <DSLink href="#">inline link</DSLink> dapibus posuere
|
|
36
|
-
velit aliquet.
|
|
37
|
-
</p>
|
|
38
|
-
</div>
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
export const inlineLinksDarkBackground = () => (
|
|
42
|
-
<div className="qpp-dark-background qpp-u-padding--16">
|
|
43
|
-
Aenean lacinia{" "}
|
|
44
|
-
<DSLink href="#" variant="white">
|
|
45
|
-
inline link
|
|
46
|
-
</DSLink>{" "}
|
|
47
|
-
nulla sed{" "}
|
|
48
|
-
<DSLink href="#" variant="white">
|
|
49
|
-
inline link
|
|
50
|
-
</DSLink>
|
|
51
|
-
. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
|
|
52
|
-
Integer posuere erat a ante venenatis{" "}
|
|
53
|
-
<DSLink href="#" variant="white">
|
|
54
|
-
inline link
|
|
55
|
-
</DSLink>{" "}
|
|
56
|
-
dapibus posuere velit aliquet.
|
|
57
|
-
</div>
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
export const linkWithIcon = () => {
|
|
61
|
-
const icon = <OpenInNewIcon classes={{ root: "qpp-icon-mat" }} />;
|
|
62
|
-
return (
|
|
63
|
-
<div className="qpp-u-padding--16">
|
|
64
|
-
<DSLink href="#">
|
|
65
|
-
Standalone Link With Icon
|
|
66
|
-
{icon}
|
|
67
|
-
</DSLink>{" "}
|
|
68
|
-
<p className=" qpp-u-width--60">
|
|
69
|
-
Aenean lacinia{" "}
|
|
70
|
-
<DSLink href="#">
|
|
71
|
-
inline link
|
|
72
|
-
{icon}
|
|
73
|
-
</DSLink>{" "}
|
|
74
|
-
nulla sed <DSLink href="#">inline link {icon}</DSLink>. Integer
|
|
75
|
-
posuere erat a ante venenatis dapibus posuere velit aliquet.
|
|
76
|
-
Integer posuere erat a ante venenatis{" "}
|
|
77
|
-
<DSLink href="#">inline link {icon}</DSLink> dapibus posuere
|
|
78
|
-
velit aliquet.
|
|
79
|
-
</p>
|
|
80
|
-
</div>
|
|
81
|
-
);
|
|
82
|
-
};
|
package/components/Link/index.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
|
|
4
|
-
const VARIANTS = ["white", "gray"];
|
|
5
|
-
|
|
6
|
-
const DSLink = ({
|
|
7
|
-
className,
|
|
8
|
-
href,
|
|
9
|
-
download,
|
|
10
|
-
ariaLabel,
|
|
11
|
-
onClick,
|
|
12
|
-
children,
|
|
13
|
-
variant,
|
|
14
|
-
...rest
|
|
15
|
-
}) => {
|
|
16
|
-
let linkClass = "qpp-c-link";
|
|
17
|
-
if (VARIANTS.includes(variant)) {
|
|
18
|
-
variant === "gray"
|
|
19
|
-
? (linkClass = linkClass.concat(" ", "qpp-u-color--gray-60"))
|
|
20
|
-
: (linkClass = linkClass.concat(" ", `qpp-u-color--${variant}`));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (className) {
|
|
24
|
-
linkClass = linkClass.concat(" ", className);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<a
|
|
29
|
-
aria-label={ariaLabel}
|
|
30
|
-
className={linkClass || ""}
|
|
31
|
-
href={href}
|
|
32
|
-
download={download}
|
|
33
|
-
onClick={onClick}
|
|
34
|
-
{...rest}
|
|
35
|
-
>
|
|
36
|
-
{children}
|
|
37
|
-
</a>
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
DSLink.propTypes = {
|
|
42
|
-
children: PropTypes.node,
|
|
43
|
-
className: PropTypes.string,
|
|
44
|
-
href: PropTypes.string,
|
|
45
|
-
ariaLabel: PropTypes.string,
|
|
46
|
-
onClick: PropTypes.func,
|
|
47
|
-
download: PropTypes.bool,
|
|
48
|
-
variant: PropTypes.oneOf(VARIANTS),
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
DSLink.defaultProps = {
|
|
52
|
-
children: null,
|
|
53
|
-
className: "",
|
|
54
|
-
href: "",
|
|
55
|
-
ariaLabel: null,
|
|
56
|
-
onClick: () => null,
|
|
57
|
-
download: false,
|
|
58
|
-
variant: null,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export default DSLink;
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import TextInput from "./index";
|
|
4
|
-
import { withKnobs } from "@storybook/addon-knobs";
|
|
5
|
-
|
|
6
|
-
export default {
|
|
7
|
-
title: "Text Input",
|
|
8
|
-
component: TextInput,
|
|
9
|
-
decorators: [withKnobs],
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const optionalProps = {
|
|
13
|
-
"aria-label": "example label",
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const Wrapper = ({ children }) => (
|
|
17
|
-
<div className="qpp-u-padding--16">{children}</div>
|
|
18
|
-
);
|
|
19
|
-
Wrapper.propTypes = {
|
|
20
|
-
children: PropTypes.node,
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const InputField = () => (
|
|
24
|
-
<Wrapper>
|
|
25
|
-
<TextInput
|
|
26
|
-
style={{ width: "auto" }}
|
|
27
|
-
id="example"
|
|
28
|
-
name="single-example"
|
|
29
|
-
value="Example value"
|
|
30
|
-
label="Input Field"
|
|
31
|
-
{...optionalProps}
|
|
32
|
-
/>
|
|
33
|
-
</Wrapper>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export const InputFieldWithPlaceholder = () => (
|
|
37
|
-
<Wrapper>
|
|
38
|
-
<TextInput
|
|
39
|
-
id="placeholder-example"
|
|
40
|
-
name="placheholder"
|
|
41
|
-
label="Placeholder Example"
|
|
42
|
-
placeholder="Placeholder value"
|
|
43
|
-
/>
|
|
44
|
-
</Wrapper>
|
|
45
|
-
);
|
|
46
|
-
export const DisabledInputField = () => (
|
|
47
|
-
<Wrapper>
|
|
48
|
-
<TextInput
|
|
49
|
-
disabled={true}
|
|
50
|
-
id="disabled-example"
|
|
51
|
-
name="disabled_example"
|
|
52
|
-
value="Example value"
|
|
53
|
-
label="Disabled Example"
|
|
54
|
-
/>
|
|
55
|
-
</Wrapper>
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
export const FocusedInputField = () => (
|
|
59
|
-
<Wrapper>
|
|
60
|
-
<TextInput
|
|
61
|
-
id="focused-example"
|
|
62
|
-
name="focused_example"
|
|
63
|
-
value="Example value"
|
|
64
|
-
label="Focused Example"
|
|
65
|
-
className="qpp-c-text-input--focus"
|
|
66
|
-
/>
|
|
67
|
-
</Wrapper>
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
export const ErrorInputField = () => (
|
|
71
|
-
<Wrapper>
|
|
72
|
-
<TextInput
|
|
73
|
-
className="qpp-u-margin-bottom--8"
|
|
74
|
-
id="error-example"
|
|
75
|
-
name="error_example"
|
|
76
|
-
value="Example value"
|
|
77
|
-
error="Error Message"
|
|
78
|
-
label="Error Example"
|
|
79
|
-
/>
|
|
80
|
-
</Wrapper>
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
export const SuccessInputField = () => (
|
|
84
|
-
<Wrapper>
|
|
85
|
-
<TextInput
|
|
86
|
-
variant="success"
|
|
87
|
-
id="success-example"
|
|
88
|
-
name="success"
|
|
89
|
-
value="Example value"
|
|
90
|
-
label="Success Example"
|
|
91
|
-
/>
|
|
92
|
-
</Wrapper>
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
export const InputFieldWithHint = () => (
|
|
96
|
-
<Wrapper>
|
|
97
|
-
<TextInput
|
|
98
|
-
className="qpp-u-margin-bottom--8"
|
|
99
|
-
id="hint-example"
|
|
100
|
-
name="hint"
|
|
101
|
-
value="Example value"
|
|
102
|
-
label="Hint Example"
|
|
103
|
-
hint="Hint Message"
|
|
104
|
-
/>
|
|
105
|
-
</Wrapper>
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
export const BigInput = () => (
|
|
109
|
-
<Wrapper>
|
|
110
|
-
<TextInput
|
|
111
|
-
id="big-example"
|
|
112
|
-
name="hint"
|
|
113
|
-
value="Example value"
|
|
114
|
-
label="Big Example"
|
|
115
|
-
size="big"
|
|
116
|
-
/>
|
|
117
|
-
</Wrapper>
|
|
118
|
-
);
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
|
|
4
|
-
const TextInput = ({
|
|
5
|
-
id,
|
|
6
|
-
name,
|
|
7
|
-
placeholder,
|
|
8
|
-
disabled,
|
|
9
|
-
required,
|
|
10
|
-
size,
|
|
11
|
-
className,
|
|
12
|
-
label,
|
|
13
|
-
minLength,
|
|
14
|
-
maxLength,
|
|
15
|
-
hint,
|
|
16
|
-
errorLabel,
|
|
17
|
-
error,
|
|
18
|
-
autoComplete,
|
|
19
|
-
onChange,
|
|
20
|
-
onKeyPress,
|
|
21
|
-
style,
|
|
22
|
-
dataTestId,
|
|
23
|
-
type,
|
|
24
|
-
innerRef,
|
|
25
|
-
number,
|
|
26
|
-
variant,
|
|
27
|
-
parentElement,
|
|
28
|
-
...props
|
|
29
|
-
}) => {
|
|
30
|
-
const ContainerElement = parentElement || "span";
|
|
31
|
-
const numberProps = {
|
|
32
|
-
pattern: "[0-9]*",
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const textInputClass = [
|
|
36
|
-
"qpp-c-text-input",
|
|
37
|
-
variant === "success" && !error && "qpp-c-text-input--success",
|
|
38
|
-
error && "qpp-c-text-input--error",
|
|
39
|
-
size === "big" && "qpp-c-text-input--big",
|
|
40
|
-
className,
|
|
41
|
-
]
|
|
42
|
-
.filter(Boolean)
|
|
43
|
-
.join(" ");
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<ContainerElement className="qppds ds-text-input-container">
|
|
47
|
-
{label && (
|
|
48
|
-
<label className="qpp-u-margin-bottom--8" htmlFor={id}>
|
|
49
|
-
{label}
|
|
50
|
-
</label>
|
|
51
|
-
)}
|
|
52
|
-
<input
|
|
53
|
-
{...(number ? numberProps : {})}
|
|
54
|
-
style={style}
|
|
55
|
-
data-testid={dataTestId}
|
|
56
|
-
type={type}
|
|
57
|
-
className={textInputClass || ""}
|
|
58
|
-
id={id}
|
|
59
|
-
name={name}
|
|
60
|
-
placeholder={placeholder}
|
|
61
|
-
disabled={disabled}
|
|
62
|
-
minLength={minLength}
|
|
63
|
-
maxLength={maxLength}
|
|
64
|
-
required={required}
|
|
65
|
-
autoComplete={autoComplete}
|
|
66
|
-
onChange={onChange}
|
|
67
|
-
onKeyPress={onKeyPress}
|
|
68
|
-
ref={innerRef}
|
|
69
|
-
{...props}
|
|
70
|
-
/>
|
|
71
|
-
{hint && <span className="qpp-hint-message">{hint}</span>}
|
|
72
|
-
{error && (
|
|
73
|
-
<span
|
|
74
|
-
aria-label={errorLabel}
|
|
75
|
-
role="alert"
|
|
76
|
-
className="qpp-error-message"
|
|
77
|
-
>
|
|
78
|
-
{error}
|
|
79
|
-
</span>
|
|
80
|
-
)}
|
|
81
|
-
</ContainerElement>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
TextInput.propTypes = {
|
|
86
|
-
id: PropTypes.string,
|
|
87
|
-
name: PropTypes.string,
|
|
88
|
-
placeholder: PropTypes.string,
|
|
89
|
-
disabled: PropTypes.bool,
|
|
90
|
-
required: PropTypes.bool,
|
|
91
|
-
className: PropTypes.string,
|
|
92
|
-
minLength: PropTypes.string,
|
|
93
|
-
maxLength: PropTypes.string,
|
|
94
|
-
hint: PropTypes.string,
|
|
95
|
-
errorLabel: PropTypes.string,
|
|
96
|
-
error: PropTypes.string,
|
|
97
|
-
autoComplete: PropTypes.string,
|
|
98
|
-
onChange: PropTypes.func,
|
|
99
|
-
onKeyPress: PropTypes.func,
|
|
100
|
-
style: PropTypes.object,
|
|
101
|
-
dataTestId: PropTypes.string,
|
|
102
|
-
type: PropTypes.string,
|
|
103
|
-
innerRef: PropTypes.string,
|
|
104
|
-
number: PropTypes.bool,
|
|
105
|
-
variant: PropTypes.oneOf(["success"]),
|
|
106
|
-
parentElement: PropTypes.string,
|
|
107
|
-
label: PropTypes.string,
|
|
108
|
-
size: PropTypes.oneOf(["big"]),
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
TextInput.defaultProps = {
|
|
112
|
-
id: "",
|
|
113
|
-
name: "",
|
|
114
|
-
placeholder: null,
|
|
115
|
-
disabled: false,
|
|
116
|
-
required: false,
|
|
117
|
-
className: "",
|
|
118
|
-
minLength: "",
|
|
119
|
-
maxLength: "",
|
|
120
|
-
error: null,
|
|
121
|
-
errorLabel: null,
|
|
122
|
-
hint: null,
|
|
123
|
-
autoComplete: "on",
|
|
124
|
-
onChange: () => null,
|
|
125
|
-
onKeyPress: () => null,
|
|
126
|
-
style: null,
|
|
127
|
-
dataTestId: "",
|
|
128
|
-
type: "text",
|
|
129
|
-
innerRef: null,
|
|
130
|
-
number: false,
|
|
131
|
-
variant: null,
|
|
132
|
-
parentElement: "span",
|
|
133
|
-
label: null,
|
|
134
|
-
size: null,
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
export default TextInput;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import React, { cloneElement, useLayoutEffect, useRef } from "react";
|
|
2
|
-
import PropTypes from "prop-types";
|
|
3
|
-
import positionTip, { positionTriangle } from "./position";
|
|
4
|
-
import { useTooltip, TooltipPopup } from "@reach/tooltip";
|
|
5
|
-
import Portal from "@reach/portal";
|
|
6
|
-
|
|
7
|
-
// TODO: investigate ways to allow more styling via css? the triangle
|
|
8
|
-
// positioning effect issue may need to be resolved to allow for this.
|
|
9
|
-
const TEXT_COLOR = "#FFF";
|
|
10
|
-
const BACKGROUND_COLOR = "#333";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Generic styled tooltip component.
|
|
14
|
-
* Corresponding styles: /styles/components/_tooltip.scss
|
|
15
|
-
*
|
|
16
|
-
* Extends implementation from @reach/tooltip:
|
|
17
|
-
* https://reacttraining.com/reach-ui/tooltip
|
|
18
|
-
*/
|
|
19
|
-
const Tooltip = ({ children, label, ariaLabel, DEBUG_STYLE }) => {
|
|
20
|
-
const [trigger, tooltip] = useTooltip({ DEBUG_STYLE });
|
|
21
|
-
const { isVisible, triggerRect } = tooltip;
|
|
22
|
-
const tooltipPopupRef = useRef();
|
|
23
|
-
const triangleRef = useRef();
|
|
24
|
-
|
|
25
|
-
useLayoutEffect(() => {
|
|
26
|
-
// For some reason, the forwardRef for the tooltipPopup points to an undefined
|
|
27
|
-
// dom element when we first render the portal containing the triangle. Using
|
|
28
|
-
// an effect here will ensure that the ref is available when applying styles.
|
|
29
|
-
// TODO: investigate and make issue for @reach-ui/tooltip?
|
|
30
|
-
if (isVisible && tooltipPopupRef.current && triggerRect) {
|
|
31
|
-
const tooltipRect = tooltipPopupRef.current.getBoundingClientRect();
|
|
32
|
-
const positionCssText = positionTriangle(triggerRect, tooltipRect);
|
|
33
|
-
const cssText = `
|
|
34
|
-
position: absolute;
|
|
35
|
-
width: 0;
|
|
36
|
-
height: 0;
|
|
37
|
-
${positionCssText}
|
|
38
|
-
border-top-color: ${BACKGROUND_COLOR};
|
|
39
|
-
border-bottom-color: ${BACKGROUND_COLOR};
|
|
40
|
-
z-index: 1;
|
|
41
|
-
`;
|
|
42
|
-
triangleRef.current.style.cssText = cssText;
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<>
|
|
48
|
-
{cloneElement(children, trigger)}
|
|
49
|
-
<TooltipPopup
|
|
50
|
-
{...tooltip}
|
|
51
|
-
label={label}
|
|
52
|
-
ariaLabel={ariaLabel}
|
|
53
|
-
style={{
|
|
54
|
-
background: BACKGROUND_COLOR,
|
|
55
|
-
color: TEXT_COLOR,
|
|
56
|
-
}}
|
|
57
|
-
ref={tooltipPopupRef}
|
|
58
|
-
position={positionTip}
|
|
59
|
-
/>
|
|
60
|
-
{isVisible && (
|
|
61
|
-
<Portal>
|
|
62
|
-
<div
|
|
63
|
-
ref={triangleRef}
|
|
64
|
-
style={{
|
|
65
|
-
position: "absolute",
|
|
66
|
-
width: 0,
|
|
67
|
-
height: 0,
|
|
68
|
-
}}
|
|
69
|
-
/>
|
|
70
|
-
</Portal>
|
|
71
|
-
)}
|
|
72
|
-
</>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
Tooltip.propTypes = {
|
|
77
|
-
children: PropTypes.node.isRequired,
|
|
78
|
-
label: PropTypes.node.isRequired,
|
|
79
|
-
ariaLabel: PropTypes.string,
|
|
80
|
-
DEBUG_STYLE: PropTypes.bool,
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
Tooltip.defaultProps = {
|
|
84
|
-
ariaLabel: undefined,
|
|
85
|
-
DEBUG_STYLE: undefined,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export default Tooltip;
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import Tooltip from "./index";
|
|
3
|
-
|
|
4
|
-
const offsetDecorator = (storyFn) => (
|
|
5
|
-
<div style={{ margin: "80px" }}>{storyFn()}</div>
|
|
6
|
-
);
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
title: "Tooltip",
|
|
10
|
-
component: Tooltip,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const ExampleTooltip = () => (
|
|
14
|
-
<Tooltip label="FOOBAR">
|
|
15
|
-
<button>
|
|
16
|
-
<span>Tooltip Trigger</span>
|
|
17
|
-
</button>
|
|
18
|
-
</Tooltip>
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
ExampleTooltip.storyName = "example Tooltip";
|
|
22
|
-
ExampleTooltip.decorators = [offsetDecorator];
|
|
23
|
-
|
|
24
|
-
export const AriaLabelTooltip = () => (
|
|
25
|
-
<Tooltip label="FOOBAR" ariaLabel="foobar">
|
|
26
|
-
<button>
|
|
27
|
-
<span>Tooltip Trigger</span>
|
|
28
|
-
</button>
|
|
29
|
-
</Tooltip>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
AriaLabelTooltip.storyName = "using ariaLabel";
|
|
33
|
-
AriaLabelTooltip.decorators = [offsetDecorator];
|
|
34
|
-
|
|
35
|
-
export const MultipleTooltip = () => (
|
|
36
|
-
<>
|
|
37
|
-
<Tooltip label="Tooltip 1">
|
|
38
|
-
<button>
|
|
39
|
-
<span>Tooltip 1 Trigger</span>
|
|
40
|
-
</button>
|
|
41
|
-
</Tooltip>
|
|
42
|
-
<Tooltip label="Tooltip 2">
|
|
43
|
-
<button>
|
|
44
|
-
<span>Tooltip 2 Trigger</span>
|
|
45
|
-
</button>
|
|
46
|
-
</Tooltip>
|
|
47
|
-
<Tooltip label="Tooltip 3">
|
|
48
|
-
<button>
|
|
49
|
-
<span>Tooltip 3 Trigger</span>
|
|
50
|
-
</button>
|
|
51
|
-
</Tooltip>
|
|
52
|
-
</>
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
MultipleTooltip.storyName = "multiple Tooltips";
|
|
56
|
-
MultipleTooltip.decorators = [offsetDecorator];
|
|
57
|
-
|
|
58
|
-
export const InputElementTooltip = () => (
|
|
59
|
-
<form>
|
|
60
|
-
<label htmlFor="foobar" style={{ marginRight: "5px " }}>
|
|
61
|
-
Text Input
|
|
62
|
-
</label>
|
|
63
|
-
<Tooltip label="example input label tooltip">
|
|
64
|
-
<input type="text" name="foobar" />
|
|
65
|
-
</Tooltip>
|
|
66
|
-
</form>
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
InputElementTooltip.storyName = "on text input";
|
|
70
|
-
InputElementTooltip.decorators = [offsetDecorator];
|
|
71
|
-
|
|
72
|
-
export const PositionedBelowTargetTooltip = () => (
|
|
73
|
-
<Tooltip label="FOOBAR">
|
|
74
|
-
<button>
|
|
75
|
-
<span>Tooltip Trigger</span>
|
|
76
|
-
</button>
|
|
77
|
-
</Tooltip>
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
PositionedBelowTargetTooltip.storyName = "positioned below trigger";
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
const OFFSET = 12; // modified from reach-ui/tooltip OFFSET value
|
|
2
|
-
const TRIANGLE_SCALE_X = 6;
|
|
3
|
-
const TRIANGLE_SCALE_Y = 8;
|
|
4
|
-
|
|
5
|
-
const isDirectionUp = (triggerRect, tooltipRect) => {
|
|
6
|
-
const collisions = {
|
|
7
|
-
top: triggerRect.top - tooltipRect.height < 0,
|
|
8
|
-
bottom:
|
|
9
|
-
window.innerHeight <
|
|
10
|
-
triggerRect.bottom + tooltipRect.height + OFFSET,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
return !collisions.top || collisions.bottom;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// modified from @reach/tooltip default positioning function
|
|
17
|
-
// positions Tooltip relative to trigger
|
|
18
|
-
// https://github.com/reach/reach-ui/blob/master/packages/tooltip/src/index.tsx#L532
|
|
19
|
-
const positionTip = (triggerRect, tooltipRect) => {
|
|
20
|
-
if (!triggerRect || !tooltipRect) {
|
|
21
|
-
return {};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const triggerCenter = triggerRect.left + triggerRect.width / 2;
|
|
25
|
-
const left = triggerCenter - tooltipRect.width / 2;
|
|
26
|
-
const maxLeft = window.innerWidth - tooltipRect.width - 2;
|
|
27
|
-
const centerLeft =
|
|
28
|
-
Math.min(Math.max(2, left), maxLeft) + window.pageXOffset;
|
|
29
|
-
|
|
30
|
-
const directionUp = isDirectionUp(triggerRect, tooltipRect);
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
left: `${centerLeft}px`,
|
|
34
|
-
top: directionUp
|
|
35
|
-
? `${
|
|
36
|
-
triggerRect.top -
|
|
37
|
-
OFFSET -
|
|
38
|
-
tooltipRect.height +
|
|
39
|
-
window.pageYOffset
|
|
40
|
-
}px`
|
|
41
|
-
: `${
|
|
42
|
-
triggerRect.top +
|
|
43
|
-
OFFSET +
|
|
44
|
-
triggerRect.height +
|
|
45
|
-
window.pageYOffset
|
|
46
|
-
}px`,
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export default positionTip;
|
|
51
|
-
|
|
52
|
-
// position triangle relative to tooltip position
|
|
53
|
-
// TODO: figure out a better way to render these updates from within react
|
|
54
|
-
// rendering. This method causes an additional repaint after the Tooltip
|
|
55
|
-
// has been rendered. may require changes to @reach/tooltip.
|
|
56
|
-
export const positionTriangle = (triggerRect, tooltipRect) => {
|
|
57
|
-
const directionUp = isDirectionUp(triggerRect, tooltipRect);
|
|
58
|
-
const triangleTop = directionUp
|
|
59
|
-
? triggerRect.top + window.pageYOffset - OFFSET
|
|
60
|
-
: triggerRect.bottom + window.pageYOffset + OFFSET - TRIANGLE_SCALE_Y;
|
|
61
|
-
|
|
62
|
-
const triangleLeft =
|
|
63
|
-
triggerRect.left - TRIANGLE_SCALE_X + triggerRect.width / 2;
|
|
64
|
-
|
|
65
|
-
const triangleBorder = directionUp
|
|
66
|
-
? `border-top: ${TRIANGLE_SCALE_Y}px solid;`
|
|
67
|
-
: `border-bottom: ${TRIANGLE_SCALE_Y}px solid;`;
|
|
68
|
-
|
|
69
|
-
return `
|
|
70
|
-
border-left: ${TRIANGLE_SCALE_X}px solid transparent;
|
|
71
|
-
border-right: ${TRIANGLE_SCALE_X}px solid transparent;
|
|
72
|
-
left: ${triangleLeft}px;
|
|
73
|
-
top: ${triangleTop}px;
|
|
74
|
-
${triangleBorder}
|
|
75
|
-
`;
|
|
76
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { render } from "@testing-library/react";
|
|
3
|
-
import ErrorUI from "../../components/Error/ErrorUI";
|
|
4
|
-
|
|
5
|
-
describe("ErrorUI", () => {
|
|
6
|
-
it("renders a list of errors in HTML", () => {
|
|
7
|
-
const code = "404";
|
|
8
|
-
const type = "Bad thing happened";
|
|
9
|
-
const message = [
|
|
10
|
-
{ contentTitle: "Not found", content: "test" },
|
|
11
|
-
{ contentTitle: "Image not found", content: "test number 2" },
|
|
12
|
-
];
|
|
13
|
-
const { debug, container } = render(
|
|
14
|
-
<ErrorUI type={type} code={code} message={message} />
|
|
15
|
-
);
|
|
16
|
-
expect(container.querySelector(".page-error")).toBeTruthy();
|
|
17
|
-
expect(container.querySelector(".collapsible-details")).toBeTruthy();
|
|
18
|
-
expect(container.querySelectorAll(".items li").length).toBe(2);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("renders a string instead of an array", () => {
|
|
22
|
-
const code = "404";
|
|
23
|
-
const type = "Bad thing happened";
|
|
24
|
-
const message = "Not found";
|
|
25
|
-
const { getByText, container } = render(
|
|
26
|
-
<ErrorUI type={type} code={code} message={message} />
|
|
27
|
-
);
|
|
28
|
-
expect(container.querySelector(".page-error")).toBeTruthy();
|
|
29
|
-
expect(container.querySelector(".collapsible-details")).toBeTruthy();
|
|
30
|
-
expect(getByText(/not found/i)).toBeTruthy();
|
|
31
|
-
});
|
|
32
|
-
});
|