Skip to content

Commit

Permalink
Fix tooltips opening when focus is removed while displaying (#2281)
Browse files Browse the repository at this point in the history
Co-authored-by: Jon Rohan <rohan@github.com>
Co-authored-by: Jon Rohan <yes@jonrohan.codes>
  • Loading branch information
3 people committed Oct 17, 2023
1 parent 0e7bc4d commit 46d5d9c
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/ten-onions-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/view-components": patch
---

Fix tooltips opening when focus is removed while displaying
16 changes: 16 additions & 0 deletions app/components/primer/alpha/tool_tip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ function focusOutListener() {
closeOpenTooltips()
}

function focusInListener(event: Event) {
setTimeout(() => {
for (const tooltip of openTooltips) {
if (isPopoverOpen(tooltip) && tooltip.showReason === 'focus' && tooltip.control !== event.target) {
tooltip.hidePopover()
}
}
}, 0)
}

const tooltips = new Set<ToolTipElement>()
const openTooltips = new Set<ToolTipElement>()
class ToolTipElement extends HTMLElement {
Expand Down Expand Up @@ -193,6 +203,10 @@ class ToolTipElement extends HTMLElement {
#align: AnchorAlignment = 'center'
#side: AnchorSide = 'outside-bottom'
#allowUpdatePosition = false
#showReason: 'focus' | 'mouse' = 'mouse'
get showReason() {
return this.#showReason
}

get htmlFor(): string {
return this.getAttribute('for') || ''
Expand Down Expand Up @@ -270,6 +284,7 @@ class ToolTipElement extends HTMLElement {
signal
})
this.ownerDocument.addEventListener('focusout', focusOutListener)
this.ownerDocument.addEventListener('focusin', focusInListener)
this.ownerDocument.addEventListener('keydown', this, {signal})
}

Expand Down Expand Up @@ -297,6 +312,7 @@ class ToolTipElement extends HTMLElement {

await Promise.resolve()
if (!showing && shouldShow && !isPopoverOpen(this)) {
this.#showReason = event.type === 'mouseenter' ? 'mouse' : 'focus'
this.showPopover()
} else if (showing && shouldHide && isPopoverOpen(this)) {
this.hidePopover()
Expand Down
5 changes: 5 additions & 0 deletions previews/primer/alpha/tooltip_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ def tooltip_inside_primer_overlay(direction: :s, tooltip_text: "You can press a
locals: {}
)
end

# @label Tooltip with button moving focus to input
def tooltip_with_dialog_moving_focus_to_input()
render_with_template(locals: {})
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<%= render(Primer::Alpha::Dialog.new(id: "my-dialog", title: "Confirm focus")) do |d| %>
<%= render(Primer::Alpha::Dialog::Body.new()) do %>
Are you sure you want to focus the input?
<% end %>
<%= render(Primer::Alpha::Dialog::Footer.new()) do %>
<%= render(Primer::Beta::Button.new(id: "yes-button", data: { "close-dialog-id": "my-dialog" })) { "Yes" } %>
<%= render(Primer::Beta::Button.new(scheme: :primary, data: { "close-dialog-id": "my-dialog" })) { "Yes but in green" } %>
<% end %>
<% d.with_show_button do |b| %>
Focus input
<% b.with_tooltip(text: "This is a tooltip in an Overlay") %>
<% end %>
<% end %>
<label>
An input
<input type="text" id="input">
</label>
<script>
document.querySelector('#my-dialog').addEventListener('cancel', function () {
console.log('!!')
setTimeout(() => document.querySelector('#input').focus(), 0);
});
</script>
16 changes: 16 additions & 0 deletions test/system/alpha/tooltip_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,21 @@ def test_only_one_visible_at_a_time
assert_selector("tool-tip[for='button-2']", visible: :visible)
assert_selector("tool-tip.sr-only[for='button-3']", visible: :hidden)
end

def test_tooltip_hidden_after_focus_change
visit_preview(:tooltip_with_dialog_moving_focus_to_input)

assert_selector("tool-tip[for='dialog-show-my-dialog']", visible: :hidden)

find("button#dialog-show-my-dialog").hover

assert_selector("tool-tip[for='dialog-show-my-dialog']", visible: :visible)

find("button#dialog-show-my-dialog").click

find("modal-dialog#my-dialog button#yes-button").click

assert_selector("tool-tip[for='dialog-show-my-dialog']", visible: :hidden)
end
end
end

0 comments on commit 46d5d9c

Please sign in to comment.