From b78f5990f67b46e8c4aa8ed490363ea40380461a Mon Sep 17 00:00:00 2001
From: Cory LaViska <cory@abeautifulsite.net>
Date: Tue, 25 Aug 2020 18:01:23 -0400
Subject: [PATCH] Use positioner for tooltip

---
 CHANGELOG.md                        |  1 +
 src/components/tooltip/tooltip.scss | 42 ++++++++++++++++-------------
 src/components/tooltip/tooltip.tsx  | 34 ++++++++++++-----------
 3 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ce0948e6..b62a85a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
 - Add `sl-format-bytes` utility component
 - Add `clearable` and `required` props to `sl-select`
 - Add `slClear` event to `sl-input`
+- Refactored `sl-dropdown` and `sl-tooltip` to use positioner elements so panels/tooltips can be customized easier
 - Fix incorrect `aria-selected` state in `sl-menu-item`
 
 ## 2.0.0-beta.15
diff --git a/src/components/tooltip/tooltip.scss b/src/components/tooltip/tooltip.scss
index 85a36a31..60010fbe 100644
--- a/src/components/tooltip/tooltip.scss
+++ b/src/components/tooltip/tooltip.scss
@@ -21,10 +21,13 @@
   display: contents;
 }
 
-.tooltip {
+.tooltip-positioner {
   position: absolute;
-  max-width: var(--max-width);
   z-index: var(--sl-z-index-tooltip);
+}
+
+.tooltip {
+  max-width: var(--max-width);
   border-radius: var(--sl-tooltip-border-radius);
   background-color: var(--sl-tooltip-background-color);
   font-family: var(--sl-tooltip-font-family);
@@ -33,7 +36,9 @@
   line-height: var(--sl-tooltip-line-height);
   color: var(--sl-tooltip-color);
   opacity: 0;
-  transition: var(--sl-transition-fast) opacity;
+  transform: scale(0.9);
+  transform-origin: bottom;
+  transition: var(--sl-transition-fast) opacity, var(--sl-transition-fast) transform;
   padding: var(--sl-tooltip-padding);
   pointer-events: none;
 
@@ -43,14 +48,15 @@
     width: 0;
     height: 0;
   }
+}
 
-  &.popover-visible {
-    opacity: 1;
-  }
+.popover-visible .tooltip {
+  opacity: 1;
+  transform: scale(1);
 }
 
 // Arrow + bottom
-.tooltip[data-popper-placement^='bottom']::after {
+.tooltip-positioner[data-popper-placement^='bottom'] .tooltip::after {
   bottom: 100%;
   left: calc(50% - var(--sl-tooltip-arrow-size));
   border-bottom: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color);
@@ -58,17 +64,17 @@
   border-right: var(--sl-tooltip-arrow-size) solid transparent;
 }
 
