FAILURE MAP
← Case archive

FA-8171 / Disclosure widgets / Open access

Tooltip trigger and dismissal: Blur hides a tooltip that remains pointer-hovered · case 01

Blur hides a tooltip that remains pointer-hovered.

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The blur operation uses `if event == 'blur': return False` where the contract requires `if event == 'blur': return bool(hovered)`.

VERIFIED REPAIR

Implement the blur operation as `if event == 'blur': return bool(hovered)`.

Unsuccessful approach: Always keeping it open leaves abandoned tooltips visible.

Case contract

Disabled triggers hide content; Escape dismisses regardless of trigger state; focus/enter open; blur and leave preserve the other active trigger.

Why this case matters

A deterministic model of tooltip trigger and dismissal; this isolates one interface invariant without requiring a browser.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(state, event, focused, hovered, disabled):
    if disabled: return False
    if event == 'escape': return False
    if event == 'focus': return True
    if event == 'enter': return True
    if event == 'blur': return False
    if event == 'leave': return bool(focused)
    return state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disable', solve(True, 'none', False, False, True), False)
check('escape', solve(True, 'escape', True, True, False), False)
check('focus', solve(False, 'focus', True, False, False), True)
check('blur hovered', solve(True, 'blur', False, True, False), True)
check('blur abandoned', solve(True, 'blur', False, False, False), False)
check('leave focused', solve(True, 'leave', True, False, False), True)
check('leave abandoned', solve(True, 'leave', False, False, False), False)
check('parameterized remaining trigger', solve(True, 'blur', False, bool(N%2), False), bool(N%2))
for repetition in range(N):
    check('repeat leave abandoned', solve(True, 'leave', False, False, False), False)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
disableFalseFalsePassed
escapeFalseFalsePassed
focusTrueTruePassed
blur hoveredFalseTrueFailed
blur abandonedFalseFalsePassed
leave focusedTrueTruePassed
leave abandonedFalseFalsePassed
parameterized remaining triggerFalseTrueFailed
repeat leave abandonedFalseFalsePassed

SHA-256 / b260936489aea2c6f7f09071a4f1e0add65e1d681ebaf07df1d71f95aac88f71

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(state, event, focused, hovered, disabled):
    if disabled: return False
    if event == 'escape': return False
    if event == 'focus': return True
    if event == 'enter': return True
    if event == 'blur': return True
    if event == 'leave': return bool(focused)
    return state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disable', solve(True, 'none', False, False, True), False)
check('escape', solve(True, 'escape', True, True, False), False)
check('focus', solve(False, 'focus', True, False, False), True)
check('blur hovered', solve(True, 'blur', False, True, False), True)
check('blur abandoned', solve(True, 'blur', False, False, False), False)
check('leave focused', solve(True, 'leave', True, False, False), True)
check('leave abandoned', solve(True, 'leave', False, False, False), False)
check('parameterized remaining trigger', solve(True, 'blur', False, bool(N%2), False), bool(N%2))
for repetition in range(N):
    check('repeat leave abandoned', solve(True, 'leave', False, False, False), False)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
disableFalseFalsePassed
escapeFalseFalsePassed
focusTrueTruePassed
blur hoveredTrueTruePassed
blur abandonedTrueFalseFailed
leave focusedTrueTruePassed
leave abandonedFalseFalsePassed
parameterized remaining triggerTrueTruePassed
repeat leave abandonedFalseFalsePassed

SHA-256 / 7270c671b17ac8f21bdebb3b62b8542e1b94fc033c65b9a4beaa4e7f91146a98

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(state, event, focused, hovered, disabled):
    if disabled: return False
    if event == 'escape': return False
    if event == 'focus': return True
    if event == 'enter': return True
    if event == 'blur': return bool(hovered)
    if event == 'leave': return bool(focused)
    return state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('disable', solve(True, 'none', False, False, True), False)
check('escape', solve(True, 'escape', True, True, False), False)
check('focus', solve(False, 'focus', True, False, False), True)
check('blur hovered', solve(True, 'blur', False, True, False), True)
check('blur abandoned', solve(True, 'blur', False, False, False), False)
check('leave focused', solve(True, 'leave', True, False, False), True)
check('leave abandoned', solve(True, 'leave', False, False, False), False)
check('parameterized remaining trigger', solve(True, 'blur', False, bool(N%2), False), bool(N%2))
for repetition in range(N):
    check('repeat leave abandoned', solve(True, 'leave', False, False, False), False)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
disableFalseFalsePassed
escapeFalseFalsePassed
focusTrueTruePassed
blur hoveredTrueTruePassed
blur abandonedFalseFalsePassed
leave focusedTrueTruePassed
leave abandonedFalseFalsePassed
parameterized remaining triggerTrueTruePassed
repeat leave abandonedFalseFalsePassed

SHA-256 / c75368672f7ce71ffb7a703eb2ba69ccbf407ff753a76cc5311461e6cb8448b7

Verification & scope

This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:38:18.983964+00:00.

Case digest / 20154f13925fd2fe3ecf251b3ddce9628313fee4e33f540d3679d69f214d37c0