Skip to content

Commit 892dc4f

Browse files
committed
Replace modal with popover
1 parent 1d1bc6b commit 892dc4f

File tree

8 files changed

+61
-46
lines changed

8 files changed

+61
-46
lines changed

lib/generators/ruby_ui/dependencies.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ codeblock:
2626
gems:
2727
- "rouge"
2828

29+
combobox:
30+
js_packages:
31+
- "@floating-ui/dom"
32+
2933
command:
3034
js_packages:
3135
- "fuse.js"

lib/ruby_ui/combobox/combobox_controller.js

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Controller } from "@hotwired/stimulus";
2+
import { computePosition, autoUpdate, offset } from "@floating-ui/dom";
23

34
// Connects to data-controller="ruby-ui--combobox"
45
export default class extends Controller {
@@ -8,7 +9,7 @@ export default class extends Controller {
89

910
static targets = [
1011
"input",
11-
"dialog",
12+
"popover",
1213
"item",
1314
"emptyState",
1415
"searchInput",
@@ -22,11 +23,15 @@ export default class extends Controller {
2223
this.updateTriggerContent()
2324
}
2425

26+
disconnect() {
27+
this.cleanup();
28+
}
29+
2530
inputChanged(e) {
2631
this.updateTriggerContent()
2732

2833
if (e.target.type == "radio") {
29-
this.closeDialog()
34+
this.closePopover()
3035
}
3136
}
3237

@@ -46,26 +51,19 @@ export default class extends Controller {
4651
}
4752
}
4853

49-
openDialog(event) {
54+
openPopover(event) {
5055
event.preventDefault()
5156

52-
document.body.classList.add('overflow-hidden')
57+
this.popoverTarget.style.positionAnchor
5358
this.triggerTarget.ariaExpanded = "true"
54-
this.dialogTarget.showModal()
55-
}
56-
57-
closeDialog() {
58-
document.body.classList.remove('overflow-hidden')
59-
this.triggerTarget.ariaExpanded = "false"
6059
this.selectedItemIndex = null
6160
this.itemTargets.forEach(item => item.ariaCurrent = "false")
62-
this.dialogTarget.close()
61+
this.popoverTarget.showPopover()
6362
}
6463

65-
handleOutsideClick(event) {
66-
if (event.target === this.dialogTarget) {
67-
this.closeDialog()
68-
}
64+
closePopover() {
65+
this.triggerTarget.ariaExpanded = "false"
66+
this.popoverTarget.hidePopover()
6967
}
7068

7169
filterItems(e) {
@@ -139,4 +137,17 @@ export default class extends Controller {
139137
wrapSelectedInputIndex(length) {
140138
this.selectedItemIndex = ((this.selectedItemIndex % length) + length) % length
141139
}
140+
141+
updatePopoverPosition() {
142+
this.cleanup = autoUpdate(this.triggerTarget, this.popoverTarget, () => {
143+
computePosition(this.triggerTarget, this.popoverTarget, {
144+
middleware: [offset(4)],
145+
}).then(({ x, y }) => {
146+
Object.assign(this.popoverTarget.style, {
147+
left: `${x}px`,
148+
top: `${y}px`,
149+
});
150+
});
151+
});
152+
}
142153
}

lib/ruby_ui/combobox/combobox_dialog.rb

Lines changed: 0 additions & 25 deletions
This file was deleted.

lib/ruby_ui/combobox/combobox_list_group.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def view_template(&)
1212

1313
def default_attrs
1414
{
15-
class: ["hidden has-[label:not(.hidden)]:flex flex-col gap-1", LABEL_CLASSES],
15+
class: ["hidden has-[label:not(.hidden)]:flex flex-col py-1 gap-1 border-b", LABEL_CLASSES],
1616
role: "group"
1717
}
1818
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# frozen_string_literal: true
2+
3+
module RubyUI
4+
class ComboboxPopover < Base
5+
def view_template(&)
6+
div(**attrs, &)
7+
end
8+
9+
private
10+
11+
def default_attrs
12+
{
13+
class: "inset-auto m-0 absolute border bg-background shadow-lg rounded-lg",
14+
role: "popover",
15+
autofocus: true,
16+
popover: true,
17+
data: {
18+
ruby_ui__combobox_target: "popover",
19+
action: "keydown.down->ruby-ui--combobox#keyDownPressed keydown.up->ruby-ui--combobox#keyUpPressed keydown.enter->ruby-ui--combobox#keyEnterPressed keydown.esc->ruby-ui--combobox#closeDialog:prevent"
20+
}
21+
}
22+
end
23+
end
24+
end

lib/ruby_ui/combobox/combobox_search_input.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def default_attrs
2424
placeholder: @placeholder,
2525
data: {
2626
ruby_ui__combobox_target: "searchInput",
27-
action: "keyup->ruby-ui--combobox#filterItems"
27+
action: "keyup->ruby-ui--combobox#filterItems search->ruby-ui--combobox#filterItems"
2828
},
2929
autocomplete: "off",
3030
autocorrect: "off",

lib/ruby_ui/combobox/combobox_trigger.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ def view_template
1818

1919
def default_attrs
2020
{
21+
type: "button",
2122
class: "flex h-full w-full items-center whitespace-nowrap rounded-md text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground h-10 px-4 py-2 w-[200px] justify-between",
2223
data: {
2324
placeholder: @placeholder,
2425
ruby_ui__combobox_target: "trigger",
25-
action: "ruby-ui--combobox#openDialog"
26+
action: "ruby-ui--combobox#openPopover"
2627
},
2728
aria: {
28-
haspopup: "dialog",
29+
haspopup: "listbox",
2930
expanded: "false"
3031
}
3132
}

test/ruby_ui/combobox_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ def test_render_with_radio_items
88
RubyUI.Combobox(multiple: true, term: "frameworks") do
99
RubyUI.ComboboxTrigger placeholder: "Select your framework"
1010

11-
RubyUI.ComboboxDialog do
11+
RubyUI.ComboboxPopover do
1212
RubyUI.ComboboxSearchInput(placeholder: "Type the framework name")
1313

1414
RubyUI.ComboboxList do
@@ -42,7 +42,7 @@ def test_render_with_checkbox_items
4242
RubyUI.Combobox(multiple: true, term: "frameworks") do
4343
RubyUI.ComboboxTrigger placeholder: "Select your framework"
4444

45-
RubyUI.ComboboxDialog do
45+
RubyUI.ComboboxPopover do
4646
RubyUI.ComboboxSearchInput(placeholder: "Type the framework name")
4747

4848
RubyUI.ComboboxList do

0 commit comments

Comments
 (0)