Skip to content

Commit

Permalink
New popover positioning service + updated EuiToolTip (#924)
Browse files Browse the repository at this point in the history
* Initial popover service logic, mostly tested

* tested and corrected the popup placement algorithm

* Fix cross-axis positioning, update EuiToolTip to use new positioning service

* tweaks for & after browser testing

* jsdoc tweak/fix

* changelog

* Find best fit for popover content instead of forcing 100% fit

* Dynamically positioned arrows

* added comments to code

* Reducing size of tooltip arrow

* Group related variables in getPopoverScreenCoordinates into discrete steps:
1) Find original cross-axis position.
2) Apply shift to cross-axis position, if necessary.
3) Find primary axis position.

* Fix positionSubstitues typo.

* Split getPopoverScreenCoordinates into getCrossAxisPosition and getPrimaryAxisPosition helper functions.

* Define iterationPositions first, and then traverse them.

* Format comments and parameters to wrap.

* Remove unnecessary minimumSpace parameter.

* Update popover tests in response to PR feedback
  • Loading branch information
chandlerprall authored Jun 19, 2018
1 parent bfc240d commit 4e8b1eb
Show file tree
Hide file tree
Showing 10 changed files with 1,002 additions and 29 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## [`master`](https://github.com/elastic/eui/tree/master)

