Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@

All notable changes for each version of this project will be documented in this file.

## 21.1.0

### New Features

- `IgxTooltipTarget`
- Added new properties:
- `showTriggers` - Which event triggers will show the tooltip. Expects a comma-separated string of different event triggers. Defaults to `pointerenter`.
- `hideTriggers` - Which event triggers will hide the tooltip. Expects a comma-separated string of different event triggers. Defaults to `pointerleave` and `click`.

```html
<igx-icon [igxTooltipTarget]="tooltipRef" [showTriggers]="'click,focus'" [hideTriggers]="'keypress,blur'">info</igx-icon>
<span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
```

## 21.0.0

### New Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ Since the **IgxTooltip** directive extends the **IgxToggle** directive and there
| hasArrow | boolean | Controls whether to display an arrow indicator for the tooltip. Defaults to `false`. |
| sticky | boolean | When set to `true`, the tooltip renders a default close icon `x`. The tooltip remains visible until the user closes it via the close icon `x` or `Esc` key. Defaults to `false`. |
| closeButtonTemplate | TemplateRef<any> | Allows templating the default close icon `x`. |
| showTriggers | string | Which event triggers will show the tooltip. Expects a comma-separated string of different event triggers. Defaults to `pointerenter`. |
| hideTriggers | string | Which event triggers will hide the tooltip. Expects a comma-separated string of different event triggers. Defaults to `pointerleave` and `click`. |


> Note: Setting `showTriggers` and `hideTriggers` only has effect when interacting with the target, not the tooltip itself. Default event triggers for the tooltip are `pointerenter` and `pointerleave`.

#### Templating the close button

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import {
Directive, OnInit, OnDestroy, Output, ViewContainerRef, HostListener,
Input, EventEmitter, booleanAttribute, inject, TemplateRef, ComponentRef, Renderer2,
Directive, OnInit, OnDestroy, Output, ElementRef, ViewContainerRef,
Input, EventEmitter, booleanAttribute, TemplateRef, ComponentRef, Renderer2,
EnvironmentInjector,
createComponent,
AfterViewInit,
inject,
} from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
Expand All @@ -13,7 +14,7 @@ import { IgxToggleActionDirective } from '../toggle/toggle.directive';
import { IgxTooltipComponent } from './tooltip.component';
import { IgxTooltipDirective } from './tooltip.directive';
import { IgxTooltipCloseButtonComponent } from './tooltip-close-button.component';
import { TooltipPositionSettings, TooltipPositionStrategy } from './tooltip.common';
import { parseTriggers, TooltipPositionSettings, TooltipPositionStrategy } from './tooltip.common';

export interface ITooltipShowEventArgs extends IBaseEventArgs {
target: IgxTooltipTargetDirective;
Expand Down Expand Up @@ -46,10 +47,6 @@ export interface ITooltipHideEventArgs extends IBaseEventArgs {
standalone: true
})
export class IgxTooltipTargetDirective extends IgxToggleActionDirective implements OnInit, AfterViewInit, OnDestroy {
private _viewContainerRef = inject(ViewContainerRef);
private _renderer = inject(Renderer2);
private _envInjector = inject(EnvironmentInjector);

/**
* Gets/sets the amount of milliseconds that should pass before showing the tooltip.
*
Expand Down Expand Up @@ -235,6 +232,46 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
@Input({ transform: booleanAttribute })
public tooltipDisabled = false;

/**
* Which event triggers will show the tooltip.
* Expects a comma-separated string of different event triggers.
* Defaults to `pointerenter`.
* ```html
* <igx-icon [igxTooltipTarget]="tooltipRef" [showTriggers]="'click,focus'">info</igx-icon>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
@Input()
public get showTriggers(): string {
return Array.from(this._showTriggers).join();
}

public set showTriggers(value: string) {
this._showTriggers = parseTriggers(value);
this.removeEventListeners();
this.addEventListeners();
}

/**
* Which event triggers will hide the tooltip.
* Expects a comma-separated string of different event triggers.
* Defaults to `pointerleave` and `click`.
* ```html
* <igx-icon [igxTooltipTarget]="tooltipRef" [hideTriggers]="'keypress,blur'">info</igx-icon>
* <span #tooltipRef="tooltip" igxTooltip>Hello there, I am a tooltip!</span>
* ```
*/
@Input()
public get hideTriggers(): string {
return Array.from(this._hideTriggers).join();
}

public set hideTriggers(value: string) {
this._hideTriggers = parseTriggers(value);
this.removeEventListeners();
this.addEventListeners();
}

/**
* @hidden
*/
Expand All @@ -256,8 +293,11 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
}

