Skip to content

Commit b92f8bb

Browse files
author
Mingze
authored
feat(highlight): Render promoter tooltip (#557)
1 parent e1081b0 commit b92f8bb

File tree

18 files changed

+383
-109
lines changed

18 files changed

+383
-109
lines changed

i18n/en-US.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ ba.annotationsSave = Save
1212
ba.popups.cancel = Cancel
1313
# Prompt message following cursor in region annotations mode
1414
ba.popups.popupCursor.regionPrompt = Draw a box to comment
15+
# Popup message for highlight promoter
16+
ba.popups.popupHighlight.promoter = Highlight and Comment
1517
# Prompt message for empty popup list
1618
ba.popups.popupList.prompt = Mention someone to notify them
1719
# Button label for creating a description, comment, or reply

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"@reduxjs/toolkit": "^1.3.5",
2323
"@types/react-redux": "^7.1.7",
2424
"axios": "^0.19.2",
25-
"box-ui-elements": "^12.0.0-beta.77",
25+
"box-ui-elements": "^12.0.0-beta.146",
2626
"classnames": "^2.2.5",
2727
"draft-js": "0.10.5",
2828
"formik": "^2.1.4",
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
@mixin ba-PopupArrow($size, $top-bg, $right-bg, $bottom-bg, $left-bg, $border-color) {
2+
// Top-facing arrows
3+
&[data-popper-placement*='bottom'] {
4+
.ba-Popup-arrow {
5+
top: -#{$size - 1};
6+
7+
&::before,
8+
&::after {
9+
transform: rotate(180deg) translateX(50%);
10+
}
11+
12+
&::after {
13+
top: 1px;
14+
border-top-color: $top-bg;
15+
}
16+
}
17+
}
18+
19+
// Right-facing arrows
20+
&[data-popper-placement*='left'] {
21+
.ba-Popup-arrow {
22+
right: 0;
23+
24+
&::before,
25+
&::after {
26+
transform: rotate(-90deg) translateY(-100%);
27+
transform-origin: center top;
28+
}
29+
30+
&::after {
31+
left: -1px;
32+
border-top-color: $right-bg;
33+
}
34+
}
35+
}
36+
37+
// Left-facing arrows
38+
&[data-popper-placement*='right'] {
39+
.ba-Popup-arrow {
40+
left: -#{$size - 1};
41+
42+
&::before,
43+
&::after {
44+
transform: rotate(90deg);
45+
transform-origin: center top;
46+
}
47+
48+
&::after {
49+
left: 1px;
50+
border-top-color: $left-bg;
51+
}
52+
}
53+
}
54+
55+
// Bottom-facing arrows
56+
&[data-popper-placement*='top'] {
57+
.ba-Popup-arrow {
58+
top: auto;
59+
bottom: 0;
60+
61+
&::before,
62+
&::after {
63+
transform: rotate(0) translateX(-50%);
64+
}
65+
66+
&::after {
67+
top: -1px;
68+
border-top-color: $bottom-bg;
69+
}
70+
}
71+
}
72+
73+
.ba-Popup-arrow {
74+
&::before,
75+
&::after {
76+
position: absolute;
77+
display: block;
78+
border-right: $size solid transparent;
79+
border-left: $size solid transparent;
80+
content: '';
81+
}
82+
83+
&::before {
84+
border-top: $size solid $border-color;
85+
}
86+
87+
&::after {
88+
border-top: $size solid;
89+
}
90+
}
91+
}

src/components/Popups/PopupBase.scss

Lines changed: 2 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
@import '~box-ui-elements/es/styles/variables';
2+
@import './PopupArrow';
23

34
.ba {
4-
$popup-arrow-size: 12px;
55
$popup-content-bg: $white;
66
$popup-border-color: $bdl-gray-20;
77
$popup-footer-bg: $bdl-gray-02;
88

99
.ba-Popup {
1010
@include common-typography;
11+
@include ba-PopupArrow(12px, $popup-content-bg, $popup-content-bg, $popup-footer-bg, $popup-content-bg, $popup-border-color);
1112

1213
z-index: 1; // Make sure popup is showing above Preview controls and left/right arrows
1314

@@ -16,93 +17,6 @@
1617
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
1718
z-index: 0;
1819
}
19-
20-
// Top-facing arrows
21-
&[data-popper-placement*='bottom'] {
22-
.ba-Popup-arrow {
23-
top: -#{$popup-arrow-size - 1};
24-
25-
&::before,
26-
&::after {
27-
transform: rotate(180deg) translateX(50%);
28-
}
29-
30-
&::after {
31-
top: 1px;
32-
}
33-
}
34-
}
35-
36-
// Right-facing arrows
37-
&[data-popper-placement*='left'] {
38-
.ba-Popup-arrow {
39-
right: 0;
40-
41-
&::before,
42-
&::after {
43-
transform: rotate(-90deg) translateY(-100%);
44-
transform-origin: center top;
45-
}
46-
47-
&::after {
48-
left: -1px;
49-
}
50-
}
51-
}
52-
53-
// Left-facing arrows
54-
&[data-popper-placement*='right'] {
55-
.ba-Popup-arrow {
56-
left: -#{$popup-arrow-size - 1};
57-
58-
&::before,
59-
&::after {
60-
transform: rotate(90deg);
61-
transform-origin: center top;
62-
}
63-
64-
&::after {
65-
left: 1px;
66-
}
67-
}
68-
}
69-
70-
// Bottom-facing arrows
71-
&[data-popper-placement*='top'] {
72-
.ba-Popup-arrow {
73-
top: auto;
74-
bottom: 0;
75-
76-
&::before,
77-
&::after {
78-
transform: rotate(0) translateX(-50%);
79-
}
80-
81-
&::after {
82-
top: -1px;
83-
border-top-color: $popup-footer-bg;
84-
}
85-
}
86-
}
87-
}
88-
89-
.ba-Popup-arrow {
90-
&::before,
91-
&::after {
92-
position: absolute;
93-
display: block;
94-
border-right: $popup-arrow-size solid transparent;
95-
border-left: $popup-arrow-size solid transparent;
96-
content: '';
97-
}
98-
99-
&::before {
100-
border-top: $popup-arrow-size solid $popup-border-color;
101-
}
102-
103-
&::after {
104-
border-top: $popup-arrow-size solid $popup-content-bg;
105-
}
10620
}
10721

10822
.ba-Popup-content {
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@import '~box-ui-elements/es/styles/variables';
2+
@import './PopupArrow';
3+
4+
.ba {
5+
$popup-content-bg: $bdl-gray;
6+
7+
.ba-PopupHighlight {
8+
@include ba-PopupArrow(4px, $popup-content-bg, $popup-content-bg, $popup-content-bg, $popup-content-bg, $popup-content-bg);
9+
10+
.ba-Popup-content {
11+
background-color: $popup-content-bg;
12+
border: none;
13+
border-radius: $bdl-border-radius-size;
14+
box-shadow: none;
15+
}
16+
}
17+
18+
.ba-PopupHighlight-button {
19+
@include common-typography;
20+
21+
display: flex;
22+
flex-direction: row;
23+
align-items: center;
24+
padding: 5px 10px;
25+
color: $white;
26+
background: transparent;
27+
border: none;
28+
border-radius: $bdl-border-radius-size;
29+
cursor: pointer;
30+
}
31+
32+
.ba-PopupHighlight-icon {
33+
margin-right: 8px;
34+
35+
path {
36+
fill: $white;
37+
}
38+
}
39+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import React from 'react';
2+
import IconHighlightTextAnnotation from 'box-ui-elements/es/icon/fill/AnnotationsHighlight16';
3+
import noop from 'lodash/noop';
4+
import { FormattedMessage } from 'react-intl';
5+
import messages from './messages';
6+
import PopupBase from './PopupBase';
7+
import { Options } from './Popper';
8+
import { Shape } from '../../@types/model';
9+
import './PopupHighlight.scss';
10+
11+
export type Props = {
12+
onClick?: (event: React.MouseEvent) => void;
13+
shape: Shape;
14+
};
15+
16+
const options: Partial<Options> = {
17+
modifiers: [
18+
{
19+
name: 'arrow',
20+
options: {
21+
element: '.ba-Popup-arrow',
22+
},
23+
},
24+
{
25+
name: 'eventListeners',
26+
options: {
27+
scroll: false,
28+
},
29+
},
30+
{
31+
name: 'offset',
32+
options: {
33+
offset: [0, 8],
34+
},
35+
},
36+
{
37+
name: 'preventOverflow',
38+
options: {
39+
padding: 5,
40+
},
41+
},
42+
],
43+
placement: 'bottom',
44+
};
45+
46+
export default function PopupHighlight({ onClick = noop, shape }: Props): JSX.Element {
47+
const buttonRef = React.useRef<HTMLButtonElement>(null);
48+
const { height, width, x, y } = shape;
49+
50+
const reference = {
51+
getBoundingClientRect: () => ({
52+
bottom: y + height,
53+
height,
54+
left: x,
55+
right: x + width,
56+
top: y,
57+
width,
58+
}),
59+
};
60+
61+
const handleEvent = (event: Event): void => {
62+
event.preventDefault();
63+
event.stopPropagation();
64+
};
65+
66+
const handleClick = (event: React.MouseEvent): void => {
67+
onClick(event);
68+
};
69+
70+
// Prevent events from propagating to upper elements. The upper elements'
71+
// mouse handlers are attached to real dom, so the belows have to attach to real dom too
72+
React.useEffect(() => {
73+
const { current: buttonEl } = buttonRef;
74+
75+
if (buttonEl) {
76+
buttonEl.addEventListener('mousedown', handleEvent);
77+
buttonEl.addEventListener('mouseup', handleEvent);
78+
}
79+
80+
return () => {
81+
if (buttonEl) {
82+
buttonEl.removeEventListener('mousedown', handleEvent);
83+
buttonEl.removeEventListener('mouseup', handleEvent);
84+
}
85+
};
86+
}, [buttonRef]);
87+
88+
return (
89+
<PopupBase className="ba-PopupHighlight" options={options} reference={reference}>
90+
<button
91+
ref={buttonRef}
92+
className="ba-PopupHighlight-button"
93+
data-testid="ba-PopupHighlight-button"
94+
onClick={handleClick}
95+
type="button"
96+
>
97+
<IconHighlightTextAnnotation className="ba-PopupHighlight-icon" />
98+
<FormattedMessage {...messages.popupHighlightPromoter} />
99+
</button>
100+
</PopupBase>
101+
);
102+
}

0 commit comments

Comments
 (0)