-.tooltip[data-popper-placement='bottom-start']::after {
+.tooltip-positioner[data-popper-placement='bottom-start'] .tooltip::after {
   left: var(--sl-tooltip-arrow-start-end-offset);
 }
 
-.tooltip[data-popper-placement='bottom-end']::after {
+.tooltip-positioner[data-popper-placement='bottom-end'] .tooltip::after {
   right: var(--sl-tooltip-arrow-start-end-offset);
   left: auto;
 }
 
 // Arrow + top
-.tooltip[data-popper-placement^='top']::after {
+.tooltip-positioner[data-popper-placement^='top'] .tooltip::after {
   top: 100%;
   left: calc(50% - var(--sl-tooltip-arrow-size));
   border-top: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color);
@@ -76,17 +82,17 @@
   border-right: var(--sl-tooltip-arrow-size) solid transparent;
 }
 
-.tooltip[data-popper-placement='top-start']::after {
+.tooltip-positioner[data-popper-placement='top-start'] .tooltip::after {
   left: var(--sl-tooltip-arrow-start-end-offset);
 }
 
-.tooltip[data-popper-placement='top-end']::after {
+.tooltip-positioner[data-popper-placement='top-end'] .tooltip::after {
   right: var(--sl-tooltip-arrow-start-end-offset);
   left: auto;
 }
 
 // Arrow + left
-.tooltip[data-popper-placement^='left']::after {
+.tooltip-positioner[data-popper-placement^='left'] .tooltip::after {
   top: calc(50% - var(--sl-tooltip-arrow-size));
   left: 100%;
   border-left: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color);
@@ -94,17 +100,17 @@
   border-bottom: var(--sl-tooltip-arrow-size) solid transparent;
 }
 
-.tooltip[data-popper-placement='left-start']::after {
+.tooltip-positioner[data-popper-placement='left-start'] .tooltip::after {
   top: var(--sl-tooltip-arrow-start-end-offset);
 }
 
-.tooltip[data-popper-placement='left-end']::after {
+.tooltip-positioner[data-popper-placement='left-end'] .tooltip::after {
   top: auto;
   bottom: var(--sl-tooltip-arrow-start-end-offset);
 }
 
 // Arrow + right
-.tooltip[data-popper-placement^='right']::after {
+.tooltip-positioner[data-popper-placement^='right'] .tooltip::after {
   top: calc(50% - var(--sl-tooltip-arrow-size));
   right: 100%;
   border-right: var(--sl-tooltip-arrow-size) solid var(--sl-tooltip-background-color);
@@ -112,11 +118,11 @@
   border-bottom: var(--sl-tooltip-arrow-size) solid transparent;
 }
 
-.tooltip[data-popper-placement='right-start']::after {
+.tooltip-positioner[data-popper-placement='right-start'] .tooltip::after {
   top: var(--sl-tooltip-arrow-start-end-offset);
 }
 
-.tooltip[data-popper-placement='right-end']::after {
+.tooltip-positioner[data-popper-placement='right-end'] .tooltip::after {
   top: auto;
   bottom: var(--sl-tooltip-arrow-start-end-offset);
 }
diff --git a/src/components/tooltip/tooltip.tsx b/src/components/tooltip/tooltip.tsx
index 1056b092..80b33179 100644
--- a/src/components/tooltip/tooltip.tsx
+++ b/src/components/tooltip/tooltip.tsx
@@ -21,6 +21,7 @@ export class Tooltip {
   componentId = `tooltip-${++id}`;
   isShowing = false;
   popover: Popover;
+  tooltipPositioner: HTMLElement;
   target: HTMLElement;
   tooltip: any;
 
@@ -96,7 +97,7 @@ export class Tooltip {
     const slot = this.host.shadowRoot.querySelector('slot');
 
     this.target = this.getTarget();
-    this.popover = new Popover(this.target, this.tooltip);
+    this.popover = new Popover(this.target, this.tooltipPositioner);
     this.syncOptions();
 
     this.host.addEventListener('blur', this.handleBlur, true);
@@ -105,7 +106,7 @@ export class Tooltip {
     slot.addEventListener('slotchange', this.handleSlotChange);
 
     // Show on init if open
-    this.tooltip.hidden = !this.open;
+    this.tooltipPositioner.hidden = !this.open;
     if (this.open) {
       this.show();
     }
@@ -219,8 +220,9 @@ export class Tooltip {
   syncOptions() {
     this.popover.setOptions({
       placement: this.placement,
-      skidding: this.skidding,
       distance: this.distance,
+      skidding: this.skidding,
+      transitionElement: this.tooltip,
       onAfterHide: () => this.slAfterHide.emit(),
       onAfterShow: () => this.slAfterShow.emit()
     });
@@ -232,18 +234,20 @@ export class Tooltip {
         <slot aria-describedby={this.componentId} />
 
         {!this.disabled && (
-          <div
-            part="base"
-            ref={el => (this.tooltip = el)}
-            id={this.componentId}
-            class={{
-              tooltip: true,
-              'tooltip--open': this.open
-            }}
-            role="tooltip"
-            aria-hidden={!this.open}
-          >
-            {this.content}
+          <div ref={el => (this.tooltipPositioner = el)} class="tooltip-positioner">
+            <div
+              part="base"
+              ref={el => (this.tooltip = el)}
+              id={this.componentId}
+              class={{
+                tooltip: true,
+                'tooltip--open': this.open
+              }}
+              role="tooltip"
+              aria-hidden={!this.open}
+            >
+              {this.content}
+            </div>
           </div>
         )}
       </Host>