/**
* @hidden
*/
* Specifies a plain text as tooltip content.
* ```html
* <igx-icon igxTooltipTarget [tooltip]="'Infragistics Inc. HQ'">info</igx-icon>
* ```
*/
@Input()
public set tooltip(content: any) {
if (!this.target && (typeof content === 'string' || content instanceof String)) {
Expand Down Expand Up @@ -326,6 +366,10 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
@Output()
public tooltipHide = new EventEmitter<ITooltipHideEventArgs>();

private _viewContainerRef = inject(ViewContainerRef);
private _renderer = inject(Renderer2);
private _envInjector = inject(EnvironmentInjector);

private _destroy$ = new Subject<void>();
private _autoHideDelay = 180;
private _isForceClosed = false;
Expand All @@ -334,15 +378,20 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
private _closeTemplate: TemplateRef<any>;
private _sticky = false;
private _positionSettings: PositionSettings = TooltipPositionSettings;
private _showTriggers = new Set(['pointerenter']);
private _hideTriggers = new Set(['pointerleave', 'click']);

private _abortController = new AbortController();

/**
* @hidden
*/
@HostListener('click')
public override onClick() {
if (!this.target.collapsed) {
this._hideOnInteraction();
} else if (this.target.timeoutId) {
if (
this.target.timeoutId &&
this.target.collapsed &&
!this._showTriggers.has('click')
) {
clearTimeout(this.target.timeoutId);
this.target.timeoutId = null;
}
Expand All @@ -351,46 +400,22 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
/**
* @hidden
*/
@HostListener('mouseenter')
public onMouseEnter() {
public onShow(): void {
this._checksBeforeShowing(() => this._showOnInteraction());
}

/**
* @hidden
*/
@HostListener('mouseleave')
public onMouseLeave() {
if (this.tooltipDisabled) {
public onHide(): void {
if (this.tooltipDisabled || this.target.collapsed) {
return;
}

this._checkOutletAndOutsideClick();
this._hideOnInteraction();
}

/**
* @hidden
*/
public onTouchStart() {
this._checksBeforeShowing(() => this._showOnInteraction());
}

/**
* @hidden
*/
public onDocumentTouchStart(event) {
if (this.tooltipDisabled || this?.target?.tooltipTarget !== this) {
return;
}

if (this.nativeElement !== event.target &&
!this.nativeElement.contains(event.target)
) {
this._hideOnInteraction();
}
}

/**
* @hidden
*/
Expand All @@ -414,7 +439,8 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
}
});

this.nativeElement.addEventListener('touchstart', this.onTouchStart = this.onTouchStart.bind(this), { passive: true });
this.removeEventListeners();
this.addEventListeners();
}

/**
Expand All @@ -431,7 +457,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
*/
public ngOnDestroy() {
this.hideTooltip();
this.nativeElement.removeEventListener('touchstart', this.onTouchStart);
this.removeEventListeners();
this._destroyCloseButton();
this._destroy$.next();
this._destroy$.complete();
Expand Down Expand Up @@ -463,6 +489,24 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
return Object.assign({}, this._overlayDefaults, this.overlaySettings);
}

private addEventListeners(): void {
const options = { passive: true, signal: this._abortController.signal };

this.onShow = this.onShow.bind(this);
for (const each of this._showTriggers) {
this.nativeElement.addEventListener(each, this.onShow, options);
}
this.onHide = this.onHide.bind(this);
for (const each of this._hideTriggers) {
this.nativeElement.addEventListener(each, this.onHide, options);
}
}

private removeEventListeners(): void {
this._abortController.abort();
this._abortController = new AbortController();
}

private _checkOutletAndOutsideClick(): void {
if (this.outlet) {
this._overlayDefaults.outlet = this.outlet;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import { useAnimation } from '@angular/animations';
import { fadeOut, scaleInCenter } from 'igniteui-angular/animations';

export const TooltipRegexes = Object.freeze({
/** Used for parsing the strings passed in the tooltip `show/hide-trigger` properties. */
triggers: /[,\s]+/,

/** Matches horizontal `Placement` end positions. `left-end` | `right-end` */
horizontalEnd: /^(left|right)-end$/,

Expand Down Expand Up @@ -330,3 +333,9 @@ export const PositionsMap = new Map<Placement, PositionSettings>([
verticalStartPoint: VerticalAlignment.Bottom,
}]
]);

export function parseTriggers(triggers: string): Set<string> {
return new Set(
(triggers ?? '').split(TooltipRegexes.triggers).filter((s) => s.trim())
);
}
Loading
Loading