Let's build - Autohide tooltip in Angular
Published: 2023-08-05 11:07:29

---
title: Let's build - Autohide tooltip in Angular
published: true
description: Hide or show a tooltip depending if the content fits into its container
series: Let's build
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-08-05 10:59 +0000
---

# 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.
```typescript
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).

```html
<div [matTooltip]="text" appTooltipIfCollapsed>
  {{ text }}
</div>
```

```css
: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](https://github.com/remshams/angular-hide-tooltip)