Skip to content

Commit c3d8a1f

Browse files
Add DropdownMenuOverlay component
1 parent f5a275f commit c3d8a1f

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

lib/ruby_ui/dropdown_menu/dropdown_menu_content.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def default_attrs
1515
data: {
1616
state: :open
1717
},
18-
class: "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-56"
18+
class: "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-background p-1 text-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-56"
1919
}
2020
end
2121
end

lib/ruby_ui/dropdown_menu/dropdown_menu_controller.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Controller } from "@hotwired/stimulus";
22
import { computePosition, flip, shift, offset } from "@floating-ui/dom";
33

44
export default class extends Controller {
5-
static targets = ["trigger", "content", "menuItem"];
5+
static targets = ["trigger", "content", "menuItem", "overlay"];
66
static values = {
77
open: {
88
type: Boolean,
@@ -33,7 +33,7 @@ export default class extends Controller {
3333

3434
onClickOutside(event) {
3535
if (!this.openValue) return;
36-
if (this.element.contains(event.target)) return;
36+
if (this.element.contains(event.target) && (!this.hasOverlayTarget || event.target !== this.overlayTarget)) return;
3737

3838
event.preventDefault();
3939
this.close();
@@ -49,12 +49,20 @@ export default class extends Controller {
4949
this.#addEventListeners();
5050
this.#computeTooltip()
5151
this.contentTarget.classList.remove("hidden");
52+
53+
if (this.hasOverlayTarget) {
54+
this.overlayTarget.classList.remove("hidden");
55+
}
5256
}
5357

5458
close() {
5559
this.openValue = false;
5660
this.#removeEventListeners();
5761
this.contentTarget.classList.add("hidden");
62+
63+
if (this.hasOverlayTarget) {
64+
this.overlayTarget.classList.add("hidden");
65+
}
5866
}
5967

6068
#handleKeydown(e) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class DropdownMenuOverlay < Base
5+
def view_template
6+
div(**attrs)
7+
end
8+
9+
private
10+
11+
def default_attrs
12+
{
13+
data: {
14+
ruby_ui__dropdown_menu_target: "overlay",
15+
action: "click->ruby-ui--dropdown-menu#onClickOutside"
16+
},
17+
class: "absolute fixed inset-0 z-40 bg-black opacity-20 hidden"
18+
}
19+
end
20+
end
21+
end

test/ruby_ui/dropdown_menu_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class RubyUI::DropdownMenuTest < ComponentTest
66
def test_render_with_all_items
77
output = phlex do
88
RubyUI.DropdownMenu do
9+
RubyUI::DropdownMenuOverlay()
910
RubyUI.DropdownMenuTrigger(class: "w-full") do
1011
RubyUI.Button(variant: :outline) { "Open" }
1112
end

0 commit comments

Comments
 (0)