diff --git a/client/scss/components/_drilldown.scss b/client/scss/components/_drilldown.scss index 8346361b53..493aa799d3 100644 --- a/client/scss/components/_drilldown.scss +++ b/client/scss/components/_drilldown.scss @@ -62,6 +62,7 @@ .w-drilldown__submenu .w-field__label { @apply w-label-1; + // Align with the submenu’s back button. margin-top: theme('spacing.2'); margin-bottom: theme('spacing.3'); } @@ -76,8 +77,10 @@ font-weight: theme('fontWeight.bold'); border-radius: theme('borderRadius.full'); background-color: theme('colors.info.100'); + border: 1px solid theme('colors.info.100'); color: theme('colors.white.DEFAULT'); + // Reuse the same count component as a button badge. .w-filter-button & { position: absolute; top: calc(-0.5 * #{$badge-size}); diff --git a/client/scss/components/_pill.scss b/client/scss/components/_pill.scss index 34b00d0fd4..70ec41efef 100644 --- a/client/scss/components/_pill.scss +++ b/client/scss/components/_pill.scss @@ -3,10 +3,10 @@ min-height: theme('spacing[6.5]'); &__content { - @apply w-pl-3 w-py-1 w-rounded-l-xl w-bg-info-100 hover:w-bg-info-125 w-p-0 w-text-white hover:w-text-white w-pr-2 w-text-14 w-flex w-items-center w-border-r w-border-white-15 w-h-full; + @apply w-pl-3 w-py-1 w-rounded-l-xl w-bg-info-100 w-p-0 w-text-white w-pr-2 w-text-14 w-flex w-items-center w-border w-border-info-100 w-border-r-white-15 w-h-full; } &__remove { - @apply w-pr-3 w-py-1 w-rounded-r-xl w-bg-info-100 hover:w-bg-info-125 w-text-white hover:w-text-white w-p-0 w-pl-2 w-flex w-items-center w-justify-center w-h-full; + @apply w-pr-3 w-py-1 w-rounded-r-xl w-border w-border-info-100 w-bg-info-100 hover:w-bg-info-125 w-text-white hover:w-text-white w-p-0 w-pl-2 w-flex w-items-center w-justify-center w-h-full; } } diff --git a/client/src/controllers/DrilldownController.ts b/client/src/controllers/DrilldownController.ts index b97b92ad6a..633ffe0fbc 100644 --- a/client/src/controllers/DrilldownController.ts +++ b/client/src/controllers/DrilldownController.ts @@ -1,19 +1,27 @@ import { Controller } from '@hotwired/stimulus'; +/** + * Drilldown menu interaction combined with URL-driven + * state management for listing filters. + */ export class DrilldownController extends Controller { - static targets = ['menu', 'toggle']; + static targets = ['count', 'menu', 'toggle']; static values = { + // Default: main menu. activeSubmenu: { default: '', type: String }, }; declare activeSubmenuValue: string; + declare readonly countTarget: HTMLElement; declare readonly menuTarget: HTMLElement; declare readonly toggleTargets: HTMLButtonElement[]; connect() { - this.updateToggleCounts(); + const filteredParams = new URLSearchParams(window.location.search); + this.countTarget.hidden = filteredParams.size === 0; + this.countTarget.textContent = filteredParams.size.toString(); } updateParamsCount(e: Event) { @@ -29,9 +37,12 @@ export class DrilldownController extends Controller { filteredParams.append(key, value); } }); - const queryString = '?' + filteredParams.toString(); - this.updateToggleCounts(); + const queryString = `?${filteredParams.toString()}`; window.history.replaceState(null, '', queryString); + + // Update the drilldown’s count badge based on remaining filter parameters. + this.countTarget.hidden = filteredParams.size === 0; + this.countTarget.textContent = filteredParams.size.toString(); } } @@ -44,9 +55,12 @@ export class DrilldownController extends Controller { close() { this.activeSubmenuValue = ''; - this.updateToggleCounts(); } + /** + * Derive the component’s targets based on the state, + * so the drilldown state can be controlled externally more easily. + */ activeSubmenuValueChanged(activeSubmenu: string, prevActiveSubmenu?: string) { if (prevActiveSubmenu) { const toggle = document.querySelector( @@ -72,7 +86,6 @@ export class DrilldownController extends Controller { toggle.setAttribute('aria-expanded', expanded.toString()); content.hidden = !expanded; this.menuTarget.hidden = expanded; - this.element.classList.toggle('w-drilldown--active', expanded); if (expanded) { content.focus(); @@ -80,37 +93,4 @@ export class DrilldownController extends Controller { toggle.focus(); } } - - /** - * Placeholder function until this is more correctly set up with the backend. - */ - updateToggleCounts() { - let sum = 0; - - this.toggleTargets.forEach((toggle) => { - const content = this.element.querySelector( - `#${toggle.getAttribute('aria-controls')}`, - ); - const counter = toggle.querySelector('.w-drilldown__count'); - if (!content || !counter) { - return; - } - // Hack to detect fields with a non-default value. - const nbActiveFields = content.querySelectorAll( - '[type="checkbox"]:checked, [type="radio"]:checked:not([id$="_0"]), option:checked:not(:first-child), input:not([type="checkbox"], [type="radio"]):not(:placeholder-shown)', - ).length; - counter.hidden = nbActiveFields === 0; - counter.textContent = nbActiveFields.toString(); - sum += nbActiveFields; - }); - - const sumCounter = this.element.querySelector( - '.w-drilldown__count', - ); - if (!sumCounter) { - return; - } - sumCounter.hidden = sum === 0; - sumCounter.textContent = sum.toString(); - } } diff --git a/wagtail/admin/templates/wagtailadmin/shared/active_filters.html b/wagtail/admin/templates/wagtailadmin/shared/active_filters.html index 227e147c5a..9aff1f72f4 100644 --- a/wagtail/admin/templates/wagtailadmin/shared/active_filters.html +++ b/wagtail/admin/templates/wagtailadmin/shared/active_filters.html @@ -2,10 +2,10 @@
    {% for filter in active_filters %}
  • - + @@ -99,7 +98,7 @@ {% for field in filters.form %}