Skip to content

[Repo Assist] Use Popover API for code snippet tooltips; fix scroll-offset positioning#1061

Open
github-actions[bot] wants to merge 11 commits intomainfrom
repo-assist/improve-popover-tooltips-804beaa-613ba4f90485b3ec
Open

[Repo Assist] Use Popover API for code snippet tooltips; fix scroll-offset positioning#1061
github-actions[bot] wants to merge 11 commits intomainfrom
repo-assist/improve-popover-tooltips-804beaa-613ba4f90485b3ec

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Mar 2, 2026

🤖 This PR was created by Repo Assist, an automated AI assistant.

Closes #422

Summary

Migrates hover tooltips (the div.fsdocs-tip elements shown when hovering over syntax tokens in code blocks) to use the browser-native [Popover API]((developer.mozilla.org/redacted), with a clean fallback for older browsers.

Changes

src/FSharp.Formatting.CodeFormat/HtmlFormatting.fs

Add the popover attribute to every generated div.fsdocs-tip element:

(div class="fsdocs-tip" id="fstips3")...(/div)

(div popover class="fsdocs-tip" id="fstips3")...(/div)

docs/content/fsdocs-tips.js

  • Popover API path (modern browsers, Baseline 2024): set position: fixed, then call el.showPopover() / el.hidePopover(). Elements in the top layer are always rendered above all other page content — no z-index arithmetic needed.
  • Fallback path (older browsers): retain existing position: absolute + display: block/none behaviour unchanged.
  • Bug fix: the right-edge overflow correction used y instead of x as the base for the left-shift; corrected to x.
  • Bug fix: currentTipElement was never cleared on hide; now set to null together with currentTip.

docs/content/fsdocs-default.css

Add div.fsdocs-tip:popover-open { display: block; } so the author-level display: none rule does not suppress the Popover API reveal (author rules take precedence over UA rules in the cascade). Also add margin: 0 to prevent UA default popover margins from shifting the tooltip.

Why the Popover API?

Property Old (JS absolute positioning) New (Popover API)
Rendering layer Normal stacking context — needs z-index: 1000 Browser top layer — always above everything
Positioning on scroll Bug: clientX/Y used with position: absolute → offset when scrolled Correct: clientX/Y used with position: fixed in top layer
Keyboard dismiss Manual document.onkeydown handler Built-in Escape key handling for auto popovers
Browser support All [Baseline 2024]((developer.mozilla.org/redacted) (Chrome 114+, Firefox 125+, Safari 17+)

Test Status

  • ✅ Build: dotnet build src/FSharp.Formatting.CodeFormat/ — 0 warnings, 0 errors
  • ✅ Tests: dotnet test tests/FSharp.CodeFormat.Tests/ — 20 passed, 2 skipped (pre-existing infrastructure skips)
  • ✅ Formatting: Fantomas check on changed .fs file — no changes needed
  • ⚠️ Visual verification: manual testing of hover tooltips, light-dismiss (Escape), and scroll-position accuracy recommended before merge

Generated by Repo Assist for issue #422

Generated by Repo Assist

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@da02dddebe71d9a937665abdcd1f5214dab852a7

- Add `popover` attribute to `div.fsdocs-tip` elements in HtmlFormatting.fs,
  placing them in the browser top layer when supported (Baseline 2024).
- Update fsdocs-tips.js to call showPopover()/hidePopover() on browsers that
  support the Popover API; fall back to display:block/none on older browsers.
- Switch to `position: fixed` in the Popover API path (correct for top-layer
  elements) and fix a scroll-offset bug where tooltips appeared at wrong
  positions when the page was scrolled.
- Fix a minor bug in the right-edge overflow correction (was using `y` instead
  of `x` as the base for the left-shift calculation).
- Add `div.fsdocs-tip:popover-open { display: block }` to fsdocs-default.css
  so author-level display:none does not suppress the Popover API reveal.
- Update RELEASE_NOTES.md.

Closes #422

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review March 6, 2026 23:59
@nojaf
Copy link
Collaborator

nojaf commented Mar 9, 2026

/repo-assist there is a regression here. When using the popover api, I see a black background on the surrounding tooltip area.
image

I also wonder if we need to stay backwards compatible here? Giving our technical audience the popover api will be present in high numbers. I don't think it is worth having the two mechanisms.

Also, improve to popup to have a very subtle fade in animation.

…fade-in

- CSS: add `inset: unset` to `div.fsdocs-tip:popover-open` to reset the UA
  popover stylesheet's `inset: 0` (i.e. right:0 / bottom:0), which was
  stretching the element across the viewport and causing the visible dark area
  around the tooltip.
- CSS: add `position: fixed` explicitly in the :popover-open rule so the
  element is correctly anchored to the JS-supplied left/top coordinates.
- CSS: add a 120ms ease-out opacity fade-in animation for a subtle reveal.
- JS: remove the display-toggle fallback branch entirely. The Popover API is
  Baseline 2024 (Chrome 114+, Firefox 125+, Safari 17+) and the technical
  audience of fsdocs users will have modern browsers.
- RELEASE_NOTES: update entry to reflect the simplified (no-fallback) design
  and the animation addition.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: 95f9b91

Generated by Repo Assist

@github-actions

This comment has been minimized.

@nojaf
Copy link
Collaborator

nojaf commented Mar 9, 2026

/repo-assist the black background is not fixed for me in latest Chrome.

I also wonder if we still need the more archaic code generated in

<span onmouseout="hideTip(event, 'fs1', 1)" onmouseover="showTip(event, 'fs1', 1)" class="fn">helloWorld</span>

onmouseout and onmouseover to trigger popover feels like fighting the modern api.
Is there no better way to do this? Modify the generated html if you must.

…ion; fix Chrome popover background

- HtmlFormatting.fs: emit data-fsdocs-tip / data-fsdocs-tip-unique instead
  of inline onmouseover/onmouseout handlers; overlapping vs non-overlapping
  cases now produce identical output (owner param is no longer needed)
- GenerateHtml.fs (ApiDocs): same data-* attrs on code elements; add the
  popover attribute to fsdocs-tip divs so showPopover() works there too
- fsdocs-tips.js: add delegated mouseover/mouseout listeners that read
  data-fsdocs-tip attributes; wrap showPopover() in try/catch for safety;
  keep showTip/hideTip on window for backward-compat with cached docs
- fsdocs-default.css: add explicit background-color inside :popover-open
  to override Chrome UA top-layer canvas default (fixes black background);
  add [data-fsdocs-tip] cursor rule alongside legacy span[onmouseout]

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: c4f034a

Generated by Repo Assist

@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

🤖 Repo Assist here — I've just pushed a follow-up commit addressing both points.

What changed

Black background in Chrome (:popover-open)

Chrome's UA stylesheet sets background-color: canvas on the top-layer element. Even though author rules should win, the canvas keyword can resolve unexpectedly in Chrome's top layer when color-scheme is involved. The fix is to repeat background-color: var(--doc-tip-background) explicitly inside div.fsdocs-tip:popover-open so there's no ambiguity.

No more onmouseover / onmouseout inline handlers

Generated HTML (HtmlFormatting.fs and GenerateHtml.fs) now emits:

<span data-fsdocs-tip="fs1" data-fsdocs-tip-unique="1" class="fn">helloWorld</span>

instead of the old inline handlers. A single delegated listener in fsdocs-tips.js picks these up:

document.addEventListener('mouseover', evt => {
    const target = evt.target.closest('[data-fsdocs-tip]');
    if (!target) return;
    showTip(evt, target.dataset.fsdocsTip, +target.dataset.fsdocsTipUnique);
});

The mouseout handler checks target.contains(evt.relatedTarget) before hiding, so moving between a trigger and its children doesn't flicker.

showTip now wraps showPopover() in a try/catch so old cached HTML (which still carries inline handlers) and API-doc tooltips won't throw if something's off. window.showTip/window.hideTip are still exported for backward compat.

API-doc tooltip divs (GenerateHtml.fs) now carry the popover attribute — previously missing, which would have caused showPopover() to throw a DOMException for every API doc hover.

Generated by Repo Assist for issue #1061 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

@nojaf nojaf requested a review from dsyme March 9, 2026 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CSS tooltips as an alternative (or replacement) for JS tooltips

2 participants