Skip to content

Commit

Permalink
feat(highlight): Render promoter tooltip (#557)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingze authored Aug 27, 2020
1 parent e1081b0 commit b92f8bb
Show file tree
Hide file tree
Showing 18 changed files with 383 additions and 109 deletions.
2 changes: 2 additions & 0 deletions i18n/en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ ba.annotationsSave = Save
ba.popups.cancel = Cancel
# Prompt message following cursor in region annotations mode
ba.popups.popupCursor.regionPrompt = Draw a box to comment
# Popup message for highlight promoter
ba.popups.popupHighlight.promoter = Highlight and Comment
# Prompt message for empty popup list
ba.popups.popupList.prompt = Mention someone to notify them
# Button label for creating a description, comment, or reply
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@reduxjs/toolkit": "^1.3.5",
"@types/react-redux": "^7.1.7",
"axios": "^0.19.2",
"box-ui-elements": "^12.0.0-beta.77",
"box-ui-elements": "^12.0.0-beta.146",
"classnames": "^2.2.5",
"draft-js": "0.10.5",
"formik": "^2.1.4",
Expand Down
91 changes: 91 additions & 0 deletions src/components/Popups/PopupArrow.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
@mixin ba-PopupArrow($size, $top-bg, $right-bg, $bottom-bg, $left-bg, $border-color) {
// Top-facing arrows
&[data-popper-placement*='bottom'] {
.ba-Popup-arrow {
top: -#{$size - 1};

&::before,
&::after {
transform: rotate(180deg) translateX(50%);
}

&::after {
top: 1px;
border-top-color: $top-bg;
}
}
}

// Right-facing arrows
&[data-popper-placement*='left'] {
.ba-Popup-arrow {
right: 0;

&::before,
&::after {
transform: rotate(-90deg) translateY(-100%);
transform-origin: center top;
}

&::after {
left: -1px;
border-top-color: $right-bg;
}
}
}

// Left-facing arrows
&[data-popper-placement*='right'] {
.ba-Popup-arrow {
left: -#{$size - 1};

&::before,
&::after {
transform: rotate(90deg);
transform-origin: center top;
}

&::after {
left: 1px;
border-top-color: $left-bg;
}
}
}

// Bottom-facing arrows
&[data-popper-placement*='top'] {
.ba-Popup-arrow {
top: auto;
bottom: 0;

&::before,
&::after {
transform: rotate(0) translateX(-50%);
}

&::after {
top: -1px;
border-top-color: $bottom-bg;
}
}
}

.ba-Popup-arrow {
&::before,
&::after {
position: absolute;
display: block;
border-right: $size solid transparent;
border-left: $size solid transparent;
content: '';
}

&::before {
border-top: $size solid $border-color;
}

&::after {
border-top: $size solid;
}
}
}
90 changes: 2 additions & 88 deletions src/components/Popups/PopupBase.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
@import '~box-ui-elements/es/styles/variables';
@import './PopupArrow';

.ba {
$popup-arrow-size: 12px;
$popup-content-bg: $white;
$popup-border-color: $bdl-gray-20;
$popup-footer-bg: $bdl-gray-02;

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

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

Expand All @@ -16,93 +17,6 @@
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
z-index: 0;
}

// Top-facing arrows
&[data-popper-placement*='bottom'] {
.ba-Popup-arrow {
top: -#{$popup-arrow-size - 1};

&::before,
&::after {
transform: rotate(180deg) translateX(50%);
}

&::after {
top: 1px;
}
}
}

// Right-facing arrows
&[data-popper-placement*='left'] {
.ba-Popup-arrow {
right: 0;

&::before,
&::after {
transform: rotate(-90deg) translateY(-100%);
transform-origin: center top;
}

&::after {
left: -1px;
}
}
}

// Left-facing arrows
&[data-popper-placement*='right'] {
.ba-Popup-arrow {
left: -#{$popup-arrow-size - 1};

&::before,
&::after {
transform: rotate(90deg);
transform-origin: center top;
}

&::after {
left: 1px;
}
}
}

// Bottom-facing arrows
&[data-popper-placement*='top'] {
.ba-Popup-arrow {
top: auto;
bottom: 0;

&::before,
&::after {
transform: rotate(0) translateX(-50%);
}

&::after {
top: -1px;
border-top-color: $popup-footer-bg;
}
}
}
}

