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>