Skip to content
Docs

Tooltip

A popup that displays information related to an element when it receives focus or is hovered.

A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.

<Tooltip.provider delay_duration={100}>
  <Tooltip.root
    id="tooltip-primitive"
    open_delay={100}
    close_delay={0}
  >
    <Tooltip.trigger
      id="tooltip-trigger"
      content_id="tooltip-content"
      class="DemoIconButton"
      aria-label="Add to library"
    >
      <svg
        width="15"
        height="15"
        viewBox="0 0 15 15"
        fill="none"
        aria-hidden="true"
      >
        <path
          d="M7.5 1v13M1 7.5h13"
          stroke="currentColor"
          stroke-width="1.5"
          stroke-linecap="round"
        />
      </svg>
    </Tooltip.trigger>
    <Tooltip.content
      id="tooltip-content"
      class="DemoTooltipContent"
      side_offset={5}
    >
      Add to library <Tooltip.arrow class="DemoTooltipArrow" />
    </Tooltip.content>
  </Tooltip.root>
</Tooltip.provider>
Provider to control display delay globally.
Opens when the trigger is focused or hovered.
Closes when the trigger is activated or when pressing Escape.
Supports custom timings.

Anatomy

Import all parts and piece them together.

<Tooltip.provider>
  <Tooltip.root>
    <Tooltip.trigger />
    <Tooltip.content>
      <Tooltip.arrow />
    </Tooltip.content>
  </Tooltip.root>
</Tooltip.provider>

Anatomy

Provider
Wraps your app to provide global delay defaults.
Root
Contains all the parts of a tooltip.
Trigger
The button that toggles the tooltip.
Portal
Optional portal for content.
Content
The component that pops out when the tooltip is open.
Arrow
An optional arrow element.

API Reference

Provider

Wraps your app to provide global functionality to your tooltips.

Prop Type Default Description
delay_duration integer 700 Default open delay in ms for tooltips in this provider.
disable_hoverable_content boolean false When true, tooltip content is not hoverable.
skip_delay_duration integer 300 Delay when moving between tooltips.
delay_duration Default open delay in ms for tooltips in this provider.
Type integer Default 700
disable_hoverable_content When true, tooltip content is not hoverable.
Type boolean Default false
skip_delay_duration Delay when moving between tooltips.
Type integer Default 300

Root

Contains all the parts of a tooltip.

Use open with on_open_change for controlled open state in LiveView:

<Tooltip.root id="info-tooltip" open={@open} on_open_change="tooltip_open_change">
  …
</Tooltip.root>
def handle_event("tooltip_open_change", %{"open" => open}, socket) do
  {:noreply, assign(socket, :open, open)}
end
Prop Type Default Description
close_delay integer 0 Delay before closing (ms).
default_open boolean false Initial open state when uncontrolled.
id string Unique id for the tooltip root.
on_open_change string nil LiveView event name pushed when open state changes.
open boolean false Controlled open state.
open_delay integer nil Override provider open delay (ms).
close_delay Delay before closing (ms).
Type integer Default 0
default_open Initial open state when uncontrolled.
Type boolean Default false
id Unique id for the tooltip root.
Type string Default
on_open_change LiveView event name pushed when open state changes.
Type string Default nil
open Controlled open state.
Type boolean Default false
open_delay Override provider open delay (ms).
Type integer Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the tooltip is open.

Trigger

The button that toggles the tooltip. By default, the Tooltip.content will position itself against the trigger.

Prop Type Default Description
as string "button"
content_id string nil
id string nil
as
Type string Default "button"
content_id
Type string Default nil
id
Type string Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the tooltip is open.

Portal

When used, portals the content part into the target (default body).

Prop Type Default Description
class any nil
container string "div"
id string
target string "body"
class
Type any Default nil
container
Type string Default "div"
id
Type string Default
target
Type string Default "body"

Content

The component that pops out when the tooltip is open.

Prop Type Default Description
align string "center"
id string nil
side string "top"
side_offset integer 4
style string nil
align
Type string Default "center"
id
Type string Default nil
side
Type string Default "top"
side_offset
Type integer Default 4
style
Type string Default nil

Data attributes

Attribute Values Description
[data-state] closed | delayed-open Reflects whether the tooltip is open. Content uses `delayed-open` when visible.
[data-side] top | right | bottom | left Preferred side relative to the trigger.
[data-align] start | center | end Alignment along the side.

Arrow

An optional arrow element to render alongside the tooltip. This can be used to help visually link the trigger with the Tooltip.content. Must be rendered inside Tooltip.content.

Prop Type Default Description
height integer 5
id string nil
width integer 10
height
Type integer Default 5
id
Type string Default nil
width
Type integer Default 10

Examples

Configure globally

Use the Provider to control delay_duration and skip_delay_duration globally.

<Tooltip.provider delay_duration={800} skip_delay_duration={500}>
  <Tooltip.root id="tooltip-a">
    <Tooltip.trigger id="tooltip-a-trigger" content_id="tooltip-a-content">…</Tooltip.trigger>
    <Tooltip.content id="tooltip-a-content">…</Tooltip.content>
  </Tooltip.root>
  <Tooltip.root id="tooltip-b">
    <Tooltip.trigger id="tooltip-b-trigger" content_id="tooltip-b-content">…</Tooltip.trigger>
    <Tooltip.content id="tooltip-b-content">…</Tooltip.content>
  </Tooltip.root>
</Tooltip.provider>

Show instantly

Use the open_delay prop to control the time it takes for the tooltip to open.

<Tooltip.root id="instant-tooltip" open_delay={0}>
  <Tooltip.trigger id="instant-tooltip-trigger" content_id="instant-tooltip-content">…</Tooltip.trigger>
  <Tooltip.content id="instant-tooltip-content">…</Tooltip.content>
</Tooltip.root>

Constrain the content size

You may want to constrain the width of the content. Use standard CSS on the content element:

.DemoTooltipContent {
  max-width: 20ch;
}

Collision-aware animations

Essence exposes data-side and data-align attributes on content. Their values reflect placement at runtime. Use them to create direction-aware animations:

<Tooltip.content id="animated-tooltip-content" class="DemoTooltipContent" side_offset={5}>
  …
</Tooltip.content>
.DemoTooltipContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.DemoTooltipContent[data-side="top"] {
  animation-name: slideUp;
}
.DemoTooltipContent[data-side="bottom"] {
  animation-name: slideDown;
}

@keyframes slideDown {
  from { opacity: 0; transform: translateY(-10px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

Accessibility

Adheres to the Tooltip WAI-ARIA design pattern.

Keyboard Interactions

Keyboard Interactions

Key Description
Tab Opens/closes the tooltip without delay.
Space If open, closes the tooltip without delay.
Enter If open, closes the tooltip without delay.
Escape If open, closes the tooltip without delay.

Custom APIs

Create your own API by abstracting the primitive parts into your own component.

Usage

<.info_tooltip label="Add to library">
  <.icon_button aria-label="Add to library">+</.icon_button>
</.info_tooltip>

Implementation

def info_tooltip(assigns) do
  ~H"""
  <Tooltip.root id={@id} open_delay={@open_delay}>
    <Tooltip.trigger id={"#{@id}-trigger"} content_id={"#{@id}-content"} as="div">
      {render_slot(@inner_block)}
    </Tooltip.trigger>
    <Tooltip.content id={"#{@id}-content"} class="DemoTooltipContent" side_offset={5}>
      {@label}
      <Tooltip.arrow class="DemoTooltipArrow" />
    </Tooltip.content>
  </Tooltip.root>
  """
end