Skip to content

Commit

Permalink
fix(tooltip): remove basetooltip (#1273)
Browse files Browse the repository at this point in the history
Closes #1272
  • Loading branch information
bennypowers authored Oct 23, 2023
1 parent 815ff6c commit 61ca720
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 24 deletions.
4 changes: 4 additions & 0 deletions .changeset/tooltip-no-base.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
"@rhds/elements": patch
---
`<rh-tooltip>`: remove dependency on `@patternfly/elements`
88 changes: 76 additions & 12 deletions elements/rh-tooltip/rh-tooltip.css
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
/* WARNING: properties containing `__`are deprecated and will be removed */

:host([position="left"]),
:host([position="right"]) {
--_text-alignment: "start";
:host {
display: inline;
}

#rh-container {
display: contents;
#container {
display: inline-flex;
position: relative;
max-width: 100%;

/* WARNING: properties containing `__`are deprecated and will be removed */
--_floating-arrow-size: var(--rh-tooltip-arrow-size,
var(--rh-tooltip__arrow--Width, 11px));
}

.dark {
--rh-tooltip-content-background-color: var(--rh-color-surface-lightest, #ffffff);
--rh-tooltip-content-color: var(--rh-color-text-primary-on-light, #151515);
#tooltip,
#tooltip:after {
position: absolute;
}

#tooltip {
line-height: var(--rh-line-height-body-text, 1.5);
max-width: var(--rh-tooltip-max-width, var(--rh-tooltip--MaxWidth, 18.75rem));
display: block;
opacity: 0;
pointer-events: none;
z-index: 10000;
transition: opacity 300ms cubic-bezier(0.54, 1.5, 0.38, 1.11) 0s;
text-align: var(--_text-alignment, center);
word-break: break-word;
translate: var(--_floating-content-translate);
width: max-content;
top: 0;
left: 0;
will-change: opacity;
line-height: var(--rh-line-height-body-text, 1.5);
box-shadow: var(--rh-box-shadow-sm, 0 2px 4px 0 rgba(21, 21, 21, 0.2));
max-width: var(--rh-tooltip-max-width, var(--rh-tooltip--MaxWidth, 18.75rem));

/* WARNING: properties containing `__`are deprecated and will be removed */
padding:
var(--rh-tooltip-content-padding-block-start,
var(--rh-tooltip__content--PaddingTop, var(--rh-space-lg, 16px)))
Expand All @@ -31,15 +44,66 @@
var(--rh-tooltip__content--PaddingBottom, var(--rh-space-lg, 16px)))
var(--rh-tooltip-content-padding-inline-start,
var(--rh-tooltip__content--PaddingLeft, var(--rh-space-lg, 16px)));

/* WARNING: properties containing `__`are deprecated and will be removed */
font-size: var(--rh-tooltip-content-font-size,
var(--rh-tooltip__content--FontSize, var(--rh-font-size-body-text-sm, 0.875rem)));

/* WARNING: properties containing `__`are deprecated and will be removed */
color: var(--rh-tooltip-content-color,
var(--rh-tooltip__content--Color, var(--rh-color-text-primary-on-dark, #ffffff)));
background-color: var(--rh-tooltip-content-background-color,
var(--rh-tooltip__content--BackgroundColor, var(--rh-color-surface-darkest, #151515)));
}

#tooltip:after {
display: block;
content: "";
rotate: 45deg;
width: var(--_floating-arrow-size);
height: var(--_floating-arrow-size);
will-change: left top right bottom;

/* WARNING: properties containing `__`are deprecated and will be removed */
background-color: var(--rh-tooltip-content-background-color,
var(--rh-tooltip__content--BackgroundColor, var(--rh-color-surface-darkest, #151515)));
}

.open #tooltip {
opacity: 1;
}

/* PLAIN */
.left #tooltip:after { right: calc(-0.5 * var(--_floating-arrow-size)); }
.top #tooltip:after { top: calc(100% - 0.5 * var(--_floating-arrow-size)); }
.right #tooltip:after { right: calc(100% - 0.5 * var(--_floating-arrow-size)); }
.bottom #tooltip:after { bottom: calc(100% - 0.5 * var(--_floating-arrow-size)); }

/* CENTER */
.left.center #tooltip:after { top: calc(50% - 0.5 * var(--_floating-arrow-size)); }
.top.center #tooltip:after { right: calc(50% - 0.5 * var(--_floating-arrow-size)); }
.right.center #tooltip:after { top: calc(50% - 0.5 * var(--_floating-arrow-size)); }
.bottom.center #tooltip:after { right: calc(50% - 0.5 * var(--_floating-arrow-size)); }

/* START */
.left.start #tooltip:after { top: var(--_floating-arrow-size); }
.top.start #tooltip:after { left: var(--_floating-arrow-size); }
.right.start #tooltip:after { top: var(--_floating-arrow-size); }
.bottom.start #tooltip:after { left: var(--_floating-arrow-size); }

/* END */
.left.end #tooltip:after { bottom: var(--_floating-arrow-size); }
.top.end #tooltip:after { right: var(--_floating-arrow-size); }
.right.end #tooltip:after { bottom: var(--_floating-arrow-size); }
.bottom.end #tooltip:after { right: var(--_floating-arrow-size); }

:host([position="left"]),
:host([position="right"]) {
--_text-alignment: "start";
}

.dark {
--rh-tooltip-content-background-color: var(--rh-color-surface-lightest, #ffffff);
--rh-tooltip-content-color: var(--rh-color-text-primary-on-light, #151515);
}

82 changes: 70 additions & 12 deletions elements/rh-tooltip/rh-tooltip.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,100 @@
import type { Placement } from '@patternfly/pfe-core/controllers/floating-dom-controller.js';

import { html } from 'lit';
import { html, LitElement } from 'lit';
import { customElement } from 'lit/decorators/custom-element.js';
import { property } from 'lit/decorators/property.js';
import { classMap } from 'lit/directives/class-map.js';
import { styleMap } from 'lit/directives/style-map.js';

import { colorContextConsumer, type ColorTheme } from '../../lib/context/color/consumer.js';

import { BaseTooltip } from '@patternfly/elements/pf-tooltip/BaseTooltip.js';
import {
FloatingDOMController,
type Placement,
} from '@patternfly/pfe-core/controllers/floating-dom-controller.js';

import styles from './rh-tooltip.css';

const ENTER_EVENTS = ['focusin', 'tap', 'click', 'mouseenter'];
const EXIT_EVENTS = ['focusout', 'blur', 'mouseleave'];

/**
* A tooltip is a floating text area that provides helpful or contextual information on hover, focus, or tap.
* A tooltip is a floating text area that provides helpful
* or contextual information on hover, focus, or tap.
*
* @summary Reveals a small area of information on hover
*
* @slot - Place element content here
* @slot - Place invoking element here,
* i.e. the element which when hovered the tooltip will display.
* Must be inline content.
* @slot content - Place tooltip content here. Overrides the `content` attribute.
*
* @cssprop {<length>} [--rh-tooltip-arrow-size=11px]
* @cssprop {<color>} [--rh-tooltip-content-background-color=#ffffff]
* @cssprop {<color>} [--rh-tooltip-content-color=#151515]
* @cssprop {<length>} [--rh-tooltip-max-width=18.75rem]
* @cssprop {<length>} [--rh-tooltip-content-padding-block-start=16px]
* @cssprop {<length>} [--rh-tooltip-content-padding-inline-end=16px]
* @cssprop {<length>} [--rh-tooltip-content-padding-block-end=16px]
* @cssprop {<length>} [--rh-tooltip-content-padding-inline-start=16px]
* @cssprop {<absolute-size> | <relative-size> | <length> | <percentage>} [--rh-tooltip-content-font-size=0.875rem]
*/
@customElement('rh-tooltip')
export class RhTooltip extends BaseTooltip {
export class RhTooltip extends LitElement {
static readonly version = '{{version}}';

static readonly styles = [...BaseTooltip.styles, styles];

@colorContextConsumer() private on?: ColorTheme;
static readonly styles = [styles];

/** The position of the tooltip, relative to the invoking content */
@property() position: Placement = 'top';

/** Tooltip content. Overridden by the content slot */
@property() content?: string;

@colorContextConsumer() private on?: ColorTheme;

#float = new FloatingDOMController(this, {
content: (): HTMLElement | undefined | null => this.shadowRoot?.querySelector('#tooltip'),
});

override connectedCallback(): void {
super.connectedCallback();
ENTER_EVENTS.forEach(evt => this.addEventListener(evt, this.show));
EXIT_EVENTS.forEach(evt => this.addEventListener(evt, this.hide));
}

override render() {
const { on = '' } = this;
const { alignment, anchor, open, styles } = this.#float;
const ariaHidden = String(!open) as 'true' | 'false';

return html`
<div id="rh-container" class="${classMap({ [on]: !!on })}">
${super.render()}
<div id="container"
style="${styleMap(styles)}"
class="${classMap({ open,
[on]: !!on,
[anchor]: !!anchor,
[alignment]: !!alignment })}">
<slot id="invoker" role="tooltip" aria-labelledby="tooltip"></slot>
<slot id="tooltip"
name="content"
aria-hidden="${ariaHidden}">${this.content}</slot>
</div>
`;
}

/** Show the tooltip */
async show() {
await this.updateComplete;
const placement = this.position;
const offset =
!placement?.match(/top|bottom/) ? 15
: { mainAxis: 15, alignmentAxis: -4 };
await this.#float.show({ offset, placement });
}

/** Hide the tooltip */
async hide() {
await this.#float.hide();
}
}

declare global {
Expand Down

0 comments on commit 61ca720

Please sign in to comment.