Tooltip
Displays informative text when users hover over or focus on an element. Apply the avTooltip directive to any host — no compound wrapper required. See also Popover for interactive anchored panels.
Import
import { AvTooltipDirective } from '@avesra/angular';Usage
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-basic-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<button av-button variant="secondary" avTooltip="Tooltip content">Hover me</button>`,
})
export class TooltipBasicDemo {}Anatomy
Tooltip is a directive-only API. The overlay (panel, text, and arrow) is created at runtime — no Trigger / Content / Arrow markup in your template.
<button
av-button
variant="secondary"
avTooltip="Helpful information about this element"
>
Hover for tooltip
</button>
<!-- Overlay is created at runtime with .av-tooltip, .av-tooltip__text, and [data-slot="overlay-arrow"] -->Placement
Use tooltip-position for the preferred side — top (default), bottom, left, or right. The directive flips when the preferred side would overflow the viewport.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-positions-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="grid max-w-md grid-cols-3 gap-4">
<div></div>
<button
av-button
class="w-full"
size="sm"
variant="tertiary"
avTooltip="Top placement"
tooltip-position="top"
>
Top
</button>
<div></div>
<button
av-button
class="w-full"
size="sm"
variant="tertiary"
avTooltip="Left placement"
tooltip-position="left"
>
Left
</button>
<div class="flex items-center justify-center text-xs text-muted">Hover</div>
<button
av-button
class="w-full"
size="sm"
variant="tertiary"
avTooltip="Right placement"
tooltip-position="right"
>
Right
</button>
<div></div>
<button
av-button
class="w-full"
size="sm"
variant="tertiary"
avTooltip="Bottom placement"
tooltip-position="bottom"
>
Bottom
</button>
<div></div>
</div>`,
})
export class TooltipPositionsDemo {}With Arrow
Avesra always renders an arrow on the overlay ([data-slot="overlay-arrow"]). There is no showArrow toggle — placement rotates the arrow automatically.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-basic-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<button av-button variant="secondary" avTooltip="Tooltip content">Hover me</button>`,
})
export class TooltipBasicDemo {}Custom Triggers
Attach avTooltip to any hoverable or focusable element — icon buttons, avatars, chips, or custom hosts. Provide aria-label when the trigger has no visible text.
import { Component } from '@angular/core';
import { AvAvatarImports, AvChipImports, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-custom-trigger-demo',
imports: [AvAvatarImports, AvChipImports, AvTooltipDirective],
template: `<div class="flex flex-wrap items-center gap-6">
<span
av-avatar
size="sm"
[avTooltip]="avatarTooltip"
aria-label="User avatar"
tabindex="0"
[show-delay]="0"
>
<img av-avatar-image alt="Jane Doe" [src]="profileAvatarUrl" />
<span av-avatar-fallback>JD</span>
</span>
<span
av-chip
color="success"
variant="secondary"
[avTooltip]="statusTooltip"
aria-label="Status chip"
tabindex="0"
[show-delay]="0"
>
<svg class="size-3" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
<path
d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13Zm3.78 4.72-4.25 4.25a.75.75 0 0 1-1.06 0l-2-2a.75.75 0 1 1 1.06-1.06l1.47 1.47 3.72-3.72a.75.75 0 1 1 1.06 1.06Z"
/>
</svg>
<span av-chip-label>Active</span>
</span>
<div
class="inline-flex cursor-default rounded-full bg-accent-soft p-2 text-accent-soft-foreground"
[avTooltip]="helpTooltip"
aria-label="Info icon"
tabindex="0"
tooltip-position="top"
[show-delay]="0"
>
<svg
class="size-4"
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
stroke-width="1.5"
aria-hidden="true"
>
<circle cx="8" cy="8" r="6.25" />
<path d="M8 7.25v4" stroke-linecap="round" />
<circle cx="8" cy="5.25" r="0.75" fill="currentColor" stroke="none" />
</svg>
</div>
</div>
<ng-template #avatarTooltip>
<div class="flex flex-col gap-0 py-1">
<p class="font-semibold">Jane Doe</p>
<p class="text-xs text-muted">jane@example.com</p>
</div>
</ng-template>
<ng-template #statusTooltip>
<div class="flex items-center gap-1.5">
<span class="relative flex size-2">
<span
class="absolute inline-flex h-full w-full animate-ping rounded-full bg-success opacity-75"
></span>
<span class="relative inline-flex size-2 rounded-full bg-success"></span>
</span>
<p>Jane is currently online</p>
</div>
</ng-template>
<ng-template #helpTooltip>
<div class="max-w-xs px-1 py-1.5">
<p class="mb-1 font-semibold">Help Information</p>
<p class="text-sm text-muted">
This is a helpful tooltip with more detailed information about this feature.
</p>
</div>
</ng-template>`,
})
export class TooltipCustomTriggerDemo {
readonly profileAvatarUrl = '/images/avatars/avatar-man-glasses-salt-pepper.png';
}Events
Control how the tooltip opens with tooltip-event: hover (default), focus, or both.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-events-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap gap-3">
<button av-button variant="outline" avTooltip="Opens on hover" tooltip-event="hover">
Hover
</button>
<input
class="w-44 rounded-xl border border-border bg-field px-3 py-2 text-sm text-foreground outline-none focus-visible:ring-2 focus-visible:ring-focus"
type="text"
placeholder="Focus me"
avTooltip="Opens on focus"
tooltip-event="focus"
/>
<input
class="w-44 rounded-xl border border-border bg-field px-3 py-2 text-sm text-foreground outline-none focus-visible:ring-2 focus-visible:ring-focus"
type="text"
placeholder="Hover or focus"
avTooltip="Opens on hover and focus"
tooltip-event="both"
/>
</div>`,
})
export class TooltipEventsDemo {}Delays
Tune timing with show-delay (default 700 ms) and hide-delay (default 0 ms).
import { Component } from '@angular/core';
import { AV_TOOLTIP_SHOW_DELAY_DEFAULT, AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-delays-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap gap-3">
<button av-button variant="outline" avTooltip="Shows after 150ms" [show-delay]="150">
Fast show (150ms)
</button>
<button av-button variant="outline" avTooltip="Uses default show delay" [show-delay]="showDelayDefault">
Default show ({{ showDelayDefault }}ms)
</button>
<button
av-button
variant="outline"
avTooltip="Stays visible 500ms after leave"
[show-delay]="0"
[hide-delay]="500"
>
Slow hide (500ms)
</button>
<button
av-button
variant="outline"
avTooltip="1s show, 300ms hide"
[show-delay]="1000"
[hide-delay]="300"
>
Both delays
</button>
</div>`,
})
export class TooltipDelaysDemo {
readonly showDelayDefault = AV_TOOLTIP_SHOW_DELAY_DEFAULT;
}Auto Hide
When auto-hide is true (default), the tooltip dismisses when the pointer leaves the trigger. Set [auto-hide]="false" to keep it open while hovering the panel.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-auto-hide-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap gap-3">
<button
av-button
variant="secondary"
avTooltip="Default — hides when pointer leaves trigger"
[auto-hide]="true"
>
auto-hide: true
</button>
<button
av-button
variant="secondary"
avTooltip="Move pointer onto this tooltip before it closes"
[auto-hide]="false"
[show-delay]="0"
>
auto-hide: false
</button>
</div>`,
})
export class TooltipAutoHideDemo {}Hide on Escape
Pressing Escape dismisses a visible tooltip by default. Set [hide-on-escape]="false" to disable that behavior.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-hide-on-escape-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap gap-3">
<button av-button variant="outline" avTooltip="Press Escape to close" [show-delay]="0">
hide-on-escape: true
</button>
<button
av-button
variant="outline"
avTooltip="Escape will not close this tooltip"
[show-delay]="0"
[hide-on-escape]="false"
>
hide-on-escape: false
</button>
</div>`,
})
export class TooltipHideOnEscapeDemo {}Position Offset
Nudge placement with position-top and position-left after the base alignment calculation.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-position-offset-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap gap-3">
<button
av-button
variant="tertiary"
avTooltip="Shifted 12px right and 8px down"
tooltip-position="top"
[position-left]="12"
[position-top]="8"
[show-delay]="0"
>
Custom offset
</button>
<button
av-button
variant="tertiary"
avTooltip="Baseline top placement"
tooltip-position="top"
[show-delay]="0"
>
No offset
</button>
</div>`,
})
export class TooltipPositionOffsetDemo {}Template Content
Bind [avTooltip] to an ng-template for formatted or multi-line content.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-template-content-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<button
av-button
variant="primary"
[avTooltip]="richTooltip"
tooltip-position="bottom"
[show-delay]="0"
>
Rich tooltip
</button>
<ng-template #richTooltip>
<div class="flex flex-col gap-1">
<span class="font-medium">Avesra Tooltip</span>
<span class="text-muted">TemplateRef with custom layout</span>
</div>
</ng-template>`,
})
export class TooltipTemplateContentDemo {}Dynamic Content
Tooltip text can be driven by component state — the overlay reflects the latest content on the next show cycle.
import { Component, signal } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-dynamic-content-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex flex-wrap items-center gap-3">
<button
av-button
variant="secondary"
[avTooltip]="dynamicLabel()"
[show-delay]="0"
>
Dynamic trigger
</button>
<button av-button variant="outline" (click)="updateDynamicTooltip()">
Update tooltip text
</button>
<span class="text-sm text-muted">Clicks: {{ clicks() }}</span>
</div>`,
})
export class TooltipDynamicContentDemo {
readonly dynamicLabel = signal('Hover to see dynamic content');
readonly clicks = signal(0);
updateDynamicTooltip(): void {
this.clicks.update((value) => value + 1);
this.dynamicLabel.set(`Clicked ${this.clicks()} time(s)`);
}
}Long Text
Long labels wrap within the panel's max-w-xs constraint.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-long-text-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<button
av-button
variant="outline"
avTooltip="This is a longer tooltip message that demonstrates wrapping behavior when the advisory text exceeds the maximum width of the overlay surface."
[show-delay]="0"
>
Long tooltip
</button>`,
})
export class TooltipLongTextDemo {}Disabled
Set [tooltip-disabled]="true" to suppress the tooltip without removing the directive.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-disabled-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<button av-button variant="secondary" avTooltip="You should not see this" tooltip-disabled>
Disabled tooltip
</button>`,
})
export class TooltipDisabledDemo {}Viewport Flip
When the preferred position would clip outside the viewport, the tooltip tries fallback sides automatically.
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-viewport-flip-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `<div class="flex justify-end">
<button
av-button
size="sm"
variant="tertiary"
avTooltip="Requested right, may flip near the viewport edge"
tooltip-position="right"
[show-delay]="0"
>
Near right edge
</button>
</div>`,
})
export class TooltipViewportFlipDemo {}Customization
Tailwind CSS
Style the trigger host with utilities. Overlay appearance is customized via Global CSS on .av-tooltip (there is no content component className).
import { Component } from '@angular/core';
import { AvButtonComponent, AvTooltipDirective } from '@avesra/angular';
@Component({
selector: 'app-tooltip-custom-styles-demo',
imports: [AvButtonComponent, AvTooltipDirective],
template: `
<button
av-button
class="cursor-help"
variant="secondary"
avTooltip="Copied to clipboard"
[show-delay]="0"
>
Share link
</button>
`,
})
export class TooltipCustomStylesDemo {}Global CSS
To customize Tooltip classes, use the @layer components directive.
@layer components {
.av-tooltip {
@apply rounded-xl shadow-lg;
}
.av-tooltip__text {
@apply text-xs;
}
}Styling Reference
Avesra follows the BEM methodology so variants and states stay reusable and easy to customize.
CSS Classes
Base Classes
.av-tooltip— Base tooltip overlay with animations.av-tooltip__text— Content wrapper above the arrow[data-slot="overlay-arrow"]— Arrow SVG
Interactive States
- Entering:
[data-entering]— applied during appearance - Exiting:
[data-exiting]— applied during disappearance - Placement:
[data-placement="*"]— drives arrow rotation and slide direction
API Reference
All options are inputs on the [avTooltip] directive host. The overlay is not a separate Angular component — there are no Trigger / Content / Arrow APIs.
| Prop | Type | Default | Description |
|---|---|---|---|
avTooltip | string | TemplateRef<unknown> | — | Tooltip content. Plain text or a template ([avTooltip]). |
tooltip-position | 'top' | 'bottom' | 'left' | 'right' | 'top' | Preferred tooltip position ([avTooltip]). |
tooltip-event | 'hover' | 'focus' | 'both' | 'hover' | Event that opens the tooltip ([avTooltip]). |
show-delay | number | 700 | Delay before showing the tooltip in milliseconds ([avTooltip]). |
hide-delay | number | 0 | Delay before hiding the tooltip in milliseconds ([avTooltip]). |
tooltip-disabled | boolean | false | Disables the tooltip ([avTooltip]). |
auto-hide | boolean | true | Hides the tooltip when the pointer leaves the trigger ([avTooltip]). |
hide-on-escape | boolean | true | Hides the tooltip when Escape is pressed ([avTooltip]). |
position-top | number | 0 | Additional vertical offset in pixels ([avTooltip]). |
position-left | number | 0 | Additional horizontal offset in pixels ([avTooltip]). |
Prefer concise labels; use Popover when content requires interaction. While visible, the trigger receives aria-describedby pointing at the tooltip.