Skip to content

Commit

Permalink
do not allow tooltip to overflow window bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
nreese committed Dec 4, 2017
1 parent bd0e937 commit 851098a
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 8 deletions.
12 changes: 12 additions & 0 deletions src-docs/src/views/tooltip/examples.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import {
TooltipTrigger,
} from '../../../../src/components';

const autoPlacementTooltip = `I should be on the top but may get placed in another location
if I overflow the browser window. This will come in handy when tooltips get placed near the top
of pages. Its very hard to read a tooltip when part of it gets cut off and if you can't read it
then what is the point?`;

export default () => (
<div>
<div>
Expand All @@ -12,6 +17,13 @@ export default () => (
<span className="overlay-trigger" tabIndex="0"> tooltip with title.</span>
</TooltipTrigger>
</div>
<div>
Check out this
<TooltipTrigger
tooltip={autoPlacementTooltip} placement="top" size="s">
<span className="overlay-trigger" tabIndex="0"> tooltip on the top (overflow).</span>
</TooltipTrigger>
</div>
<div>
Check out this
<TooltipTrigger tooltip="I should be on the left" placement="left">
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/tooltip/tooltip_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default props => (
code: examplesHtml,
}]}
demo={
<div style={{ width: 320 }}>
<div>
<TooltipExamples />
</div>
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/tooltip/_tooltip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -268,21 +268,21 @@ $tooltip-lg-width: $base-unit * 45;
}

//Tooltip Sizes
.tooltip-sm.tooltip-container {
.tooltip-s.tooltip-container {
width: $tooltip-sm-width;
.tooltip-content {
white-space: normal;
}
}

.tooltip-md.tooltip-container {
.tooltip-m.tooltip-container {
width: $tooltip-md-width;
.tooltip-content {
white-space: normal;
}
}

.tooltip-lg.tooltip-container {
.tooltip-l.tooltip-container {
width: $tooltip-lg-width;
.tooltip-content {
white-space: normal;
Expand Down
37 changes: 33 additions & 4 deletions src/components/tooltip/tooltip.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classnames from 'classnames';

Expand Down Expand Up @@ -90,12 +91,41 @@ export class TooltipTrigger extends React.Component {
constructor(props) {
super(props);
const openOnLoad = props.trigger === 'manual' ? props.display : false;
this.state = { isVisible: openOnLoad };
this.state = {
isVisible: openOnLoad,
noOverflowPlacement: props.placement
};
this.clickHandler = this.clickHandler.bind(this);
}

hoverHandler(e) {
this.setState({isVisible: e.type === 'mouseenter'});
const domNode = ReactDOM.findDOMNode(this);
const tooltipContainer = domNode.getElementsByClassName('tooltip-container')[0];
const rect = tooltipContainer.getBoundingClientRect();
const vWidth = window.innerWidth;
const vHeight = window.innerHeight;
const windowOverflow = {
top: rect.y - rect.height,
right: vWidth - rect.right,
bottom: vHeight - rect.bottom,
left: rect.left
}
const userPlacement = this.props.placement;
let bestPlacement = userPlacement;
if (windowOverflow[userPlacement] <= 0) {
// requested placement overflows window bounds
// select direction what has the most free space
Object.keys(windowOverflow).forEach((key) => {
if (windowOverflow[key] > windowOverflow[bestPlacement]) {
bestPlacement = key;
}
});
}

this.setState({
isVisible: e.type === 'mouseenter',
noOverflowPlacement: bestPlacement
});
}

clickHandler(e, onClick) {
Expand Down Expand Up @@ -145,7 +175,6 @@ export class TooltipTrigger extends React.Component {
render() {
const {
isSticky,
placement,
title,
tooltip,
trigger,
Expand All @@ -165,7 +194,7 @@ export class TooltipTrigger extends React.Component {

const newClasses = classnames('tooltip', className, {
'tooltip-light': theme === 'light',
[`tooltip-${placement}`]: placement !== 'top'
[`tooltip-${this.state.noOverflowPlacement}`]: this.state.noOverflowPlacement !== 'top'
});
const newProps = {
className: newClasses,
Expand Down

0 comments on commit 851098a

Please sign in to comment.