.ba-Popup-arrow {
&::before,
&::after {
position: absolute;
display: block;
border-right: $popup-arrow-size solid transparent;
border-left: $popup-arrow-size solid transparent;
content: '';
}

&::before {
border-top: $popup-arrow-size solid $popup-border-color;
}

&::after {
border-top: $popup-arrow-size solid $popup-content-bg;
}
}

.ba-Popup-content {
Expand Down
39 changes: 39 additions & 0 deletions src/components/Popups/PopupHighlight.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@import '~box-ui-elements/es/styles/variables';
@import './PopupArrow';

.ba {
$popup-content-bg: $bdl-gray;

.ba-PopupHighlight {
@include ba-PopupArrow(4px, $popup-content-bg, $popup-content-bg, $popup-content-bg, $popup-content-bg, $popup-content-bg);

.ba-Popup-content {
background-color: $popup-content-bg;
border: none;
border-radius: $bdl-border-radius-size;
box-shadow: none;
}
}

.ba-PopupHighlight-button {
@include common-typography;

display: flex;
flex-direction: row;
align-items: center;
padding: 5px 10px;
color: $white;
background: transparent;
border: none;
border-radius: $bdl-border-radius-size;
cursor: pointer;
}

.ba-PopupHighlight-icon {
margin-right: 8px;

path {
fill: $white;
}
}
}
102 changes: 102 additions & 0 deletions src/components/Popups/PopupHighlight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from 'react';
import IconHighlightTextAnnotation from 'box-ui-elements/es/icon/fill/AnnotationsHighlight16';
import noop from 'lodash/noop';
import { FormattedMessage } from 'react-intl';
import messages from './messages';
import PopupBase from './PopupBase';
import { Options } from './Popper';
import { Shape } from '../../@types/model';
import './PopupHighlight.scss';

export type Props = {
onClick?: (event: React.MouseEvent) => void;
shape: Shape;
};

const options: Partial<Options> = {
modifiers: [
{
name: 'arrow',
options: {
element: '.ba-Popup-arrow',
},
},
{
name: 'eventListeners',
options: {
scroll: false,
},
},
{
name: 'offset',
options: {
offset: [0, 8],
},
},
{
name: 'preventOverflow',
options: {
padding: 5,
},
},
],
placement: 'bottom',
};

export default function PopupHighlight({ onClick = noop, shape }: Props): JSX.Element {
const buttonRef = React.useRef<HTMLButtonElement>(null);
const { height, width, x, y } = shape;

const reference = {
getBoundingClientRect: () => ({
bottom: y + height,
height,
left: x,
right: x + width,
top: y,
width,
}),
};

const handleEvent = (event: Event): void => {
event.preventDefault();
event.stopPropagation();
};

const handleClick = (event: React.MouseEvent): void => {
onClick(event);
};

// Prevent events from propagating to upper elements. The upper elements'
// mouse handlers are attached to real dom, so the belows have to attach to real dom too
React.useEffect(() => {
const { current: buttonEl } = buttonRef;

if (buttonEl) {
buttonEl.addEventListener('mousedown', handleEvent);
buttonEl.addEventListener('mouseup', handleEvent);
}

return () => {
if (buttonEl) {
buttonEl.removeEventListener('mousedown', handleEvent);
buttonEl.removeEventListener('mouseup', handleEvent);
}
};
}, [buttonRef]);

return (
<PopupBase className="ba-PopupHighlight" options={options} reference={reference}>
<button
ref={buttonRef}
className="ba-PopupHighlight-button"
data-testid="ba-PopupHighlight-button"
onClick={handleClick}
type="button"
>
<IconHighlightTextAnnotation className="ba-PopupHighlight-icon" />
<FormattedMessage {...messages.popupHighlightPromoter} />
</button>
</PopupBase>
);
}
Loading

0 comments on commit b92f8bb

Please sign in to comment.