Skip to content

fix(tooltip): destroy tooltip instance on component removal#4382

Merged
imorland merged 2 commits into
2.xfrom
fix/tooltip-orphaned-on-remove
Feb 21, 2026
Merged

fix(tooltip): destroy tooltip instance on component removal#4382
imorland merged 2 commits into
2.xfrom
fix/tooltip-orphaned-on-remove

Conversation

@imorland

Copy link
Copy Markdown
Member

Problem

When the container prop is set to "body" (or any element other than the trigger's natural parent), Bootstrap appends the tooltip's DOM node directly to that container rather than adjacent to the trigger element.

When Mithril subsequently removes the trigger element from the DOM — for example, when the notification dropdown is closed — Bootstrap is never informed. The tooltip DOM node is left stranded in <body>, remains visible on screen, and cannot be dismissed. The tooltip stays there permanently until the page is reloaded.

This was introduced as a regression by #4375, which correctly added container="body" to the notification list tooltips to fix their positioning inside the overflow-clipped dropdown. The positioning fix works, but exposed the missing cleanup.

Without container, Bootstrap places the tooltip adjacent to the trigger element in the normal DOM tree; it is removed as part of Mithril's standard DOM cleanup and the problem does not occur.

Root cause

Tooltip.tsx had no onremove lifecycle hook. The Bootstrap tooltip instance was never explicitly destroyed when the Mithril component was removed.

Fix

Add an onremove hook that calls tooltip('destroy') on the child DOM node before Mithril removes it. This is identical to the destroy call already used in recreateTooltip() when the tooltip text changes, so the approach is consistent with the existing pattern in this component.

Impact

  • Fixes the stuck/orphaned tooltip on the notification list buttons (mark all as read, delete all)
  • Correctly cleans up Bootstrap tooltip instances for all Tooltip usages on removal, not just container="body" — this is the right behaviour regardless
  • No behaviour change for the common case where container is not set, since Bootstrap already handles cleanup naturally in that case

Testing

  1. Open the notification dropdown
  2. Hover over the "mark all as read" or "delete all" button — tooltip appears correctly
  3. Close the notification dropdown
  4. Confirm the tooltip does not remain on screen after the dropdown closes

When `container` is set to `"body"` (or any element other than the
trigger's natural parent), Bootstrap appends the tooltip DOM node
directly to that container element rather than adjacent to the trigger.

When Mithril subsequently removes the trigger element from the DOM
(e.g. closing the notification dropdown), Bootstrap is never informed
and the tooltip DOM node is left stranded in the container — visible
forever, impossible to dismiss.

Without `container`, Bootstrap places the tooltip adjacent to the
trigger element; it is removed as part of normal DOM cleanup and the
issue does not manifest.

The fix adds an `onremove` lifecycle hook that calls `tooltip('destroy')`
on the child DOM node before Mithril removes it. This is identical to
the destroy call already used in `recreateTooltip()` when the tooltip
text changes, so the approach is consistent with the existing pattern.

Fixes the regression introduced by #4375 (adding `container="body"` to
the notification list tooltips to fix positioning inside the
overflow-clipped dropdown).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@imorland imorland requested a review from a team as a code owner February 21, 2026 19:37
@imorland imorland added this to the 2.0.0-beta.7 milestone Feb 21, 2026
imorland added a commit that referenced this pull request Feb 21, 2026
@imorland imorland merged commit 9a87082 into 2.x Feb 21, 2026
35 checks passed
@imorland imorland deleted the fix/tooltip-orphaned-on-remove branch February 21, 2026 19:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant