diff --git a/src/web-components/tooltip/index.style.ts b/src/web-components/tooltip/index.style.ts new file mode 100644 index 00000000..f63613ce --- /dev/null +++ b/src/web-components/tooltip/index.style.ts @@ -0,0 +1,119 @@ +import { css } from 'lit'; + +export const dropdownStyle = css` + .superviz-who-is-online__tooltip { + --host-heigth: 0px; + --host-width: 0px; + + background-color: rgb(var(--sv-gray-600)); + padding: 8px; + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; + position: absolute; + left: 50%; + transform: translateX(-50%); + opacity: 0; + border-radius: 2px; + cursor: default; + display: none; + transition: opacity 0.2s ease-in-out display 0s; + overflow-x: clip; + } + + .tooltip-extras { + left: 29px; + top: 60px; + z-index: 10; + } + + .superviz-who-is-online__tooltip-arrow { + width: 13px; + height: 13px; + position: absolute; + background-color: rgb(var(--sv-gray-600)); + transform: rotate(45deg); + border-top-left-radius: 3px; + border-bottom-right-radius: 3px; + } + + .show-tooltip { + opacity: 1; + display: block; + } + + .tooltip-name, + .tooltip-action { + margin: 0; + font-family: roboto; + white-space: nowrap; + text-align: center; + } + + .tooltip-name { + color: white; + font-size: 14px; + } + + .tooltip-action { + color: rgb(var(--sv-gray-400)); + font-size: 12px; + } + + .tooltip-top { + top: auto; + bottom: calc(var(--host-heigth) + 12px); + } + + .tooltip-bottom { + top: calc(var(--host-heigth) + 12px); + bottom: auto; + } + + .tooltip-left { + translate: -50% 0; + } + + .tooltip-center { + left: 50%; + transform: translateX(-50%); + right: auto; + } + + .tooltip-right { + translate: 50% 0; + } + + .tooltip-bottom .superviz-who-is-online__tooltip-arrow { + top: -6.5px; + } + + .tooltip-top .superviz-who-is-online__tooltip-arrow { + bottom: -6.5px; + } + + .tooltip-center .superviz-who-is-online__tooltip-arrow { + left: 0; + margin-left: 50%; + translate: -50% 0; + } + + .tooltip-left .superviz-who-is-online__tooltip-arrow { + translate: 50% 0; + border-radius: 0; + right: 0; + } + + .tooltip-right .superviz-who-is-online__tooltip-arrow { + translate: -100% 0; + border-radius: 0; + } + + @media (max-width: 780px) { + .tooltip-extras { + top: 52px; + left: 25px; + } + } +`; diff --git a/src/web-components/tooltip/index.test.ts b/src/web-components/tooltip/index.test.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/web-components/tooltip/index.ts b/src/web-components/tooltip/index.ts new file mode 100644 index 00000000..cb48956b --- /dev/null +++ b/src/web-components/tooltip/index.ts @@ -0,0 +1,138 @@ +import { CSSResultGroup, LitElement, PropertyValueMap, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { classMap } from 'lit/directives/class-map.js'; + +import { WebComponentsBase } from '../base'; + +import { dropdownStyle } from './index.style'; +import { Positions, PositionsEnum } from './types'; + +const WebComponentsBaseElement = WebComponentsBase(LitElement); +const styles: CSSResultGroup[] = [WebComponentsBaseElement.styles, dropdownStyle]; + +@customElement('superviz-tooltip') +export class Tooltip extends WebComponentsBaseElement { + static styles = styles; + + declare tooltipData: { name: string; action: string }; + + declare tooltip: HTMLElement; + declare tooltipOnLeft: boolean; + declare showTooltip: boolean; + declare tooltipVerticalPosition: Positions; + declare tooltipHorizontalPosition: Positions; + + declare hostSizes: { height: number; width: number }; + + static properties = { + tooltipData: { type: Object }, + tooltipOnLeft: { type: Boolean }, + showTooltip: { type: Boolean }, + tooltip: { type: Object }, + tooltipVerticalPosition: { type: String }, + tooltipHorizontalPosition: { type: String }, + hostSizes: { type: Object }, + }; + + constructor() { + super(); + this.tooltipVerticalPosition = PositionsEnum['TOOLTIP-BOTTOM']; + this.tooltipHorizontalPosition = PositionsEnum['TOOLTIP-CENTER']; + } + + protected firstUpdated( + _changedProperties: PropertyValueMap | Map, + ): void {} + + protected updated(changedProperties: PropertyValueMap | Map): void { + if (changedProperties.has('dropdown')) { + // + } + + if (changedProperties.has('showTooltip') && this.showTooltip) { + const { height, width } = (this.getRootNode() as any).host.getBoundingClientRect(); + if (this.hostSizes?.height !== height || this.hostSizes?.width !== width) { + this.hostSizes = { height, width }; + } + + this.tooltipVerticalPosition = PositionsEnum['TOOLTIP-BOTTOM']; + this.tooltipHorizontalPosition = PositionsEnum['TOOLTIP-CENTER']; + } + } + + private adjustTooltipVerticalPosition = () => { + const { left, right, bottom, top } = this.tooltip.getBoundingClientRect(); + const maxY = window.innerHeight; + + if (this.tooltipVerticalPosition.includes('top') && top < 0) { + this.tooltipVerticalPosition = this.tooltipVerticalPosition.replace( + 'top', + 'bottom', + ) as Positions; + } + + if (this.tooltipVerticalPosition.includes('bottom') && bottom > maxY) { + this.tooltipVerticalPosition = this.tooltipVerticalPosition.replace( + 'bottom', + 'top', + ) as Positions; + } + }; + + private adjustTooltipHorizontalPosition = () => { + const { left, right } = this.tooltip.getBoundingClientRect(); + const maxX = window.innerWidth; + + if (left < 0) { + this.tooltipHorizontalPosition = this.tooltipHorizontalPosition.replace( + 'center', + 'right', + ) as Positions; + } + + if (right > maxX) { + this.tooltipHorizontalPosition = this.tooltipHorizontalPosition.replace( + 'center', + 'left', + ) as Positions; + } + }; + + private adjustTooltipPosition = () => { + if (!this.tooltip) { + this.tooltip = this.shadowRoot.querySelector('.superviz-who-is-online__tooltip'); + } + + this.adjustTooltipVerticalPosition(); + this.adjustTooltipHorizontalPosition(); + }; + + private renderTooltip() { + setTimeout(() => this.adjustTooltipPosition()); + const verticalPosition = this.tooltipVerticalPosition; + const horizontalPosition = this.tooltipHorizontalPosition; + + const classList = { + 'superviz-who-is-online__tooltip': true, + 'tooltip-extras': this.tooltipOnLeft, + 'show-tooltip': this.showTooltip, + }; + classList[verticalPosition] = true; + classList[horizontalPosition] = true; + + console.error(horizontalPosition); + + return html`
+

${this.tooltipData.name}

+

${this.tooltipData.action}

+
+
`; + } + + protected render() { + return html`${this.renderTooltip()}`; + } +} diff --git a/src/web-components/tooltip/types.ts b/src/web-components/tooltip/types.ts new file mode 100644 index 00000000..7ad72330 --- /dev/null +++ b/src/web-components/tooltip/types.ts @@ -0,0 +1,9 @@ +export enum PositionsEnum { + 'TOOLTIP-BOTTOM' = 'tooltip-bottom', + 'TOOLTIP-TOP' = 'tooltip-top', + 'TOOLTIP-LEFT' = 'tooltip-left', + 'TOOLTIP-RIGHT' = 'tooltip-right', + 'TOOLTIP-CENTER' = 'tooltip-center', +} + +export type Positions = PositionsEnum | `${PositionsEnum}`;