Skip to content

Commit e6b6b5b

Browse files
committed
[Bug Fix] DropdownMenu: fix z-index stacking and default placement (#439)
- Default placement changed from `top` to `bottom` so menus open below their trigger (matches dropdown convention). - Removed the static `z-50` from the DropdownMenu container; the controller now sets z-index only while open, so closed sibling dropdowns no longer cover an open menu (they share the same z-50 and DOM order decided paint order). - Dropped `w-full` from the Usage demo trigger so the floating reference matches the visible button instead of a full-width wrapper.
1 parent fe69c94 commit e6b6b5b

5 files changed

Lines changed: 13 additions & 6 deletions

File tree

docs/app/javascript/controllers/ruby_ui/dropdown_menu_controller.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default class extends Controller {
4343

4444
#computeTooltip() {
4545
computePosition(this.triggerTarget, this.contentTarget, {
46-
placement: this.optionsValue.placement || "top",
46+
placement: this.optionsValue.placement || "bottom",
4747
middleware: [flip(), shift(), offset(8)],
4848
strategy: this.optionsValue.strategy || "absolute",
4949
}).then(({ x, y }) => {
@@ -73,12 +73,16 @@ export default class extends Controller {
7373
this.#deselectAll();
7474
this.#addEventListeners();
7575
this.#computeTooltip();
76+
// Lift the open menu above sibling dropdowns/elements. The container has no
77+
// static z-index, so closed siblings stack in normal flow and never cover it.
78+
this.element.style.zIndex = "50";
7679
this.contentTarget.classList.remove("hidden");
7780
}
7881

7982
close() {
8083
this.openValue = false;
8184
this.#removeEventListeners();
85+
this.element.style.zIndex = "";
8286
this.contentTarget.classList.add("hidden");
8387
}
8488

docs/app/views/docs/dropdown_menu.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def view_template
1111
render Docs::VisualCodeExample.new(title: "Example", context: self) do
1212
<<~RUBY
1313
DropdownMenu do
14-
DropdownMenuTrigger(class: 'w-full') do
14+
DropdownMenuTrigger do
1515
Button(variant: :outline) { "Open" }
1616
end
1717
DropdownMenuContent do
@@ -29,7 +29,7 @@ def view_template
2929
render Docs::VisualCodeExample.new(title: "Non-navigational item", description: "Use as: :div when the item hosts its own interactive element (e.g. a dialog or form trigger). This avoids nesting a <button>/<form> inside the item's <a> while keeping the menu-item styling, role and keyboard behavior.", context: self) do
3030
<<~RUBY
3131
DropdownMenu do
32-
DropdownMenuTrigger(class: 'w-full') do
32+
DropdownMenuTrigger do
3333
Button(variant: :outline) { "Open" }
3434
end
3535
DropdownMenuContent do

gem/lib/ruby_ui/dropdown_menu/dropdown_menu.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ def view_template(&)
1616
def default_attrs
1717
{
1818
class: [
19-
"z-50",
2019
"group/dropdown-menu",
2120
(strategy == "absolute") ? "is-absolute" : "is-fixed"
2221
],

gem/lib/ruby_ui/dropdown_menu/dropdown_menu_controller.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export default class extends Controller {
4343

4444
#computeTooltip() {
4545
computePosition(this.triggerTarget, this.contentTarget, {
46-
placement: this.optionsValue.placement || "top",
46+
placement: this.optionsValue.placement || "bottom",
4747
middleware: [flip(), shift(), offset(8)],
4848
strategy: this.optionsValue.strategy || "absolute",
4949
}).then(({ x, y }) => {
@@ -73,12 +73,16 @@ export default class extends Controller {
7373
this.#deselectAll();
7474
this.#addEventListeners();
7575
this.#computeTooltip();
76+
// Lift the open menu above sibling dropdowns/elements. The container has no
77+
// static z-index, so closed siblings stack in normal flow and never cover it.
78+
this.element.style.zIndex = "50";
7679
this.contentTarget.classList.remove("hidden");
7780
}
7881

7982
close() {
8083
this.openValue = false;
8184
this.#removeEventListeners();
85+
this.element.style.zIndex = "";
8286
this.contentTarget.classList.add("hidden");
8387
}
8488

gem/lib/ruby_ui/dropdown_menu/dropdown_menu_docs.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def view_template
1111
render Docs::VisualCodeExample.new(title: "Example", context: self) do
1212
<<~RUBY
1313
DropdownMenu do
14-
DropdownMenuTrigger(class: 'w-full') do
14+
DropdownMenuTrigger do
1515
Button(variant: :outline) { "Open" }
1616
end
1717
DropdownMenuContent do

0 commit comments

Comments
 (0)