Fancy customization of Angular Tooltip component

6 Mar 202517 minutes to read

The arrow of the Tooltip can be customized as needed by customizing CSS in the sample level.

The EJ2 Tooltip component is styled using CSS3 and positions the tip arrow according to the Tooltip positions such as TopCenter, BottomLeft, RightTop, and others.

Here, the tip arrow is customized as Curved Tooltip and Bubble Tooltip.

Curved tip

The content for the tip pointer arrow has been added. To customize the curved tip arrow, override the following CSS class of tip arrow.

.e-arrow-tip-outer.e-tip-bottom,
.e-arrow-tip-outer.e-tip-top {
     border-left: none !important;
     border-right: none !important;
     border-top: none !important;
}

.e-arrow-tip.e-tip-top {
     transform: rotate(170deg);
}

Bubble tip

The two divs(inner div and outer div) have been added to achieve the bubble tip arrow. To customize the bubble tip arrow, override the following CSS class of tip arrow.

.e-arrow-tip-outer.e-tip-bottom, .e-arrow-tip-outer.e-tip-top
{
   border-radius: 50px;
   height: 10px;
   width: 10px;
}

.e-arrow-tip-inner.e-tip-bottom, .e-arrow-tip-inner.e-tip-top
  {
   border-radius: 50px;
   height: 10px;
   width: 10px;
  }

These tip arrow customizations have been achieved through CSS changes in the sample level. The Tooltip position can be changed by using the radio button click event.

The arrow tip pointer can also be disabled using the showTipPointer property.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { TooltipModule } from '@syncfusion/ej2-angular-popups'
import { RadioButtonModule } from '@syncfusion/ej2-angular-buttons'




import { Component, ViewChild, ViewEncapsulation } from '@angular/core';
import { TooltipComponent } from '@syncfusion/ej2-angular-popups';
import { ChangeArgs } from '@syncfusion/ej2-buttons';

@Component({
    imports: [

        TooltipModule, RadioButtonModule
    ],


    standalone: true,
    selector: 'my-app',
    template: `
     <div id="customization">
      <ejs-tooltip #tooltipcurve cssClass='curvetips e-tooltip-css' content='Tooltip arrow customized'>
            <button id="target">
                Curve Tip Arrow
            </button>
        </ejs-tooltip>
       </div>
        <div id="positions">
            <ul>
             <li><ejs-radiobutton label="TopCenter" value="TopCenter" name="state" checked='true' (change)="onChange($event)"></ejs-radiobutton></li>
              <li><ejs-radiobutton label="BottomLeft" value="BottomLeft" name="state" (change)="onChange($event)"></ejs-radiobutton></li>
            </ul>
        </div>
     <div id="balloon">
      <ejs-tooltip #tooltipCustom cssClass='bubbletip e-tooltip-css' content='Tooltip arrow customized as balloon tip' position='TopRight'>
            <button id="bubbletip">
                Bubble Tip Arrow
            </button>
        </ejs-tooltip>
       </div>
        <div id="btn">
            <ul>
             <li><ejs-radiobutton label="TopRight" value="TopRight" name="default" [checked]="true" (change)="onChanged($event)"></ejs-radiobutton></li>
              <li><ejs-radiobutton label="BottomLeft" value="BottomLeft" name="default" (change)="onChanged($event)"></ejs-radiobutton></li>
            </ul>
        </div>
        <ejs-tooltip #tooltip cssClass='pointertip e-tooltip-css' content='Disabled Tooltip Pointer' mouseTrail='true' [showTipPointer]='false'>
        <button id="tooltip">
            Disabled Tip Arrow
        </button>
        </ejs-tooltip>
    `,
    encapsulation: ViewEncapsulation.None,
})

export class AppComponent {
    @ViewChild('tooltip')
    public tooltipControl: TooltipComponent | any;
    @ViewChild('tooltipcurve')
    public tooltipCurve: TooltipComponent | any;
    @ViewChild('tooltipCustom')
    public tooltipCustom: TooltipComponent | any;
    constructor() { }
    onChange(args: ChangeArgs): void {
        this.tooltipCurve.position = args.value as any;
        this.tooltipCurve.dataBind();
    }
    onChanged(args: ChangeArgs): void {
        this.tooltipCustom.position = args.value as any;
        if (this.tooltipCustom.position == 'BottomLeft') {
            this.tooltipCustom.offsetY = -30;
        } else {
            this.tooltipCustom.offsetY = 0;
        }
        this.tooltipCustom.dataBind();
    }
}
@import 'node_modules/@syncfusion/ej2-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-popups/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-base/styles/material.css';
@import 'node_modules/@syncfusion/ej2-angular-buttons/styles/material.css';

/* csslint ignore:start */
#loader {
    color: #008cff;
    font-family: 'Helvetica Neue', 'calibiri', sans-serif;
    font-size: 16px;
    height: 40px;
    left: 45%;
    position: absolute;
    top: 45%;
    width: 30%;
  }
  
  #bubbletip {
    border-color: #d2a679;
  }

  #tooltip {
    border-color: #80180d;
    margin: 100px 0 0 100px;
  }

  #target {
    border-color: #e86238;
  }

  li {
    list-style: none;
  }

  .e-radio-wrapper {
    margin-top: 18px;
  }
  
  #target, #bubbletip, #tooltip {
    box-sizing: border-box;
    padding: 20px;
    width: 200px;
    text-align: center;
    top: -17px;
    margin-bottom: 40px;
  }
  
  @font-face {
    font-family: "tip";
    src: url("//ej2.syncfusion.com/products/typescript/tooltip/customization/Fonts/tip.tff") format("truetype"),
         url("//ej2.syncfusion.com/products/typescript/tooltip/customization/Fonts/tip.woff") format("woff"),
         url("//ej2.syncfusion.com/products/typescript/tooltip/customization/Fonts/tip.eot") format("eot"),
         url("//ej2.syncfusion.com/products/typescript/tooltip/customization/Fonts/tip.svg#tip") format("svg");
    font-weight: normal;
    font-style: normal;
  }
  
  #container {
    width: 100%;
  }
  
  #customization {
    padding-top: 40px;
    display: inline-block;
    margin: 40px 0 0 100px;
  }
  
  #balloon {
    display: inline-block;
    margin: 100px 0 0 100px;
  }
  
  .pointertip.e-tooltip-wrap .e-tip-content,
  .curvetips.e-tooltip-wrap .e-tip-content {
    color: white;
  }
  
  .pointertip.e-tooltip-wrap.e-popup {
    background-color: #80180d;
    border: 3px solid #ff9999;
  }
  
  .curvetips .e-arrow-tip.e-tip-top {
    margin-left: -20px;
    top: -16px;
    transform: rotate(177deg);
    left: 50px;
  }
  
  .curvetips.e-tooltip-wrap {
    padding: 17px;
    border-radius: 5px;
    background: #e86238;
    border: none;
  }
  
  .curvetips.e-tooltip-wrap .e-arrow-tip-outer.e-tip-bottom:before,
  .curvetips.e-tooltip-wrap .e-arrow-tip-outer.e-tip-top:before {
    font-family: "tip" !important;
    speak: none;
    font-size: 21px;
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    content: "\e700";
    color: #e86238;
  }
  
  .curvetips.e-tooltip-wrap .e-arrow-tip-outer.e-tip-bottom,
  .curvetips.e-tooltip-wrap .e-arrow-tip-outer.e-tip-top {
    border: none;
    top: -1px;
  }
  
  .curvetips.e-tooltip-wrap .e-arrow-tip.e-tip-bottom,
  .curvetips.e-tooltip-wrap .e-arrow-tip.e-tip-top {
    position: absolute;
    height: 18px;
    width: 28px;
  }
  
  #positions,
  #btn {
    display: inline-block;
  }

  #target .e-tip-content {
    padding: 0;
  }
  
  .bubbletip.e-tooltip-wrap {
    padding: 8px;
    border: 5px solid #dfccad;
    background-color: #7b5e32;
    width: 150px !important;
    border-radius: 50%;
  }
  
  .bubbletip.e-tooltip-wrap .e-tip-content {
    border-radius: 50%;
    text-align: center;
    color: white;
  }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip.e-tip-bottom { height: 40px; width: 50px; }
  .bubbletip.e-tooltip-wrap .e-arrow-tip.e-tip-top { height: 40px; width: 40px; }
  .bubbletip.e-tooltip-wrap .e-arrow-tip.e-tip-left,
  .bubbletip.e-tooltip-wrap .e-arrow-tip.e-tip-right { height: 12px; width: 20px; }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer {
    border: 1px solid #dfccad;
    background-color: #7b5e32;
  }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-bottom,
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-top {
    width: 10px;
    height: 10px;
    border-radius: 50px;
  }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-bottom {
    margin: 20px 20px 0 0;
  }

  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-top {
    margin-left: 20px;
  }
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-left,
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-right {
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
  }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-left {
    border-right: 20px solid #dfccad;
  }

  .bubbletip.e-tooltip-wrap .e-arrow-tip-outer.e-tip-right {
    border-left: 20px solid #dfccad;
  }
  .bubbletip.e-tooltip-wrap .e-arrow-tip-inner.e-tip-bottom,
  .bubbletip.e-tooltip-wrap .e-arrow-tip-inner.e-tip-top {
    border: 2px solid #dfccad;
    width: 20px;
    height: 20px;
    border-radius: 50px;
    background-color: #7b5e32;
  }
  
  .bubbletip.e-tooltip-wrap .e-arrow-tip-inner.e-tip-bottom {
    margin: -2px 0 0 8px;
    top: 1px !important;
  }
  
  .bubbletip .e-arrow-tip.e-tip-top {
    left: 44px !important;
    top: -19px !important;
  }

  .bubbletip .e-arrow-tip.e-tip-bottom {
    top: 88.9% !important;
    left: 4px !important;
  }

  .bubbletip.e-tooltip-wrap .e-arrow-tip-inner.e-tip-top {
    top: 10px !important;
  }

  .bubbletip.e-tooltip-wrap .e-arrow-tip-inner.e-tip-top:before {
    content: none;
  }
  
  /* csslint ignore:end */
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));