From 99d9e736dc7b89e11eaee0cedd6c5ab3fc68c429 Mon Sep 17 00:00:00 2001
From: Aman Sharma <mannu.poski10@gmail.com>
Date: Fri, 19 Jul 2019 02:00:27 +0530
Subject: [PATCH] Toogle position of tooltip vertically

---
 src/Tooltip/index.js | 141 +++++++++++++++++++++++++++++++++----------
 1 file changed, 109 insertions(+), 32 deletions(-)

diff --git a/src/Tooltip/index.js b/src/Tooltip/index.js
index 3e23d3b178..86670fc346 100644
--- a/src/Tooltip/index.js
+++ b/src/Tooltip/index.js
@@ -6,28 +6,98 @@ import glossary from '../Documentation/glossary'
 
 class Tooltip extends Component {
   state = {
+    description: '',
+    header: '',
     hover: false,
-    timeout: null,
-    width: 400,
+    id: null,
     margin: -70,
-    pointMargin: -15
+    pointBorderAfter: 'white transparent transparent transparent',
+    pointBorderBefore: '#d1d5da transparent transparent transparent',
+    pointMargin: -15,
+    pointTop: 100,
+    pointTopAfter: -14,
+    pointTopBefore: 16,
+    timeout: null,
+    top: 'unset',
+    width: 400
   }
 
-  tooltipWidthEval = () => {
+  componentDidMount() {
+    glossary.contents.forEach((glossaryItem, index) => {
+      if (glossaryItem.match.includes(this.props.text)) {
+        this.setState({
+          description: glossaryItem.desc,
+          header: glossaryItem.name,
+          key: index
+        })
+      }
+    })
+  }
+
+  tooltipPositionEval = () => {
     const markdownBody = document.getElementsByClassName('markdown-body')[0]
+    const tooltipBoundary = document
+      .getElementById(`tooltip-text-${this.state.key}`)
+      .getBoundingClientRect()
+    const tooltipBoxHeight = document.getElementById(
+      `tooltip-box-${this.state.key}`
+    ).offsetHeight
+    const tooltipHeight = tooltipBoundary.top - tooltipBoxHeight
     const maxWidth = markdownBody.offsetLeft + markdownBody.clientWidth
     const container = document.getElementsByClassName('tooltip-container')[0]
     const tooltipWidth = container.offsetLeft + this.state.width
-    if (tooltipWidth > maxWidth) {
-      this.setState({
-        margin: -340,
-        pointMargin: 260
-      })
-    } else {
-      this.setState({
-        margin: -70,
-        pointMargin: -15
-      })
+    const vertical = tooltipHeight > 80 ? 'top' : 'bottom'
+    const horizontal = tooltipWidth > maxWidth ? 'right' : 'left'
+
+    switch (`${horizontal} ${vertical}`) {
+      case 'left top':
+        this.setState({
+          margin: -70,
+          pointBorderAfter: 'white transparent transparent transparent',
+          pointBorderBefore: '#d1d5da transparent transparent transparent',
+          pointMargin: -15,
+          pointTop: 100,
+          pointTopAfter: 'unset',
+          pointTopBefore: 'unset',
+          top: -tooltipBoxHeight
+        })
+        break
+      case 'right top':
+        this.setState({
+          margin: -340,
+          pointBorderAfter: 'white transparent transparent transparent',
+          pointBorderBefore: '#d1d5da transparent transparent transparent',
+          pointMargin: 260,
+          pointTop: 100,
+          pointTopAfter: 'unset',
+          pointTopBefore: 'unset',
+          top: -tooltipBoxHeight
+        })
+        break
+      case 'left bottom':
+        this.setState({
+          margin: -70,
+          pointBorderAfter: 'transparent transparent white transparent',
+          pointBorderBefore: 'transparent transparent #d1d5da transparent',
+          pointMargin: -15,
+          pointTop: -15,
+          pointTopAfter: -20,
+          pointTopBefore: -23,
+          top: 40
+        })
+        break
+      case 'right bottom':
+        this.setState({
+          margin: -340,
+          pointBorderAfter: 'transparent transparent white transparent',
+          pointBorderBefore: 'transparent transparent #d1d5da transparent',
+          pointMargin: 260,
+          pointTop: -15,
+          pointTopAfter: -20,
+          pointTopBefore: -23,
+          top: 40
+        })
+        break
     }
   }
 
@@ -39,14 +109,14 @@ class Tooltip extends Component {
           interval: null,
           hover: true
         },
-        this.tooltipWidthEval
+        this.tooltipPositionEval
       )
     } else {
       this.setState(
         {
           hover: true
         },
-        this.tooltipWidthEval
+        this.tooltipPositionEval
       )
     }
   }
@@ -62,22 +132,13 @@ class Tooltip extends Component {
   }
 
   render() {
-    const { text } = this.props
-    let header = ''
-    let description = ''
-    glossary.contents.forEach(glossaryItem => {
-      if (glossaryItem.match.includes(text)) {
-        header = glossaryItem.name
-        description = glossaryItem.desc
-      }
-    })
     return (
       <>
         <HighlightedText
           onMouseOver={this.hoverIn}
           onMouseLeave={this.hoverOut}
         >
-          {text}
+          <span id={`tooltip-text-${this.state.key}`}>{this.props.text}</span>
         </HighlightedText>
         {this.state.hover && (
           <TooltipContainer
@@ -86,12 +147,20 @@ class Tooltip extends Component {
             onMouseLeave={this.hoverOut}
           >
             <TooltipText
+              id={`tooltip-box-${this.state.key}`}
               margin={this.state.margin}
               width={this.state.width}
+              pointBorderAfter={this.state.pointBorderAfter}
+              pointBorderBefore={this.state.pointBorderBefore}
               pointMargin={this.state.pointMargin}
+              pointTop={this.state.pointTop}
+              pointTopBefore={this.state.pointTopBefore}
+              pointTopAfter={this.state.pointTopAfter}
+              top={this.state.top}
+              bottom={this.state.bottom}
             >
-              <div className="header">{header}</div>
-              <ReactMarkdown source={description} />
+              <div className="header">{this.state.header}</div>
+              <ReactMarkdown source={this.state.description} />
             </TooltipText>
           </TooltipContainer>
         )}
@@ -118,7 +187,13 @@ const TooltipText = styled.div`
   background-color: white;
   position: absolute;
   z-index: 1;
-  bottom: 90%;
+  top: ${props => {
+    if (props.top === 'unset') {
+      return 'unset'
+    } else {
+      return `${props.top}px`
+    }
+  }};
   margin-left: ${props => props.margin || -70}px;
   width: ${props => props.width || 400}px;
 
@@ -126,20 +201,22 @@ const TooltipText = styled.div`
   &:before {
     content: '';
     position: absolute;
-    top: 100%;
+    top: ${props => props.pointTop}%;
     border-style: solid;
     margin-left: ${props => props.pointMargin || -15}px;
   }
 
   &:after {
+    top: ${props => props.pointTopAfter}px;
     left: 10%;
     border-width: 10px;
-    border-color: white transparent transparent transparent;
+    border-color: ${props => props.pointBorderAfter};
   }
   &:before {
+    top: ${props => props.pointTopBefore}px;
     left: 10%;
     border-width: 11px;
-    border-color: #d1d5da transparent transparent transparent;
+    border-color: ${props => props.pointBorderBefore};
   }
 
   .header {