No public interface changes since `0.0.54`.
- Added `getPopoverScreenCoordinates` service function for positioining popover/tooltip content, updated `EuiToolTip` to use it ([#924](https://github.com/elastic/eui/pull/924))

## [`0.0.54`](https://github.com/elastic/eui/tree/v0.0.54)

Expand Down
2 changes: 1 addition & 1 deletion src-docs/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ module.exports = {

devServer: {
contentBase: 'src-docs/build',
host: 'localhost',
host: '0.0.0.0',
port: 8030,
disableHostCheck: true
}
Expand Down
39 changes: 21 additions & 18 deletions src/components/tool_tip/_tool_tip.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*
* 1. Shift arrow 1px more than half it's size to account for border radius
*/

.euiToolTip {
@include euiBottomShadow;
@include euiFontSizeS();
Expand All @@ -12,46 +16,45 @@
animation: euiToolTipTop $euiAnimSpeedSlow ease-out $euiAnimSpeedNormal forwards;
z-index: $euiZLevel9;

&::before {
// Custom sizing
$arrowSize: $euiSizeM;
$arrowPlusSize: (($arrowSize/2) + 1px) * -1; /* 1 */
$arrowMinusSize: (($arrowSize/2) - 1px) * -1; /* 1 */

.euiToolTip__arrow {
content: "";
position: absolute;
bottom: -$euiSize/2;
left: 50%;
transform: translateX(-50%) rotateZ(45deg);
transform-origin: center;
border-radius: 2px;
background-color: tintOrShade($euiColorFullShade, 25%, 90%);
width: $euiSize;
height: $euiSize;
width: $arrowSize;
height: $arrowSize;

transform: translateY($arrowPlusSize) rotateZ(45deg); /* 1 */
}

// Positions the arrow and animates in from the same side.
&.euiToolTip--right {
animation-name: euiToolTipRight;

&:before {
bottom: 50%;
left: -$euiSize/2;
transform: translateY(50%) rotateZ(45deg);
.euiToolTip__arrow {
transform: translateX($arrowMinusSize) rotateZ(45deg); /* 1 */
}
}

&.euiToolTip--bottom {
animation-name: euiToolTipBottom;

&:before {
bottom: auto;
top: -$euiSize/2;
.euiToolTip__arrow {
transform: translateY($arrowMinusSize) rotateZ(45deg); /* 1 */
}
}

&.euiToolTip--left {
animation-name: euiToolTipLeft;

&:before {
bottom: 50%;
left: auto;
right: -$euiSize/2;
transform: translateY(50%) rotateZ(45deg);
.euiToolTip__arrow {
transform: translateX($arrowPlusSize) rotateZ(45deg); /* 1 */
}
}

Expand Down
34 changes: 26 additions & 8 deletions src/components/tool_tip/tool_tip.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import classNames from 'classnames';

import { EuiPortal } from '../portal';
import { EuiToolTipPopover } from './tool_tip_popover';
import { calculatePopoverPosition } from '../../services';
import { findPopoverPosition } from '../../services';

import makeId from '../form/form_row/make_id';

Expand All @@ -30,29 +30,43 @@ export class EuiToolTip extends Component {
hasFocus: false,
calculatedPosition: this.props.position,
toolTipStyles: {},
arrowStyles: {},
id: this.props.id || makeId(),
};
}

setPopoverRef = ref => {
this.popover = ref;
}

showToolTip = () => {
this.setState({ visible: true });
};

positionToolTip = (toolTipBounds) => {
const anchorBounds = this.anchor.getBoundingClientRect();
positionToolTip = () => {
const requestedPosition = this.props.position;

const { position, left, top } = calculatePopoverPosition(anchorBounds, toolTipBounds, requestedPosition);
const { position, left, top, arrow } = findPopoverPosition({
anchor: this.anchor,
popover: this.popover,
position: requestedPosition,
offset: 16, // offset popover 16px from the anchor
arrowConfig: {
arrowWidth: 14,
arrowBuffer: 4
}
});

const toolTipStyles = {
top: top + window.scrollY,
top,
left,
};

this.setState({
visible: true,
calculatedPosition: position,
toolTipStyles,
arrowStyles: arrow,
});
};

Expand Down Expand Up @@ -94,6 +108,8 @@ export class EuiToolTip extends Component {
...rest
} = this.props;

const { arrowStyles, id, toolTipStyles, visible } = this.state;

const classes = classNames(
'euiToolTip',
positionsToClassNameMap[this.state.calculatedPosition],
Expand All @@ -106,18 +122,20 @@ export class EuiToolTip extends Component {
);

let tooltip;
if (this.state.visible) {
if (visible) {
tooltip = (
<EuiPortal>
<EuiToolTipPopover
className={classes}
style={this.state.toolTipStyles}
style={toolTipStyles}
positionToolTip={this.positionToolTip}
popoverRef={this.setPopoverRef}
title={title}
id={this.state.id}
id={id}
role="tooltip"
{...rest}
>
<div style={arrowStyles} className="euiToolTip__arrow"/>
{content}
</EuiToolTipPopover>
</EuiPortal>
Expand Down
11 changes: 10 additions & 1 deletion src/components/tool_tip/tool_tip_popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class EuiToolTipPopover extends Component {
className: PropTypes.string,
title: PropTypes.node,
positionToolTip: PropTypes.func.isRequired,
popoverRef: PropTypes.func,
}

updateDimensions = () => {
Expand All @@ -21,6 +22,13 @@ export class EuiToolTipPopover extends Component {
});
};

setPopoverRef = ref => {
this.popover = ref;
if (this.props.popoverRef) {
this.props.popoverRef(ref);
}
}

componentDidMount() {
document.body.classList.add('euiBody-hasPortalContent');

Expand All @@ -39,6 +47,7 @@ export class EuiToolTipPopover extends Component {
title,
className,
positionToolTip, // eslint-disable-line no-unused-vars
popoverRef, // eslint-disable-line no-unused-vars
...rest
} = this.props;

Expand All @@ -57,7 +66,7 @@ export class EuiToolTipPopover extends Component {
return (
<div
className={classes}
ref={popover => this.popover = popover}
ref={this.setPopoverRef}
{...rest}
>
{optionalTitle}
Expand Down
1 change: 1 addition & 0 deletions src/services/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,5 @@ export {

export {
calculatePopoverPosition,
findPopoverPosition,
} from './popover';
25 changes: 25 additions & 0 deletions src/services/popover/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { EuiPopoverPosition } from "@elastic/eui";

declare module '@elastic/eui' {
type EuiToolTipPosition = 'top' | 'right' | 'bottom' | 'left';

Expand Down Expand Up @@ -26,4 +28,27 @@ declare module '@elastic/eui' {
height: number;
position: EuiToolTipPosition;
};

type EuiPopoverPosition =
'topLeft' | 'topCenter' | 'topRight' |
'rightTop' | 'rightCenter' | 'rightBottom' |
'bottomLeft' | 'bottomCenter' | 'bottomRight' |
'leftTop' | 'leftCenter' | 'leftBottom';

type FindPopoverPositionArgs = {
anchor: HTMLElement | JSX.Element,
popover: HTMLElement | JSX.Element,
position: string,
buffer?: number,
offset?: number,
container?: HTMLElement
}
export const findPopoverPosition: (
args: FindPopoverPositionArgs
) => {
position: EuiToolTipPosition,
relativePosition: EuiPopoverPosition,
top: number,
left: number
};
}
1 change: 1 addition & 0 deletions src/services/popover/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { calculatePopoverPosition } from './calculate_popover_position';
export { findPopoverPosition } from './popover_positioning';
Loading

0 comments on commit 4e8b1eb

Please sign in to comment.