Skip to content

New combobox component #208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 11, 2024
Merged

New combobox component #208

merged 5 commits into from
Dec 11, 2024

Conversation

stephannv
Copy link
Contributor

@stephannv stephannv commented Nov 29, 2024

EDIT:
After some problems with combobox dialog we are keeping the floating-ui popover. I spent 2 days trying to make it work with anchor-positioning polyfill but I got no success due to some anchor-name/position-anchor property strange behavior. Other update: We are using radio/checkbox to control combobox inputs instead of a hidden select.

Screen.Recording.2024-12-04.at.14.51.56.mov

ORIGINAL:
@cirdes asked me to build a combobox with multiselect. I started building a new component (Multiselect) inspired by how <select multiple> behaves on mobile browsers, which opens a dialog with options instead a dropdown widget. But after some discussions, Cirdes and I agreed that we should build the new component as an evolution of current combobox. We read some texts and docs and got inspiration from OpenUI combobox proposal: https://open-ui.org/components/combobox.explainer. Floating-ui was removed in favor of native dialog component.

Demo:

Combobox(multiple: true, term: "frameworks") do
  ComboboxInput(name: "multiple")

  ComboboxTrigger placeholder: "Select your framework"

  ComboboxDialog do
    ComboboxSearchInput(placeholder: "Type the framework name")

    ComboboxDatalist do
      ComboboxEmptyState { "No results" }

      ComboboxOptgroup label: "Ruby" do
        ComboboxOption(value: "rails") { "Rails" }
        ComboboxOption(value: "hanami") { "Hanami" }
      end

      ComboboxOptgroup label: "Crystal" do
        ComboboxOption(value: "lucky", selected: true) { "Lucky" }
        ComboboxOption(value: "kemal") { "Kemal" }
      end

      ComboboxOptgroup label: "Others" do
        ComboboxOption(value: "django",) { "Django" }
        ComboboxOption(value: "laravel") { "Laravel" }
      end


      ComboboxOption(value: "spring",) { "Spring" }
      ComboboxOption(value: "vraptor") { "VRaptor" }
    end
  end
end
Screen.Recording.2024-11-29.at.13.57.40.mov

@stephannv stephannv self-assigned this Nov 29, 2024
@@ -26,10 +26,6 @@ codeblock:
gems:
- "rouge"

combobox:
js_packages:
- "@floating-ui/dom"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great not to have to use any dependencies for dialogs!

@@ -3,7 +3,7 @@
module RubyUI
class ComboboxInput < Base
def view_template
input(**attrs)
select(**attrs)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is a great idea to use a hidden select to hold the values and submit the options

}

this.datalistOptionTargets.forEach((datalistOption) => {
const selectOption = document.createElement("option")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if this would work if the combobox components were loaded using Turbo/async. Relying on JavaScript to create elements might be risky.

@stephannv stephannv requested a review from cirdes December 4, 2024 17:59

def default_attrs
{
class: "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 accent-primary",
Copy link
Contributor

@pierry01 pierry01 Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a good syntax for classes with big strings
classes | focus-visible classes | disabled classes

Suggested change
class: "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 accent-primary",
class: [
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background accent-primary",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
"disabled:cursor-not-allowed disabled:opacity-50"
]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Boa, acho que vai ajudar bastante mesmo a manter organizado.

Copy link
Contributor

@pierry01 pierry01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

insane!

Copy link
Collaborator

@cirdes cirdes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulations, @stephannv! It’s incredible to see that the combobox now supports multiple items.

@stephannv stephannv marked this pull request as draft December 9, 2024 13:28
@stephannv
Copy link
Contributor Author

Converting to draft while we apply the new combobox on a real application.
To do:
[ ] Jean's suggestions
[ ] Add flip() to popover.

@sethhorsley
Copy link
Member

Wow this is great!!

@stephannv stephannv marked this pull request as ready for review December 11, 2024 15:43
@stephannv stephannv merged commit d29fac6 into main Dec 11, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants