Skip to main content

Creating Custom Tooltips

Overview

This guide will teach you how to create a custom tooltip component for the @celerofinancas/ui-directives library using the TOOLTIP_COMPONENT_TOKEN. You'll learn to build a tooltip component from scratch that integrates seamlessly with the tooltip directive system.

What You'll Build

By the end of this guide, you'll have:

  • A custom tooltip component that implements the required interface
  • Proper styling with arrow indicators for different placements
  • A component that can be injected via dependency injection tokens
  • Full integration with the existing tooltip directive system

Prerequisites

  • Basic Angular knowledge
  • Understanding of Angular components and dependency injection
  • Familiarity with TypeScript interfaces

Step 1: Understanding the TooltipBase Interface

First, you need to understand what interface your component must implement:

export interface TooltipBase {
text: string;
tooltipRef?: TemplateRef<any>;
maxWidth?: string | number;
placement?: TooltipPlacement;
}

export type TooltipPlacement = 'top' | 'bottom' | 'start' | 'end';

Step 2: Create the Component Structure

Create your tooltip component file:

src/app/shared/components/tooltip/tooltip.component.ts
import { ChangeDetectionStrategy, Component, Input, TemplateRef } from '@angular/core';
import { TooltipBase, TooltipPlacement } from '@celerofinancas/ui-directives';

@Component({
selector: 'app-tooltip',
standalone: true,
templateUrl: './tooltip.component.html',
styleUrl: './tooltip.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TooltipComponent implements TooltipBase {
// We'll implement the required properties next
}

Step 3: Implement Required Properties

Add the required properties from the TooltipBase interface:

src/app/shared/components/tooltip/tooltip.component.ts
export class TooltipComponent implements TooltipBase {
/**
* The text content to display in the tooltip
*/
@Input()
public text = '';

/**
* Optional template reference for custom tooltip content
*/
@Input()
public tooltipRef?: TemplateRef<any>;

/**
* Maximum width constraint for the tooltip
*/
@Input()
public maxWidth?: string | number;

/**
* Position of the tooltip relative to the trigger element
*/
@Input()
public placement?: TooltipPlacement = 'top';
}

Step 4: Create the Template

Create the HTML template for your tooltip:

src/app/shared/components/tooltip/tooltip.component.html
<div
[class]="'tooltip-container ' + (placement || 'top')"
[style.max-width.px]="maxWidth"
>
<!-- Handle custom template content -->
<ng-container *ngIf="tooltipRef; else defaultContent">
<ng-container *ngTemplateOutlet="tooltipRef"></ng-container>
</ng-container>

<!-- Default text content -->
<ng-template #defaultContent>
<span class="tooltip-text">{{ text }}</span>
</ng-template>
</div>

Step 5: Add Styling

Create the CSS/SCSS styles for your tooltip:

src/app/shared/components/tooltip/tooltip.component.scss
.tooltip-container {
background: #333;
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
position: relative;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);

.tooltip-text {
white-space: nowrap;
font-weight: 500;
}

// Arrow styles for different placements
&.top::before {
content: '';
position: absolute;
top: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-top-color: #333;
}

&.bottom::before {
content: '';
position: absolute;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
border: 6px solid transparent;
border-bottom-color: #333;
}

&.start::before {
content: '';
position: absolute;
top: 50%;
left: 100%;
transform: translateY(-50%);
border: 6px solid transparent;
border-left-color: #333;
}

&.end::before {
content: '';
position: absolute;
top: 50%;
right: 100%;
transform: translateY(-50%);
border: 6px solid transparent;
border-right-color: #333;
}
}

Step 6: Register Your Component with the Token

Configure your custom tooltip component to be used by the directive system:

src/app/configs/tokens.ts
import { TOOLTIP_COMPONENT_TOKEN } from '@celerofinancas/ui-directives';
import { TooltipComponent } from '@shared/components/tooltip/tooltip.component';

export const APPLICATION_TOKENS = [
// Register your custom tooltip component
{ provide: TOOLTIP_COMPONENT_TOKEN, useValue: TooltipComponent },
// ... other tokens
];

Step 7: Provide the Token in Your Application

Add the token to your application's providers:

src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { APPLICATION_TOKENS } from './configs/tokens';

export const appConfig: ApplicationConfig = {
providers: [
// ... other providers
...APPLICATION_TOKENS,
],
};

Step 8: Test Your Component

Now you can use your custom tooltip component with the directive:

example-usage.component.html
<!-- Basic usage -->
<button
[cdsTooltip]="'This is a custom tooltip'"
placement="top"
>
Hover me
</button>

<!-- With different placements -->
<div [cdsTooltip]="'Bottom tooltip'" placement="bottom">Bottom</div>
<div [cdsTooltip]="'Start tooltip'" placement="start">Start</div>
<div [cdsTooltip]="'End tooltip'" placement="end">End</div>

<!-- With max width -->
<span
[cdsTooltip]="'This is a very long tooltip text that will be constrained by max width'"
[maxWidth]="200"
>
Long tooltip
</span>

Advanced Customization

Adding Animation

Enhance your tooltip with animations:

tooltip.component.scss
.tooltip-container {
// ... existing styles

animation: fadeIn 0.2s ease-in-out;

@keyframes fadeIn {
from {
opacity: 0;
transform: scale(0.8);
}
to {
opacity: 1;
transform: scale(1);
}
}
}

Theme Support

Add CSS custom properties for theming:

tooltip.component.scss
.tooltip-container {
background: var(--tooltip-background, #333);
color: var(--tooltip-text-color, white);
border: var(--tooltip-border, none);

// Update arrow colors to use custom properties
&.top::before {
border-top-color: var(--tooltip-background, #333);
}

// ... repeat for other placements
}

Adding Custom Logic

Extend your component with additional functionality:

tooltip.component.ts
export class TooltipComponent implements TooltipBase {
@Input() text = '';
@Input() tooltipRef?: TemplateRef<any>;
@Input() maxWidth?: string | number;
@Input() placement?: TooltipPlacement = 'top';

// Additional custom properties
@Input() showDelay = 0;
@Input() hideDelay = 0;
@Input() theme: 'light' | 'dark' = 'dark';

get containerClasses(): string {
return `tooltip-container ${this.placement} ${this.theme}`;
}
}

Best Practices

1. Accessibility

  • Add ARIA attributes for screen readers
  • Ensure proper keyboard navigation support
  • Use semantic HTML elements

2. Performance

  • Use OnPush change detection strategy
  • Keep animations lightweight
  • Avoid complex calculations in templates

3. Maintainability

  • Follow consistent naming conventions
  • Document your custom properties
  • Write unit tests for your component

4. Design System Integration

  • Use design tokens/CSS custom properties
  • Follow your organization's design guidelines
  • Ensure consistency across different themes

Troubleshooting

Common Issues

  1. Component not appearing: Ensure the token is properly registered and provided
  2. Styling not applied: Check CSS specificity and ensure styles are included
  3. Arrow positioning issues: Verify placement classes and CSS calculations
  4. Animation glitches: Test with different placement positions and screen sizes

Congratulations! You now have a fully functional custom tooltip component that integrates with the @celerofinancas/ui-directives system.