Skip to content

Commit

Permalink
Implement grouped options
Browse files Browse the repository at this point in the history
  • Loading branch information
josefarias committed Mar 20, 2024
1 parent 659767e commit 33c184e
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ Combobox.Navigation = Base => class extends Base {
},
ArrowDown: (event) => {
this._selectIndex(this._selectedOptionIndex + 1)

if (this._selectedOptionIndex === 0) {
this._actingListbox.scrollTop = 0
}

cancel(event)
},
Home: (event) => {
Expand Down
15 changes: 15 additions & 0 deletions app/assets/stylesheets/hotwire_combobox.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
:root {
--hw-active-bg-color: #F3F4F6;
--hw-border-color: #D1D5DB;
--hw-group-color: #57595C;
--hw-invalid-color: #EF4444;
--hw-dialog-label-color: #1D1D1D;
--hw-focus-color: #2563EB;
Expand Down Expand Up @@ -138,6 +139,20 @@
}
}

.hw-combobox__group {
display: none;
padding: 0;
}

.hw-combobox__group__label {
color: var(--hw-group-color);
padding: var(--hw-padding--slim);
}

.hw-combobox__group:has(.hw-combobox__option:not([hidden])) {
display: block;
}

.hw-combobox__option {
background-color: var(--hw-option-bg-color);
padding: var(--hw-padding--slim) var(--hw-padding--thick);
Expand Down
45 changes: 45 additions & 0 deletions app/presenters/hotwire_combobox/listbox/group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "securerandom"

class HotwireCombobox::Listbox::Group
def initialize(name, options:)
@name = name
@options = options
end

def render_in(view)
view.tag.ul **group_attrs do
view.concat view.tag.li(name, **label_attrs)

options.map do |option|
view.concat view.render(option)
end
end
end

private
attr_reader :name, :options

def id
@id ||= SecureRandom.uuid
end

def group_attrs
{
class: "hw-combobox__group",
role: :group,
aria: group_aria
}
end

def group_aria
{ labelledby: id }
end

def label_attrs
{
id: id,
class: "hw-combobox__group__label",
role: :presentation
}
end
end
19 changes: 16 additions & 3 deletions lib/hotwire_combobox/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,22 @@ def hw_extract_options_and_src(options_or_src, render_in, include_blank)
end

def hw_parse_combobox_options(options, render_in_proc: nil, **methods)
options.map do |option|
HotwireCombobox::Listbox::Option.new \
**hw_option_attrs_for(option, render_in_proc: render_in_proc, **methods)
are_groups = options.is_a?(Hash) && options.values.all?(Array)

if are_groups
options.map do |group_name, group_options|
group_options = group_options.map do |option|
HotwireCombobox::Listbox::Option.new \
**hw_option_attrs_for(option, render_in_proc: render_in_proc, **methods)
end

HotwireCombobox::Listbox::Group.new group_name, options: group_options
end
else
options.map do |option|
HotwireCombobox::Listbox::Option.new \
**hw_option_attrs_for(option, render_in_proc: render_in_proc, **methods)
end
end
end

Expand Down
5 changes: 4 additions & 1 deletion test/dummy/app/controllers/comboboxes_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class ComboboxesController < ApplicationController
before_action :set_states, except: :new_options
before_action :set_states, except: %i[ new_options grouped_options ]

def plain
end
Expand Down Expand Up @@ -90,6 +90,9 @@ def multiselect_new_values
@user = User.first || raise("No user found, load fixtures first.")
end

def grouped_options
end

private
delegate :combobox_options, :html_combobox_options, to: "ApplicationController.helpers", private: true

Expand Down
1 change: 1 addition & 0 deletions test/dummy/app/views/comboboxes/grouped_options.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= combobox_tag "state", State.all.group_by(&:location), id: "state-field" %>
1 change: 1 addition & 0 deletions test/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
get "multiselect_prefilled_form", to: "comboboxes#multiselect_prefilled_form"
get "multiselect_custom_events", to: "comboboxes#multiselect_custom_events"
get "multiselect_new_values", to: "comboboxes#multiselect_new_values"
get "grouped_options", to: "comboboxes#grouped_options"

resources :movies, only: %i[ index update ]
get "movies_html", to: "movies#index_html"
Expand Down
16 changes: 16 additions & 0 deletions test/system/hotwire_combobox_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,18 @@ class HotwireComboboxTest < ApplicationSystemTestCase
assert_equal %w[ Alabama Newplace ], User.first.visited_states.map(&:name)
end

test "grouped options" do
visit grouped_options_path

open_combobox "#state-field"

assert_group_with text: "South"
assert_option_with text: "Alabama"

type_in_combobox "#state-field", :down
assert_selected_option_with text: "Alabama"
end

private
def open_combobox(selector)
find(selector).click
Expand Down Expand Up @@ -1183,6 +1195,10 @@ def assert_focused_combobox(selector)
page.evaluate_script("document.activeElement.id") == locator_for(selector)
end

def assert_group_with(**kwargs)
assert_selector "ul[role=group] li[role=presentation]", **kwargs
end

def remove_chip(text)
find("[aria-label='Remove #{text}']").click
end
Expand Down

0 comments on commit 33c184e

Please sign in to comment.