UNPKG

@rhds/elements

Version:

Red Hat Design System Elements

192 lines 11 kB
var _RhTooltip_instances, _RhTooltip_float, _RhTooltip_initialized, _RhTooltip_style, _RhTooltip_content_get, _RhTooltip_onKeydown; var RhTooltip_1; import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib"; import { html, LitElement, isServer } 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 { FloatingDOMController, } from '@patternfly/pfe-core/controllers/floating-dom-controller.js'; import { themable } from '@rhds/elements/lib/themable.js'; import { css } from "lit"; const styles = css `:host{display:inline}#container{display:inline-flex;position:relative;max-width:100%;--_floating-arrow-size:var(--rh-tooltip-arrow-size,var(--rh-tooltip__arrow--Width,11px))}#tooltip,#tooltip:after{position:absolute}#tooltip{display:none;opacity:0;pointer-events:none;z-index:10000;transition:opacity .3s cubic-bezier(.54,1.5,.38,1.11) 0s;text-align:var(--_text-alignment,center);word-break:break-word;translate:var(--_floating-content-translate);transform:translateX(var(--_rh-tooltip-shake-x,0));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 #15151533);max-width:var(--rh-tooltip-max-width,var(--rh-tooltip--MaxWidth,18.75rem) );border-radius:var(--rh-border-radius-default,3px);padding-block:var(--rh-tooltip-content-padding-block-start,var(--rh-tooltip__content--PaddingTop,var(--rh-space-lg,16px))) var(--rh-tooltip-content-padding-block-end,var(--rh-tooltip__content--PaddingBottom,var(--rh-space-lg,16px)));padding-inline:var(--rh-tooltip-content-padding-inline-start,var(--rh-tooltip__content--PaddingLeft,var(--rh-space-lg,16px))) var(--rh-tooltip-content-padding-inline-end,var(--rh-tooltip__content--PaddingRight,var(--rh-space-lg,16px)));font-size:var(--rh-tooltip-content-font-size,var(--rh-tooltip__content--FontSize,var(--rh-font-size-body-text-sm,.875rem)));color:light-dark(var(--rh-tooltip-content-color,var(--rh-tooltip__content--Color,var(--rh-color-text-primary-on-light,#151515))),var(--rh-tooltip-content-color,var(--rh-color-text-primary-on-dark,#fff)));background-color:light-dark(var(--rh-tooltip-content-background-color,var(--rh-tooltip__content--BackgroundColor,var(--rh-color-surface-lightest,#fff))),var(--rh-tooltip-content-background-color,var(--rh-color-surface-darkest,#151515)))}#tooltip.dark{color-scheme:dark}#tooltip.light{color-scheme:light}.initialized #tooltip{display:block}#tooltip:after{display:block;content:"";rotate:45deg;width:var(--_floating-arrow-size);height:var(--_floating-arrow-size);will-change:left top right bottom;background-color:light-dark(var(--rh-tooltip-content-background-color,var(--rh-tooltip__content--BackgroundColor,var(--rh-color-surface-lightest,#fff))),var(--rh-tooltip-content-background-color,var(--rh-tooltip__content--BackgroundColor,var(--rh-color-surface-darkest,#151515))))}.open #tooltip{opacity:1}.left #tooltip:after{inset-inline-end:calc(var(--_floating-arrow-size)*-.5)}.top #tooltip:after{inset-block-end:calc(var(--_floating-arrow-size)*-.5)}.right #tooltip:after{inset-inline-start:calc(var(--_floating-arrow-size)*-.5)}.bottom #tooltip:after{inset-block-start:calc(var(--_floating-arrow-size)*-.5)}.left.center #tooltip:after{inset-block-start:calc(50% - var(--_floating-arrow-size)*.5)}.top.center #tooltip:after{inset-inline-end:calc(50% - var(--_floating-arrow-size)*.5)}.right.center #tooltip:after{inset-block-start:calc(50% - var(--_floating-arrow-size)*.5)}.bottom.center #tooltip:after{inset-inline-end:calc(50% - var(--_floating-arrow-size)*.5)}.left.start #tooltip:after{inset-block-start:var(--_floating-arrow-size)}.top.start #tooltip:after{inset-inline-start:var(--_floating-arrow-size)}.right.start #tooltip:after{inset-block-start:var(--_floating-arrow-size)}.bottom.start #tooltip:after{inset-inline-start:var(--_floating-arrow-size)}.left.end #tooltip:after{inset-block-end:var(--_floating-arrow-size)}.top.end #tooltip:after{inset-inline-end:var(--_floating-arrow-size)}.right.end #tooltip:after{inset-block-end:var(--_floating-arrow-size)}.bottom.end #tooltip:after{inset-inline-end:var(--_floating-arrow-size)}:host([position=left]),:host([position=right]){--_text-alignment:"start"}#container.left:dir(rtl) #tooltip:after{inset-inline:calc(var(--_floating-arrow-size)*-.5) auto}#container.right:dir(rtl) #tooltip:after{inset-inline:auto calc(var(--_floating-arrow-size)*-.5)}`; const ENTER_EVENTS = ['focusin', 'tap', 'click', 'mouseenter']; const EXIT_EVENTS = ['focusout', 'blur', 'mouseleave']; function flattenSlottedNodes(x) { if (x.nodeType === Node.COMMENT_NODE) { return []; } else if (x instanceof HTMLSlotElement) { let assignedNodes = x.assignedNodes(); if (!assignedNodes.length) { assignedNodes = Array.from(x.childNodes); } return assignedNodes.flatMap(flattenSlottedNodes); } else { return [x]; } } function getBestGuessAccessibleContent(node) { if (node instanceof HTMLElement) { if (node.hasAttribute('aria-label')) { return node.getAttribute('aria-label') ?? ''; } else if (node.hidden || node.hasAttribute('inert')) { return ''; } } return node.textContent ?? ''; } /** * 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 * * @alias tooltip * */ let RhTooltip = RhTooltip_1 = class RhTooltip extends LitElement { constructor() { super(...arguments); _RhTooltip_instances.add(this); /** The position of the tooltip, relative to the invoking content */ this.position = 'top'; /** When true, disables screen reader announcements for tooltip content. Only use when another accessible label is provided. */ this.silent = false; _RhTooltip_float.set(this, new FloatingDOMController(this, { content: () => this.shadowRoot?.querySelector('#tooltip'), })); _RhTooltip_initialized.set(this, false); _RhTooltip_style.set(this, void 0); _RhTooltip_onKeydown.set(this, (event) => { if (event.key === 'Escape') { this.hide(); } }); } static announce(message) { this.announcer.innerText = message; } static initAnnouncer() { document.body.append((this.announcer = Object.assign(document.createElement('div'), { role: 'status', // apply `.visually-hidden` styles style: /* css */ ` position: fixed; inset-block-start: 0; inset-inline-start: 0; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;`, }))); } connectedCallback() { super.connectedCallback(); ENTER_EVENTS.forEach(evt => this.addEventListener(evt, this.show)); EXIT_EVENTS.forEach(evt => this.addEventListener(evt, this.hide)); RhTooltip_1.instances.add(this); } render() { const { alignment, anchor, open, styles } = __classPrivateFieldGet(this, _RhTooltip_float, "f"); const scheme = __classPrivateFieldGet(this, _RhTooltip_style, "f")?.colorScheme ?? 'light'; const dark = !!scheme.match(/^light( (dark|only))?/); const light = !!scheme.match(/^dark( only)?/); return html ` <div id="container" style="${styleMap(styles)}" class="${classMap({ open, initialized: !!__classPrivateFieldGet(this, _RhTooltip_initialized, "f"), [anchor]: !!anchor, [alignment]: !!alignment })}"> <div id="invoker"> <!-- Place invoking element here, i.e. the element which when hovered the tooltip will display. Must be inline content. --> <slot id="invoker-slot"></slot> </div> <div id="tooltip" role="status" class="${classMap({ dark, light })}"> <!-- Place tooltip content here. Overrides the \`content\` attribute. --> <slot id="content" name="content">${this.content}</slot> </div> </div> `; } /** Show the tooltip */ async show() { __classPrivateFieldSet(this, _RhTooltip_style, __classPrivateFieldGet(this, _RhTooltip_style, "f") ?? getComputedStyle(this), "f"); await this.updateComplete; const placement = this.position; const offset = !placement?.match(/top|bottom/) ? 15 : { mainAxis: 15, alignmentAxis: -4 }; await __classPrivateFieldGet(this, _RhTooltip_float, "f").show({ offset, placement }); __classPrivateFieldSet(this, _RhTooltip_initialized, __classPrivateFieldGet(this, _RhTooltip_initialized, "f") || true, "f"); if (!this.silent) { RhTooltip_1.announce(__classPrivateFieldGet(this, _RhTooltip_instances, "a", _RhTooltip_content_get)); } } /** Hide the tooltip */ async hide() { await __classPrivateFieldGet(this, _RhTooltip_float, "f").hide(); if (!this.silent) { RhTooltip_1.announcer.innerText = ''; } } }; _RhTooltip_float = new WeakMap(); _RhTooltip_initialized = new WeakMap(); _RhTooltip_style = new WeakMap(); _RhTooltip_onKeydown = new WeakMap(); _RhTooltip_instances = new WeakSet(); _RhTooltip_content_get = function _RhTooltip_content_get() { if (!__classPrivateFieldGet(this, _RhTooltip_float, "f").open || isServer) { return ''; } else if (this.content) { return this.content; } else { const contentSlot = this.shadowRoot?.getElementById('content') ?? null; const nodes = contentSlot ?.assignedNodes() ?.flatMap(flattenSlottedNodes) ?? []; return nodes .map(getBestGuessAccessibleContent) .join(' ') .trim(); } }; RhTooltip.version = '{{version}}'; RhTooltip.styles = [styles]; RhTooltip.instances = new Set(); (() => { if (!isServer) { globalThis.addEventListener('keydown', (event) => { const { instances } = RhTooltip_1; for (const instance of instances) { __classPrivateFieldGet(instance, _RhTooltip_onKeydown, "f").call(instance, event); } }); RhTooltip_1.initAnnouncer(); } })(); __decorate([ property() ], RhTooltip.prototype, "position", void 0); __decorate([ property() ], RhTooltip.prototype, "content", void 0); __decorate([ property({ type: Boolean, reflect: true }) ], RhTooltip.prototype, "silent", void 0); RhTooltip = RhTooltip_1 = __decorate([ customElement('rh-tooltip'), themable ], RhTooltip); export { RhTooltip }; //# sourceMappingURL=rh-tooltip.js.map