Tooltip

Tooltips appear on demand to explain UI elements, clarify functionality, or provide helpful context without permanently occupying screen space. They automatically position themselves relative to their trigger element.

import {TooltipModule} from "@qualcomm-ui/angular/tooltip"

Overview

The tooltip should be used to provide additional non-essential information. It is linked to an interactive element (the trigger) and will be shown when this element is focused or hovered. Because the tooltip itself can't be focused or tabbed to, it should not contain interactive elements. Only one tooltip can be open at a time.

In general, tooltips should be used sparingly and only contain succinct information. Here are guidelines to help you decide when to use one:

  • When using controls that lack visual labels, like icon buttons.
  • When defining a term or inline item.
  • When additional information may help a user make decisions.
  • When providing more context to an element.

Examples

Simple

The simple API provides a standalone component with built-in layout. The trigger is supplied as a child directive, and the content of the tooltip is the children.

<div q-tooltip>
  <button emphasis="primary" q-button q-tooltip-trigger variant="fill">
    Hover me
  </button>
  Hello World!
</div>

Composite

Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.

<div q-tooltip-root>
  <button emphasis="primary" q-button q-tooltip-trigger variant="fill">
    Hover me
  </button>
  <q-portal>
    <div q-tooltip-positioner>
      <div q-tooltip-content>
        <div q-tooltip-arrow>
          <div q-tooltip-arrow-tip></div>
        </div>
        Hello World!
      </div>
    </div>
  </q-portal>
</div>

Placement

The tooltip's position, relative to the trigger element, can be set using the placement option of the positioning prop. Its default value is top. Change the values in the example below and hover over the select to see the tooltip position change.

import {Component, signal} from "@angular/core"
import {FormsModule} from "@angular/forms"

import {SelectModule} from "@qualcomm-ui/angular/select"
import {TooltipModule} from "@qualcomm-ui/angular/tooltip"
import {PortalDirective} from "@qualcomm-ui/angular-core/portal"
import {selectCollection} from "@qualcomm-ui/core/select"
import type {Placement} from "@qualcomm-ui/dom/floating-ui"

@Component({
  imports: [TooltipModule, SelectModule, FormsModule, PortalDirective],
  selector: "tooltip-placement",
  template: `
    <div class="flex flex-col">
      <div q-tooltip-root [positioning]="{placement: placement()[0]}">
        <div
          class="w-48"
          q-select-root
          [collection]="collection()"
          [(ngModel)]="placement"
        >
          <span q-tooltip-trigger>
            <button q-select-trigger>
              <span q-select-value-text></span>
              <span q-select-indicator></span>
            </button>
          </span>
          <select q-select-hidden-select></select>
          <ng-template qPortal>
            <div q-select-positioner>
              <div q-select-content>
                <q-select-items />
              </div>
            </div>
          </ng-template>
        </div>
        <q-tooltip-floating-portal>Hello World!</q-tooltip-floating-portal>
      </div>
    </div>
  `,
})
export class TooltipPlacementDemo {
  readonly placement = signal<Placement[]>(["top"])

  readonly collection = signal(
    selectCollection({
      items: [
        "top",
        "bottom",
        "right",
        "left",
        "top-end",
        "bottom-end",
        "right-end",
        "left-end",
        "top-start",
        "bottom-start",
        "right-start",
        "left-start",
      ],
    }),
  )
}

Close On Click / Escape

By default, the tooltip will close when the Escape key is pressed or a click is detected. You can customize this behavior using the closeOnClick and closeOnEscape props.

<div closeOnClick="false" closeOnEscape="false" q-tooltip>
  <button emphasis="primary" q-button q-tooltip-trigger variant="fill">
    Hover me
  </button>
  Hello World!
</div>

Controlled Visibility

Set the initial visibility using the defaultOpen prop, or use open and openChanged to control the visibility manually. These props follow our controlled state pattern.

the tooltip is closed
import {Component, signal} from "@angular/core"

import {ButtonModule} from "@qualcomm-ui/angular/button"
import {TooltipModule} from "@qualcomm-ui/angular/tooltip"

