Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/silly-lights-fall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@openproject/primer-view-components': patch
---

Fix lazy loaded action-menu positioning when opened at the bottom of the page.
Comment thread
dombesz marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ export class ActionMenuElement extends HTMLElement {
#handleIncludeFragmentReplaced() {
this.#firstItem?.focus()
this.#softDisableItems()
this.overlay?.update()

// async items have loaded, so component is ready
this.setAttribute('data-ready', 'true')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ActionMenuController < ApplicationController
def landing; end

def deferred
sleep params[:delay].to_f if params[:delay].present?
render "primer/view_components/action_menu/deferred"
end

Expand Down
7 changes: 7 additions & 0 deletions previews/primer/alpha/action_menu_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,13 @@ def with_deferred_content(nest_in_sub_menu: false)
render_with_template(locals: { nest_in_sub_menu: nest_in_sub_menu })
end

# @label With deferred content near the bottom of the viewport
#
# @hidden
def with_deferred_content_near_bottom_of_viewport
render_with_template
end

# @label With deferred preloaded content
#
def with_deferred_preloaded_content
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<%# The invoker is pinned near the bottom of the viewport, leaving enough room for the loading %>
<%# spinner placeholder to fit below it but not enough for the full deferred content, reproducing %>
<%# the scenario from DREAM-729. The `delay` param forces the fragment response to arrive after the %>
<%# overlay has already been positioned using the placeholder's size, instead of racing the fetch %>
<%# against the initial position calculation. %>
<div style="position: fixed; bottom: 100px; right: 0;">
<%= render(Primer::Alpha::ActionMenu.new(menu_id: "deferred-bottom", src: primer_view_components.action_menu_deferred_path(delay: 0.3))) do |menu| %>
<% menu.with_show_button { "Menu with deferred content" } %>
<% end %>
</div>
13 changes: 13 additions & 0 deletions static/info_arch.json
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,19 @@
]
}
},
{
"preview_path": "primer/alpha/action_menu/with_deferred_content_near_bottom_of_viewport",
"name": "with_deferred_content_near_bottom_of_viewport",
"snapshot": "false",
"skip_rules": {
"wont_fix": [
"region"
],
"will_fix": [
"color-contrast"
]
}
},
{
"preview_path": "primer/alpha/action_menu/with_deferred_preloaded_content",
"name": "with_deferred_preloaded_content",
Expand Down
13 changes: 13 additions & 0 deletions static/previews.json
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,19 @@
]
}
},
{
"preview_path": "primer/alpha/action_menu/with_deferred_content_near_bottom_of_viewport",
"name": "with_deferred_content_near_bottom_of_viewport",
"snapshot": "false",
"skip_rules": {
"wont_fix": [
"region"
],
"will_fix": [
"color-contrast"
]
}
},
{
"preview_path": "primer/alpha/action_menu/with_deferred_preloaded_content",
"name": "with_deferred_preloaded_content",
Expand Down
11 changes: 11 additions & 0 deletions test/system/alpha/action_menu_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,17 @@ def test_deferred_loading_on_keydown
assert_equal page.evaluate_script("document.activeElement").text, "Copy link"
end

def test_deferred_loading_overlay_positioned_within_viewport
visit_preview(:with_deferred_content_near_bottom_of_viewport)
click_on_invoker_button

# Wait for lazy content to load
assert_selector "action-menu ul li", text: "Copy link"

overlay = find("anchored-position").native.node
assert overlay.in_viewport?, "Overlay should be positioned within the viewport after deferred content loads"
end

def test_deferred_dialog_opens
visit_preview(:with_deferred_content)

Expand Down
Loading