From d96521512695555657e4883900cb85772a0801ef Mon Sep 17 00:00:00 2001 From: jazairi <16103405+jazairi@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:28:31 -0500 Subject: [PATCH] Redesign filter sidebar Why these changes are being introduced: The filter sidebar can become unwieldy, as all available filters are shown at all times. Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/GDT-127 * https://mitlibraries.atlassian.net/browse/GDT-173 * https://mitlibraries.atlassian.net/browse/GDT-174 How this addresses that need: This restyles the filter sidebar as dropdown menus. In so doing, it also changes some behavior in the filter logic: * Number of results is listed in the filter sidebar header. * Clicking an applied filter removes that filter (this replaces the previous removal mechanism, which removed all applied filters). * Applied filters are highlighted with an `x` symbol, to indicate that it can be removed on click. (Previously, the 'applied' filter was added, but we hadn't done anything with it.) * The first filter dropdown in the sidebar is always open, even if no filters are applied. Not addressed in this commit: * Darcy asked that we persist menu state between page loads, such that an open menu always remains open unless a user closes it manually (e.g., if all filters have been removed in that category). This proved relatively complex, so I opened GDT-173 to address it. * There are some visual differences in how the sidebar appears in smaller viewports. This is covered in GDT-174. Side effects of this change: * Some tests have been updated to reflect the new logic. * One potential a11y issue with filter categories is having to navigate through a bunch of filter opens before getting to the next category. We might want to add skip-content links if this feels onerous. * The JS for the dropdown menus is so minimal that I included it in the view as a `script` tag. * The filter container is now above the results in the DOM. --- app/assets/stylesheets/partials/_filters.scss | 107 ++++++++++++++---- app/helpers/filter_helper.rb | 16 ++- app/helpers/results_helper.rb | 5 + app/views/search/_filter.html.erb | 40 ++++--- app/views/search/_filter_empty.html.erb | 1 - app/views/search/results.html.erb | 28 +++-- test/controllers/search_controller_test.rb | 2 +- test/helpers/filter_helper_test.rb | 49 +++++++- test/helpers/results_helper_test.rb | 20 ++++ 9 files changed, 209 insertions(+), 59 deletions(-) create mode 100644 app/helpers/results_helper.rb delete mode 100644 app/views/search/_filter_empty.html.erb create mode 100644 test/helpers/results_helper_test.rb diff --git a/app/assets/stylesheets/partials/_filters.scss b/app/assets/stylesheets/partials/_filters.scss index b3225be6..cee6f4a4 100644 --- a/app/assets/stylesheets/partials/_filters.scss +++ b/app/assets/stylesheets/partials/_filters.scss @@ -1,48 +1,107 @@ #filters { - h3 { + .category { + position: relative; + margin-bottom: 0.5em; + border: 1px solid $gray-l3; + border-radius: 3px; + } + + button.filter-label { + display: flex; + justify-content: space-between; + width: 100%; + text-align: left; margin-bottom: 0; + padding: 1rem; + border: 0; + color: $black; + background-color: $gray-l4; + font-size: $fs-small; + font-weight: $fw-bold; + + &::after { + font-family: FontAwesome; + content: '\f054'; + } + &.expanded { + border: 0; + border-radius: 0; + border-bottom: 1px solid $gray-l3; + & + .filter-options { + max-height: 200px; + overflow-y: scroll; + scrollbar-gutter: auto; + scroll-behavior: auto; + } + } + &.expanded:after { + font-family: FontAwesome; + content: '\f078'; + } + &::-webkit-details-marker { + display: none; + } } - .category { - margin-bottom: 1em; + .filter-options { + max-height: 0; + transition: max-height 0.5s ease-in-out; + overflow: hidden; } ul.category-terms { border-collapse: separate; border-spacing: 0px 4px; - display: table; - margin-bottom: 0; - table-layout: fixed; - width: 100%; + margin: 1rem; + margin-bottom: 2rem; li.term { - display: contents; + display: block; + width: 100%; + float: none; + margin: 0; + font-size: $fs-small; a { - display: table-row; + display: block; + width: 100%; text-decoration: none; - &:hover, - &:focus, - &.applied { - background: #000; - color: #fff; - } - span { display: table-cell; padding: 2px; - &.name { - width: 75%; - text-decoration: underline; - } + &.name { + width: 100%; + color: $blue; + } - &.count { - min-width: 25%; - text-align: right; - text-decoration: none; + &.count { + text-align: right; + text-decoration: none; + } + } + + &:hover, + &:focus { + background: #000; + span { + color: #fff; + } + } + &.applied { + .name { + color: #000; + &:hover, + &:focus { + color: #fff; } + } + .name::after { + font-family: FontAwesome; + margin-left: 0.5rem; + content: '\f00d'; + } } } } diff --git a/app/helpers/filter_helper.rb b/app/helpers/filter_helper.rb index 140ccd07..fe17874d 100644 --- a/app/helpers/filter_helper.rb +++ b/app/helpers/filter_helper.rb @@ -26,10 +26,22 @@ def nice_labels } end - def remove_filter(query, filter) + def remove_filter(query, filter, term) new_query = query.deep_dup new_query[:page] = 1 - new_query.delete filter.to_sym + + if new_query[filter].length > 1 + new_query[filter].delete(term) # If more than one term is filtered, we only delete the selected term + else + new_query.delete(filter) # If only one term is filtered, delete the entire filter from the query + end + new_query end + + def filter_applied?(terms, term) + return if terms.blank? + + terms.include?(term) + end end diff --git a/app/helpers/results_helper.rb b/app/helpers/results_helper.rb new file mode 100644 index 00000000..5889faef --- /dev/null +++ b/app/helpers/results_helper.rb @@ -0,0 +1,5 @@ +module ResultsHelper + def results_summary(hits) + hits.to_i >= 10_000 ? '10,000+ items' : "#{number_with_delimiter(hits)} items" + end +end diff --git a/app/views/search/_filter.html.erb b/app/views/search/_filter.html.erb index 7a8fd532..0cc9f833 100644 --- a/app/views/search/_filter.html.erb +++ b/app/views/search/_filter.html.erb @@ -1,19 +1,29 @@ <% return if values.empty? %>
There are no filters.
diff --git a/app/views/search/results.html.erb b/app/views/search/results.html.erb index 48e09fbc..38c3ac5d 100644 --- a/app/views/search/results.html.erb +++ b/app/views/search/results.html.erb @@ -49,6 +49,22 @@ <%= render(partial: 'shared/error', collection: @errors) %>