Skip to content

Commit 6ab97f7

Browse files
Merge pull request #16608 from IgniteUI/rivanova/tooltip-arrow-16572-21.0.x
fix(tooltip): show arrow for nested tooltips - 21.0.x
2 parents b6e991e + 420c0fb commit 6ab97f7

File tree

3 files changed

+106
-3
lines changed

3 files changed

+106
-3
lines changed

projects/igniteui-angular/directives/src/directives/tooltip/tooltip.common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export class TooltipPositionStrategy extends AutoPositionStrategy {
185185
return;
186186
}
187187

188-
const arrow = tooltip.querySelector('[data-arrow="true"]') as HTMLElement;
188+
const arrow = Array.from(tooltip.children).find(el => el.matches('[data-arrow="true"]')) as HTMLElement;
189189

190190
// If display is none -> tooltipTarget's hasArrow is false
191191
if (!arrow || arrow.style.display === 'none') {

projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { DebugElement } from '@angular/core';
22
import { fakeAsync, TestBed, tick, flush, waitForAsync, ComponentFixture } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
5-
import { IgxTooltipSingleTargetComponent, IgxTooltipMultipleTargetsComponent, IgxTooltipPlainStringComponent, IgxTooltipWithToggleActionComponent, IgxTooltipMultipleTooltipsComponent, IgxTooltipWithCloseButtonComponent, IgxTooltipWithNestedContentComponent } from '../../../../test-utils/tooltip-components.spec';
5+
import { IgxTooltipSingleTargetComponent, IgxTooltipMultipleTargetsComponent, IgxTooltipPlainStringComponent, IgxTooltipWithToggleActionComponent, IgxTooltipMultipleTooltipsComponent, IgxTooltipWithCloseButtonComponent, IgxTooltipWithNestedContentComponent, IgxTooltipNestedTooltipsComponent } from '../../../../test-utils/tooltip-components.spec';
66
import { UIInteractions } from '../../../../test-utils/ui-interactions.spec';
77
import { HorizontalAlignment, VerticalAlignment, AutoPositionStrategy } from '../../../../core/src/services/public_api';
88
import { IgxTooltipDirective } from './tooltip.directive';
@@ -29,7 +29,8 @@ describe('IgxTooltip', () => {
2929
IgxTooltipPlainStringComponent,
3030
IgxTooltipWithToggleActionComponent,
3131
IgxTooltipWithCloseButtonComponent,
32-
IgxTooltipWithNestedContentComponent
32+
IgxTooltipWithNestedContentComponent,
33+
IgxTooltipNestedTooltipsComponent
3334
]
3435
}).compileComponents();
3536
UIInteractions.clearOverlay();
@@ -533,6 +534,69 @@ describe('IgxTooltip', () => {
533534
}));
534535
});
535536

