WIP with a combobox controller to handle filters with pure JS

This commit is contained in:
Jorge Manrubia
2025-09-18 15:02:25 +02:00
parent e33f1a6333
commit 7b60c6959a
4 changed files with 76 additions and 32 deletions
+9 -1
View File
@@ -108,7 +108,15 @@
}
.quick-filter {
&:not(.default-value):has(.checked) {
.checked {
display: none;
}
[aria-checked="true"] .checked {
display: block;
}
&:has([aria-checked="true"]) {
.input--select {
--input-background: var(--color-selected);
}
@@ -0,0 +1,38 @@
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
static targets = [ "label", "item" ]
static values = { selectPropertyName: { type: String, default: "aria-checked" } }
connect() {
this.labelTarget.textContent = this.#selectedLabel
}
change(event) {
const item = event.target.closest("[role='checkbox']")
if (item) {
this.#selectedItem = item
}
}
get #selectedLabel() {
const label = this.#selectedItem.querySelector("[data-combobox-label]")
return label.dataset.comboboxLabel
}
get #selectedItem() {
return this.itemTargets.find(item => item.getAttribute(this.selectPropertyNameValue) === "true")
}
set #selectedItem(item) {
this.#clearSelection()
item.setAttribute(this.selectPropertyNameValue, "true")
this.labelTarget.textContent = this.#selectedLabel
}
#clearSelection() {
this.itemTargets.forEach(target => {
target.setAttribute(this.selectPropertyNameValue, "false")
})
}
}
+11 -6
View File
@@ -1,6 +1,11 @@
<%= render "filters/settings/sorted_by", user_filtering: user_filtering %>
<%= render "filters/settings/indexed_by", user_filtering: user_filtering %>
<%= render "filters/settings/tags", user_filtering: user_filtering %>
<%= render "filters/settings/assignees", user_filtering: user_filtering %>
<%= render "filters/settings/creators", user_filtering: user_filtering %>
<%= render "filters/settings/closers", user_filtering: user_filtering %>
<%= form_with url: cards_path, method: :get, data: { controller: "form" } do |form| %>
<%= hidden_field_tag :expand_all, true, disabled: !user_filtering.expanded?, data: { toggle_enable_target: "element" } %>
<%= render "filters/settings/sorted_by", user_filtering: user_filtering %>
<%#= render "filters/settings/indexed_by", user_filtering: user_filtering %>
<%#= render "filters/settings/tags", user_filtering: user_filtering %>
<%#= render "filters/settings/assignees", user_filtering: user_filtering %>
<%#= render "filters/settings/creators", user_filtering: user_filtering %>
<%#= render "filters/settings/closers", user_filtering: user_filtering %>
<% end %>
+18 -25
View File
@@ -1,37 +1,30 @@
<% filter = user_filtering.filter %>
<%= tag.div class: class_names("quick-filter position-relative", "default-value": filter.sorted_by.latest?),
data: { controller: "dialog", action: "keydown.esc->dialog#close click@document->dialog#closeOnClickOutside", filter_show: user_filtering.show_sorted_by? } do %>
<button class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#open:stop">
<span class="overflow-ellipsis">
<%= sorted_by_label(filter.sorted_by) %>
<%= tag.div class: class_names("quick-filter position-relative"),
data: {
controller: "dialog combobox",
action: "keydown.esc->dialog#close click@document->dialog#closeOnClickOutside",
filter_show: user_filtering.show_sorted_by? } do %>
<button type="button" class="btn input input--select flex-inline txt-x-small" data-action="click->dialog#toggle:stop">
<span class="overflow-ellipsis" data-combobox-target="label">
</span>
</button>
<%= filter_dialog "Sort by…" do %>
<strong class="popup__title">Sort by…</strong>
<ul class="popup__list" data-filter-target="list">
<ul class="popup__list" data-filter-target="list" role="listbox">
<% Filter::SORTED_BY.each do |sort| %>
<li class="popup__item" data-navigable-list-target="item">
<%= form_with url: cards_path, method: :get, class: "full-width", data: { controller: "form" } do |form| %>
<% filter.as_params.except(:sorted_by).each do |key, value| %>
<%= filter_hidden_field_tag key, value %>
<% end %>
<%= hidden_field_tag :sorted_by, sort %>
<%= hidden_field_tag :expand_all, true, disabled: !user_filtering.expanded?, data: { toggle_enable_target: "element" } %>
<%= form.button type: "submit", class: "popup__btn btn" do %>
<span class="overflow-ellipsis flex-item-grow"><%= sorted_by_label(sort) %></span>
<% if filter.sorted_by == sort %>
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
<% end %>
<% end %>
<% end %>
</li>
<%= tag.li class: "popup__item", data: {
navigable_list_target: "item", combobox_target: "item", combobox_value: sort },
role: "checkbox",
aria: { checked: filter.sorted_by == sort } do %>
<button type="button" class="btn popup__btn" data-action="dialog#close combobox#change">
<span class="overflow-ellipsis flex-item-grow" data-combobox-label="<%= sorted_by_label(sort) %>"><%= sorted_by_label(sort) %></span>
<%= icon_tag "check", class: "checked flex-item-justify-end", "aria-hidden": true %>
</button>
<% end %>
<% end %>
</ul>
<% end %>
<% end %>
<% end %>