@scm-manager/ui-components 2.30.2-20220115-150339 → 2.30.2-20220116-101546
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/package.json +5 -5
- package/src/Help.tsx +3 -2
- package/src/Tooltip.stories.tsx +11 -0
- package/src/Tooltip.tsx +166 -24
- package/src/__snapshots__/storyshots.test.ts.snap +3973 -3353
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scm-manager/ui-components",
|
|
3
|
-
"version": "2.30.2-
|
|
3
|
+
"version": "2.30.2-20220116-101546",
|
|
4
4
|
"description": "UI Components for SCM-Manager and its plugins",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@scm-manager/jest-preset": "^2.13.0",
|
|
26
26
|
"@scm-manager/prettier-config": "^2.10.1",
|
|
27
27
|
"@scm-manager/tsconfig": "^2.12.0",
|
|
28
|
-
"@scm-manager/ui-tests": "^2.30.2-
|
|
28
|
+
"@scm-manager/ui-tests": "^2.30.2-20220116-101546",
|
|
29
29
|
"@storybook/addon-actions": "^6.3.12",
|
|
30
30
|
"@storybook/addon-storyshots": "^6.3.12",
|
|
31
31
|
"@storybook/builder-webpack5": "^6.3.12",
|
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@headlessui/react": "^1.4.3",
|
|
69
|
-
"@scm-manager/ui-api": "^2.30.2-
|
|
70
|
-
"@scm-manager/ui-extensions": "^2.30.2-
|
|
71
|
-
"@scm-manager/ui-types": "^2.30.2-
|
|
69
|
+
"@scm-manager/ui-api": "^2.30.2-20220116-101546",
|
|
70
|
+
"@scm-manager/ui-extensions": "^2.30.2-20220116-101546",
|
|
71
|
+
"@scm-manager/ui-types": "^2.30.2-20220116-101546",
|
|
72
72
|
"classnames": "^2.2.6",
|
|
73
73
|
"date-fns": "^2.4.1",
|
|
74
74
|
"deepmerge": "^4.2.2",
|
package/src/Help.tsx
CHANGED
|
@@ -40,16 +40,17 @@ const AbsolutePositionTooltip = styled(Tooltip)`
|
|
|
40
40
|
|
|
41
41
|
const Help: FC<Props> = ({ message, multiline, className, id }) => (
|
|
42
42
|
<AbsolutePositionTooltip
|
|
43
|
-
className={classNames("is-inline-block", "pl-1",
|
|
43
|
+
className={classNames("is-inline-block", "pl-1", className)}
|
|
44
44
|
message={message}
|
|
45
45
|
id={id}
|
|
46
|
+
multiline={multiline}
|
|
46
47
|
>
|
|
47
48
|
<HelpIcon />
|
|
48
49
|
</AbsolutePositionTooltip>
|
|
49
50
|
);
|
|
50
51
|
|
|
51
52
|
Help.defaultProps = {
|
|
52
|
-
multiline: true
|
|
53
|
+
multiline: true
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
export default Help;
|
package/src/Tooltip.stories.tsx
CHANGED
|
@@ -94,4 +94,15 @@ storiesOf("Tooltip", module)
|
|
|
94
94
|
</Spacing>
|
|
95
95
|
))}
|
|
96
96
|
</Wrapper>
|
|
97
|
+
))
|
|
98
|
+
.add("Styled", () => (
|
|
99
|
+
<Wrapper>
|
|
100
|
+
{positions.map((position) => (
|
|
101
|
+
<Spacing>
|
|
102
|
+
<Tooltip message={message} location={position} className={"has-text-warning"}>
|
|
103
|
+
<Button label={position} color="info" />{" "}
|
|
104
|
+
</Tooltip>
|
|
105
|
+
</Spacing>
|
|
106
|
+
))}
|
|
107
|
+
</Wrapper>
|
|
97
108
|
));
|
package/src/Tooltip.tsx
CHANGED
|
@@ -21,12 +21,128 @@
|
|
|
21
21
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
|
-
import React, { ReactNode } from "react";
|
|
24
|
+
import React, { FC, ReactNode, useEffect, useState } from "react";
|
|
25
|
+
import styled from "styled-components";
|
|
26
|
+
import classNames from "classnames";
|
|
27
|
+
|
|
28
|
+
// See for css reference: https://github.com/Wikiki/bulma-tooltip/blob/master/src/sass/index.sass
|
|
29
|
+
|
|
30
|
+
const TooltipWrapper = styled.div`
|
|
31
|
+
position: relative;
|
|
32
|
+
display: inline-block;
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const ArrowBase = styled.span`
|
|
36
|
+
z-index: 1020;
|
|
37
|
+
position: absolute;
|
|
38
|
+
width: 0;
|
|
39
|
+
height: 0;
|
|
40
|
+
border-style: solid;
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const ArrowTop = styled(ArrowBase)`
|
|
44
|
+
top: 0;
|
|
45
|
+
right: auto;
|
|
46
|
+
bottom: auto;
|
|
47
|
+
left: 50%;
|
|
48
|
+
margin-top: -5px;
|
|
49
|
+
margin-right: auto;
|
|
50
|
+
margin-bottom: auto;
|
|
51
|
+
margin-left: -5px;
|
|
52
|
+
border-width: 5px 5px 0 5px;
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
const ArrowRight = styled(ArrowBase)`
|
|
56
|
+
top: auto;
|
|
57
|
+
right: 0;
|
|
58
|
+
bottom: 50%;
|
|
59
|
+
left: auto;
|
|
60
|
+
margin-top: auto;
|
|
61
|
+
margin-right: -5px;
|
|
62
|
+
margin-bottom: -5px;
|
|
63
|
+
margin-left: auto;
|
|
64
|
+
border-width: 5px 5px 5px 0;
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
const ArrowLeft = styled(ArrowBase)`
|
|
68
|
+
top: auto;
|
|
69
|
+
right: auto;
|
|
70
|
+
bottom: 50%;
|
|
71
|
+
left: 0;
|
|
72
|
+
margin-top: auto;
|
|
73
|
+
margin-right: auto;
|
|
74
|
+
margin-bottom: -5px;
|
|
75
|
+
margin-left: -5px;
|
|
76
|
+
border-width: 5px 0 5px 5px;
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const ArrowBottom = styled(ArrowBase)`
|
|
80
|
+
top: auto;
|
|
81
|
+
right: auto;
|
|
82
|
+
bottom: 0;
|
|
83
|
+
left: 50%;
|
|
84
|
+
margin-top: auto;
|
|
85
|
+
margin-right: auto;
|
|
86
|
+
margin-bottom: -5px;
|
|
87
|
+
margin-left: -5px;
|
|
88
|
+
border-width: 0 5px 5px 5px;
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
const Arrow = {
|
|
92
|
+
bottom: ArrowBottom,
|
|
93
|
+
left: ArrowLeft,
|
|
94
|
+
right: ArrowRight,
|
|
95
|
+
top: ArrowTop
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const TooltipContainerBase = styled.div<{ multiline?: boolean }>`
|
|
99
|
+
z-index: 1020;
|
|
100
|
+
position: absolute;
|
|
101
|
+
padding: 0.5rem 1rem;
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
hyphens: auto;
|
|
104
|
+
text-overflow: ${({ multiline }) => (multiline ? "clip" : "ellipsis")};
|
|
105
|
+
white-space: ${({ multiline }) => (multiline ? "normal" : "pre")};
|
|
106
|
+
max-width: ${({ multiline }) => (multiline ? "15rem" : "auto")};
|
|
107
|
+
width: ${({ multiline }) => (multiline ? "15rem" : "auto")};
|
|
108
|
+
word-break: ${({ multiline }) => (multiline ? "keep-all" : "unset")};
|
|
109
|
+
`;
|
|
110
|
+
|
|
111
|
+
const TooltipContainerTop = styled(TooltipContainerBase)`
|
|
112
|
+
left: 50%;
|
|
113
|
+
bottom: calc(100% + 5px);
|
|
114
|
+
transform: translateX(-50%);
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
const TooltipContainerBottom = styled(TooltipContainerBase)`
|
|
118
|
+
left: 50%;
|
|
119
|
+
top: calc(100% + 5px);
|
|
120
|
+
transform: translateX(-50%);
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
const TooltipContainerLeft = styled(TooltipContainerBase)`
|
|
124
|
+
right: calc(100% + 5px);
|
|
125
|
+
top: 50%;
|
|
126
|
+
transform: translateY(-50%);
|
|
127
|
+
`;
|
|
128
|
+
|
|
129
|
+
const TooltipContainerRight = styled(TooltipContainerBase)`
|
|
130
|
+
left: calc(100% + 5px);
|
|
131
|
+
top: 50%;
|
|
132
|
+
transform: translateY(-50%);
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
const Container = {
|
|
136
|
+
bottom: TooltipContainerBottom,
|
|
137
|
+
left: TooltipContainerLeft,
|
|
138
|
+
right: TooltipContainerRight,
|
|
139
|
+
top: TooltipContainerTop
|
|
140
|
+
};
|
|
25
141
|
|
|
26
142
|
type Props = {
|
|
27
143
|
message: string;
|
|
28
144
|
className?: string;
|
|
29
|
-
location
|
|
145
|
+
location?: TooltipLocation;
|
|
30
146
|
multiline?: boolean;
|
|
31
147
|
children: ReactNode;
|
|
32
148
|
id?: string;
|
|
@@ -34,27 +150,53 @@ type Props = {
|
|
|
34
150
|
|
|
35
151
|
export type TooltipLocation = "bottom" | "right" | "top" | "left";
|
|
36
152
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
153
|
+
const Tooltip: FC<Props> = ({ className, message, location = "right", multiline, children, id }) => {
|
|
154
|
+
const [open, setOpen] = useState(false);
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
const listener = (event: KeyboardEvent) => {
|
|
158
|
+
if (event.key === "Escape") {
|
|
159
|
+
setOpen(false);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
window.addEventListener("keydown", listener);
|
|
163
|
+
return () => window.removeEventListener("keydown", listener);
|
|
164
|
+
}, []);
|
|
165
|
+
|
|
166
|
+
const LocationContainer = Container[location];
|
|
167
|
+
const LocationArrow = Arrow[location];
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<TooltipWrapper
|
|
171
|
+
onMouseEnter={() => setOpen(true)}
|
|
172
|
+
onMouseLeave={() => setOpen(false)}
|
|
173
|
+
onClick={() => setOpen(false)}
|
|
174
|
+
>
|
|
175
|
+
{open ? (
|
|
176
|
+
<>
|
|
177
|
+
<LocationArrow className={`tooltip-arrow-${location}-border-color`} />
|
|
178
|
+
<LocationContainer
|
|
179
|
+
className={classNames(
|
|
180
|
+
"is-size-7",
|
|
181
|
+
"is-family-primary",
|
|
182
|
+
"has-rounded-border",
|
|
183
|
+
"has-text-white",
|
|
184
|
+
"has-background-grey-dark",
|
|
185
|
+
"has-text-weight-semibold",
|
|
186
|
+
className
|
|
187
|
+
)}
|
|
188
|
+
multiline={multiline}
|
|
189
|
+
aria-live="polite"
|
|
190
|
+
id={id}
|
|
191
|
+
role="tooltip"
|
|
192
|
+
>
|
|
193
|
+
{message}
|
|
194
|
+
</LocationContainer>
|
|
195
|
+
</>
|
|
196
|
+
) : null}
|
|
197
|
+
{children}
|
|
198
|
+
</TooltipWrapper>
|
|
199
|
+
);
|
|
200
|
+
};
|
|
59
201
|
|
|
60
202
|
export default Tooltip;
|