537+
describe('Nested tooltips', () => {
538+
let tooltipTarget1: IgxTooltipTargetDirective;
539+
let tooltipTarget2: IgxTooltipTargetDirective;
540+
let tooltipTarget3: IgxTooltipTargetDirective;
541+
542+
let tooltip1: IgxTooltipDirective;
543+
let tooltip2: IgxTooltipDirective;
544+
let tooltip3: IgxTooltipDirective;
545+
546+
// Handles getting the left offset when tooltip placement is Bottom
547+
const getArrowLeftOffset = (tooltip: IgxTooltipDirective) => {
548+
const tooltipRect = tooltip.element.getBoundingClientRect();
549+
const arrowRect = tooltip.arrow.getBoundingClientRect();
550+
551+
const offset = tooltipRect.width / 2 - arrowRect.width / 2;
552+
return Math.round(offset);
553+
};
554+
555+
const verifyTooltipArrowAlignment = (tooltip: IgxTooltipDirective) => {
556+
const arrowClassName = 'igx-tooltip--bottom';
557+
const arrowTopOffset = '-4px';
558+
const arrowLeftOffset = getArrowLeftOffset(tooltip) + 'px';
559+
560+
expect(tooltip.arrow.classList.contains(arrowClassName)).toBeTrue();
561+
expect(tooltip.arrow.style.top).toBe(arrowTopOffset);
562+
expect(tooltip.arrow.style.left).toBe(arrowLeftOffset);
563+
};
564+
565+
beforeEach(waitForAsync(() => {
566+
fix = TestBed.createComponent(IgxTooltipNestedTooltipsComponent);
567+
fix.detectChanges();
568+
569+
tooltipTarget1 = fix.componentInstance.targetLevel1;
570+
tooltipTarget2 = fix.componentInstance.targetLevel2;
571+
tooltipTarget3 = fix.componentInstance.targetLevel3;
572+
573+
tooltip1 = fix.componentInstance.tooltipLevel1;
574+
tooltip2 = fix.componentInstance.tooltipLevel2;
575+
tooltip3 = fix.componentInstance.tooltipLevel3;
576+
}));
577+
578+
it('should show arrow for each tooltip', fakeAsync(() => {
579+
hoverElement(tooltipTarget1);
580+
flush();
581+
verifyTooltipVisibility(tooltip1.element, tooltipTarget1, true);
582+
expect(tooltipTarget1.hasArrow).toBeTrue();
583+
verifyTooltipArrowAlignment(tooltip1);
584+
585+
hoverElement(tooltipTarget2);
586+
flush();
587+
verifyTooltipVisibility(tooltip2.element, tooltipTarget2, true);
588+
expect(tooltipTarget2.hasArrow).toBeTrue();
589+
verifyTooltipArrowAlignment(tooltip2);
590+
591+
hoverElement(tooltipTarget3);
592+
flush();
593+
verifyTooltipVisibility(tooltip3.element, tooltipTarget3, true);
594+
expect(tooltipTarget3.hasArrow).toBeTrue();
595+
verifyTooltipArrowAlignment(tooltip3);
596+
597+
}));
598+
});
599+
536600
describe('Multiple targets with single tooltip', () => {
537601
let targetOne: IgxTooltipTargetDirective;
538602
let targetTwo: IgxTooltipTargetDirective;

projects/igniteui-angular/test-utils/tooltip-components.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,42 @@ export class IgxTooltipWithNestedContentComponent {
168168
@ViewChild(IgxTooltipDirective, { static: true }) public tooltip!: IgxTooltipDirective;
169169
@ViewChild(IgxTooltipTargetDirective, { static: true }) public tooltipTarget!: IgxTooltipTargetDirective;
170170
}
171+
172+
@Component({
173+
template: `
174+
<button #targetLevel1 [igxTooltipTarget]="tooltipLevel1" [hasArrow]="true">
175+
Parent
176+
</button>
177+
178+
<!-- Level 1 Tooltip -->
179+
<div #tooltipLevel1="tooltip" igxTooltip>
180+
Parent tooltip
181+
<button #targetLevel2 [igxTooltipTarget]="tooltipLevel2" [hasArrow]="true">
182+
Child
183+
</button>
184+
185+
<!-- Level 2 Tooltip -->
186+
<div #tooltipLevel2="tooltip" igxTooltip>
187+
Child tooltip
188+
<button #targetLevel3 [igxTooltipTarget]="tooltipLevel3" [hasArrow]="true">
189+
Grandchild
190+
</button>
191+
192+
<!-- Level 3 Tooltip -->
193+
<div #tooltipLevel3="tooltip" igxTooltip>Grandchild tooltip</div>
194+
195+
</div>
196+
</div>
197+
`,
198+
imports: [IgxTooltipDirective, IgxTooltipTargetDirective],
199+
standalone: true
200+
})
201+
export class IgxTooltipNestedTooltipsComponent {
202+
@ViewChild('targetLevel1', { read: IgxTooltipTargetDirective, static: true }) public targetLevel1: IgxTooltipTargetDirective;
203+
@ViewChild('targetLevel2', { read: IgxTooltipTargetDirective, static: true }) public targetLevel2: IgxTooltipTargetDirective;
204+
@ViewChild('targetLevel3', { read: IgxTooltipTargetDirective, static: true }) public targetLevel3: IgxTooltipTargetDirective;
205+
206+
@ViewChild('tooltipLevel1', { read: IgxTooltipDirective, static: true }) public tooltipLevel1: IgxTooltipDirective;
207+
@ViewChild('tooltipLevel2', { read: IgxTooltipDirective, static: true }) public tooltipLevel2: IgxTooltipDirective;
208+
@ViewChild('tooltipLevel3', { read: IgxTooltipDirective, static: true }) public tooltipLevel3: IgxTooltipDirective;
209+
}

0 commit comments

Comments
 (0)