The problem
We want to show/hide a tooltip for some text depending on whether there is enough room for the text.
Solution
A directive that checks the width of the text and compares it against the width of the container. If the latter is smaller than the former the tooltip will be shown.
To focus on the directive implementation we are going to use the tooltips provided by angular material.
Implementation
TooltipIfCollapsedDirective
The directive reads the width of the component it is applied to to check if the tooltip needs to enabled or disabled.
import { Directive, ElementRef, HostListener } from '@angular/core';
import { MatTooltip } from '@angular/material/tooltip';
@Directive({
selector: '[appTooltipIfCollapsed]',
standalone: true,
})
export class TooltipIfCollapsedDirective {
constructor(private element: ElementRef, private tooltip: MatTooltip) {}
ngAfterViewInit(): void {
// The requestAnimationFrame gives the browser some time to calculate the scrollWidth which is required
// to determine if the tooltip should be hidden or not.
window.requestAnimationFrame(() => {
this.updateTooltip();
});
}
@HostListener('window:resize', ['$event'])
onResize() {
window.requestAnimationFrame(() => {
this.updateTooltip();
});
}
private updateTooltip() {
if (
this.element.nativeElement.getBoundingClientRect().width <
this.element.nativeElement.scrollWidth
) {
this.tooltip.disabled = false;
} else {
this.tooltip.disabled = true;
}
}
}
It compares the width
of the component against the scrollWidth
. If the latter is larger than the former it means that the text does not completely fit into the container.
The first call to updateTooltip
is in ngAfterViewInit
so that the container width
is available. The same call is made whenever the browser window is changed.
As mentioned in the comment, requestAnimationFrame
gives the browser some time to recalculate the scrollWidth
. Without it I had some instances where the scrollWidth
was not up to date leading to the tooltip being shown/hidden when it should not.
Example
The directive is added to the node which also defines the tooltip (matToolbar
in the case of Angular Material).
<div [matTooltip]="text" appTooltipIfCollapsed>
{{ text }}
</div>
:host {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
container-type: inline-size;
}
div {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
@container (width < 600px) {
div {
width: 100px;
}
}
For the sake of the example the width
of the text container is restricted to 100px
when the containing component (AppComponent
) width
drops below 600px
.
Resizing the browser window now shows or hides the tooltip
when the width
is larger or smaller than 600px
.
The code can be found here
Top comments (0)