@Component({
  imports: [TooltipModule, ButtonModule],
  selector: "tooltip-controlled-state-demo",
  template: `
    <div class="flex flex-col items-center gap-4">
      <div q-tooltip [open]="open()" (openChanged)="handleOpenChange($event)">
        <button emphasis="primary" q-button q-tooltip-trigger variant="fill">
          Hover me
        </button>
        Hello World!
      </div>

      <output class="text-neutral-primary block">
        the tooltip is {{ open() ? "open" : "closed" }}
      </output>
    </div>
  `,
})
export class TooltipControlledStateDemo {
  readonly open = signal(false)

  handleOpenChange(open: boolean): void {
    this.open.set(open)
  }
}

Disabled

You can disable the tooltip by using the disabled prop.

<div q-tooltip [disabled]="disabled()">
  <button emphasis="primary" q-button q-tooltip-trigger variant="fill">
    Hover me
  </button>
  Hello World!
</div>

Shortcuts

<q-tooltip-floating-portal>

A helper component that combines the portal, positioner, content, and arrow components. This shortcut is equivalent to:

<q-portal>
  <div q-tooltip-positioner>
    <div q-tooltip-content>
      <div q-tooltip-arrow>
        <div q-tooltip-arrow-tip></div>
      </div>
      <ng-content />
    </div>
  </div>
</q-portal>

API

q-tooltip

The simple tooltip extends the q-tooltip-root directive with the following props:

PropType
If true, the tooltip will not be rendered in a DOM portal.
boolean
Whether to hide the arrow.
boolean
Type
boolean
Description
If true, the tooltip will not be rendered in a DOM portal.
Type
boolean
Description
Whether to hide the arrow.

Composite API

q-tooltip-root

PropType
Whether the tooltip should close when the trigger is clicked.
boolean
Whether to close the tooltip when the escape key is pressed.
boolean
The document's text/writing direction.
'ltr' | 'rtl'
The disabled state of the tooltip
boolean
HTML id attribute. If omitted, a unique identifier will be generated for accessibility.)
string
The open state of the tooltip.
boolean
The user provided options used to position the popover content
Function called when the tooltip is opened/closed.
boolean
Type
boolean
Description
Whether the tooltip should close when the trigger is clicked.
Type
boolean
Description
Whether to close the tooltip when the escape key is pressed.
Type
'ltr' | 'rtl'
Description
The document's text/writing direction.
Type
boolean
Description
The disabled state of the tooltip
Type
string
Description
HTML id attribute. If omitted, a unique identifier will be generated for accessibility.)
Type
boolean
Description
The open state of the tooltip.
Description
The user provided options used to position the popover content
Type
boolean
Description
Function called when the tooltip is opened/closed.

q-tooltip-trigger

PropType
id attribute. If omitted, a unique identifier will be generated for accessibility.)
string
Type
string
Description
id attribute. If omitted, a unique identifier will be generated for accessibility.)

q-tooltip-positioner

PropType
id attribute. If omitted, a unique identifier will be generated for accessibility.)
string
Type
string
Description
id attribute. If omitted, a unique identifier will be generated for accessibility.)

q-tooltip-content

PropType
id attribute. If omitted, a unique identifier will be generated for accessibility.)
string
Type
string
Description
id attribute. If omitted, a unique identifier will be generated for accessibility.)

q-tooltip-arrow

PropType
id attribute. If omitted, a unique identifier will be generated for accessibility.)
string
Type
string
Description
id attribute. If omitted, a unique identifier will be generated for accessibility.)

q-tooltip-arrow-tip

TooltipPositioningOptions

