From ec0433d72112bcf59acf09347b2c119077186747 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Tue, 16 Sep 2025 14:46:21 -0500 Subject: [PATCH] Remember localStorage state after filtering --- app/assets/stylesheets/popup.css | 14 +---- app/helpers/filters_helper.rb | 2 +- .../nav_section_expander_controller.js | 63 ++++++++----------- app/views/filters/_menu.html.erb | 2 +- 4 files changed, 28 insertions(+), 53 deletions(-) diff --git a/app/assets/stylesheets/popup.css b/app/assets/stylesheets/popup.css index ba5be2a54..c6035dedd 100644 --- a/app/assets/stylesheets/popup.css +++ b/app/assets/stylesheets/popup.css @@ -45,23 +45,11 @@ } /* Hide lists when all the items within are hidden */ - /* .popup__section { + .popup__section { &:has(.popup__section-title:only-child), &:has(.popup__item[hidden]):not(:has(.popup__item:not([hidden]))) { display: none; } - } */ - - .popup__section { - .popup__section-title { - background: orange; - } - - &[open] { - .popup__section-title { - background: lime; - } - } } .popup__section-title { diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb index 337c7e2d4..8b33a23b1 100644 --- a/app/helpers/filters_helper.rb +++ b/app/helpers/filters_helper.rb @@ -36,7 +36,7 @@ module FiltersHelper end def collapsible_nav_section(title, &block) - tag.details class: "popup__section", data: { controller: "nav-section-expander", action: "toggle->nav-section-expander#toggle", nav_section_expander_target: "section", nav_section_expander_key_value: title.parameterize }, open: true do + tag.details class: "popup__section", data: { action: "toggle->nav-section-expander#toggle", nav_section_expander_target: "section", nav_section_expander_key_value: title.parameterize }, open: true do concat(tag.summary(class: "popup__section-title") do concat title concat icon_tag "caret-down" diff --git a/app/javascript/controllers/nav_section_expander_controller.js b/app/javascript/controllers/nav_section_expander_controller.js index c1642fcb2..7c591b024 100644 --- a/app/javascript/controllers/nav_section_expander_controller.js +++ b/app/javascript/controllers/nav_section_expander_controller.js @@ -1,60 +1,47 @@ import { Controller } from "@hotwired/stimulus" -// TODO: roll up this controller to one level; remove from sections -// This will involve using events to select the sections when they're clicked - export default class extends Controller { static values = { key: String } - static targets = [ "input" ] + static targets = [ "input", "section" ] - connect() { - this.#restoreToggle() + sectionTargetConnected() { + this.#restoreToggles() } - toggle() { - console.log(this.element) - if (this.element.hasAttribute("data-ignore")) { - // console.log("Don't save it!") - } else { - // console.log("Save it!") - if (this.element.open) { - localStorage.removeItem(this.#localStorageKey) + // When toggling, save the state to localStorage as long as it's not + // temporarily expanded during a filter + toggle(event) { + const section = event.target + + if (!section.hasAttribute("data-temp-expand")) { + if (section.open) { + localStorage.removeItem(this.#localStorageKey(section)) } else { - localStorage.setItem(this.#localStorageKey, this.keyValue) + localStorage.setItem(this.#localStorageKey(section), true) } } } - // OK, here's the behavior we want: - // Open the dialog, and the sections are in various states of collapsed/open. - // When you filter, we open them all. - // When the filter is empty, we need to go back to the saved state. - showAll() { - console.log(this.element) - // When filtering, we open everything and don't save to local storage. - // When the filter is cleared, we restore toggles + showWhileFiltering() { if (this.inputTarget.value) { - for (const section of this.#sections) { - section.setAttribute("data-ignore", true) - section.setAttribute("open", true) + for (const section of this.sectionTargets) { + section.setAttribute("data-temp-expand", true) + section.open = true } } else { - // UGH! This works in the context of the controller on the section, not from the birds-eye view of the details el. - this.#restoreToggle() + this.#restoreToggles() } } - #restoreToggle() { - // console.log("RESTORE TOGGLE") - const isCollapsed = localStorage.getItem(this.#localStorageKey) != null - if (isCollapsed) this.element.open = false + #restoreToggles() { + for (const section of this.sectionTargets) { + const isCollapsed = localStorage.getItem(this.#localStorageKey(section)) != null + if (isCollapsed) section.open = false + section.removeAttribute("data-temp-expand") + } } - get #localStorageKey() { - return this.keyValue - } - - get #sections() { - return this.element.querySelectorAll(":scope details:not([open])") + #localStorageKey(section) { + return section.getAttribute("data-nav-section-expander-key-value") } } diff --git a/app/views/filters/_menu.html.erb b/app/views/filters/_menu.html.erb index 95c4b29dc..7b84cdd60 100644 --- a/app/views/filters/_menu.html.erb +++ b/app/views/filters/_menu.html.erb @@ -3,7 +3,7 @@ <%= tag.dialog class: "fizzy-menu filter popup popup--animated panel margin-block-start-half", data: { - action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset filter:changed->nav-section-expander#showAll toggle->filter#filter", + action: "turbo:before-cache@document->dialog#close keydown->navigable-list#navigate filter:changed->navigable-list#reset filter:changed->nav-section-expander#showWhileFiltering toggle->filter#filter", controller: "filter navigable-list nav-section-expander", dialog_target: "dialog", navigable_list_focus_on_selection_value: false,