PropTypeDefault
The minimum padding between the arrow and the floating element's corner.
number
10
The overflow boundary of the reference element
    () =>
    | 'clippingAncestors'
    | Element
    | Array<Element>
    | {
    height: number
    width: number
    x: number
    y: number
    }
    Whether the popover should fit the viewport.
    boolean
    Whether to flip the placement when the floating element overflows the boundary.
    | boolean
    | Array<
    | 'bottom'
    | 'bottom-end'
    | 'bottom-start'
    | 'left'
    | 'left-end'
    | 'left-start'
    | 'right'
    | 'right-end'
    | 'right-start'
    | 'top'
    | 'top-end'
    | 'top-start'
    >
    true
    
    Function that returns the anchor rect
      (
      element:
      | HTMLElement
      | VirtualElement,
      ) => {
      height?: number
      width?: number
      x?: number
      y?: number
      }
      The main axis offset or gap between the reference and floating element
      number
      8
      
      Whether the popover should be hidden when the reference element is detached
      boolean
      Options to activate auto-update listeners
      | boolean
      | {
      ancestorResize?: boolean
      ancestorScroll?: boolean
      animationFrame?: boolean
      elementResize?: boolean
      layoutShift?: boolean
      }
      true
      
      The offset of the floating element
      {
      crossAxis?: number
      mainAxis?: number
      }
      Function called when the placement is computed
        (
        data: ComputePositionReturn,
        ) => void
        Function called when the floating element is positioned or not
          (data: {
          placed: boolean
          }) => void
          The virtual padding around the viewport edges to check for overflow
          number
          Whether the floating element can overlap the reference element
          boolean
          false
          
          The initial placement of the floating element
          | 'bottom'
          | 'bottom-end'
          | 'bottom-start'
          | 'left'
          | 'left-end'
          | 'left-start'
          | 'right'
          | 'right-end'
          | 'right-start'
          | 'top'
          | 'top-end'
          | 'top-start'
          'top'
          
          Whether to make the floating element same width as the reference element
          boolean
          The secondary axis offset or gap between the reference and floating elements
          number
          Whether the popover should slide when it overflows.
          boolean
          The strategy to use for positioning
          | 'absolute'
          | 'fixed'
          'absolute'
          
          A callback that will be called when the popover needs to calculate its position.
            (data: {
            updatePosition: () => Promise<void>
            }) => void | Promise<void>
            Type
            number
            Description
            The minimum padding between the arrow and the floating element's corner.
            Type
            () =>
            | 'clippingAncestors'
            | Element
            | Array<Element>
            | {
            height: number
            width: number
            x: number
            y: number
            }
            Description
            The overflow boundary of the reference element
              Type
              boolean
              Description
              Whether the popover should fit the viewport.
              Type
              | boolean
              | Array<
              | 'bottom'
              | 'bottom-end'
              | 'bottom-start'
              | 'left'
              | 'left-end'
              | 'left-start'
              | 'right'
              | 'right-end'
              | 'right-start'
              | 'top'
              | 'top-end'
              | 'top-start'
              >
              Description
              Whether to flip the placement when the floating element overflows the boundary.
              Type
              (
              element:
              | HTMLElement
              | VirtualElement,
              ) => {
              height?: number
              width?: number
              x?: number
              y?: number
              }
              Description
              Function that returns the anchor rect
                Type
                number
                Description
                The main axis offset or gap between the reference and floating element
                Type
                boolean
                Description
                Whether the popover should be hidden when the reference element is detached
                Type
                | boolean
                | {
                ancestorResize?: boolean
                ancestorScroll?: boolean
                animationFrame?: boolean
                elementResize?: boolean
                layoutShift?: boolean
                }
                Description
                Options to activate auto-update listeners
                Type
                {
                crossAxis?: number
                mainAxis?: number
                }
                Description
                The offset of the floating element
                Type
                (
                data: ComputePositionReturn,
                ) => void
                Description
                Function called when the placement is computed
                  Type
                  (data: {
                  placed: boolean
                  }) => void
                  Description
                  Function called when the floating element is positioned or not
                    Type
                    number
                    Description
                    The virtual padding around the viewport edges to check for overflow
                    Type
                    boolean
                    Description
                    Whether the floating element can overlap the reference element
                    Type
                    | 'bottom'
                    | 'bottom-end'
                    | 'bottom-start'
                    | 'left'
                    | 'left-end'
                    | 'left-start'
                    | 'right'
                    | 'right-end'
                    | 'right-start'
                    | 'top'
                    | 'top-end'
                    | 'top-start'
                    Description
                    The initial placement of the floating element
                    Type
                    boolean
                    Description
                    Whether to make the floating element same width as the reference element
                    Type
                    number
                    Description
                    The secondary axis offset or gap between the reference and floating elements
                    Type
                    boolean
                    Description
                    Whether the popover should slide when it overflows.
                    Type
                    | 'absolute'
                    | 'fixed'
                    Description
                    The strategy to use for positioning
                    Type
                    (data: {
                    updatePosition: () => Promise<void>
                    }) => void | Promise<void>
                    Description
                    A callback that will be called when the popover needs to calculate its position.