feat(web): show applied-filter count badge on search filter toggle#684
Merged
feat(web): show applied-filter count badge on search filter toggle#684
Conversation
memtomem
pushed a commit
that referenced
this pull request
May 2, 2026
Review (#684) caught two restore paths that set ``tag-filter`` / ``chunk-type-filter`` and call ``doSearch()`` without first telling the badge to recount: - ``saved-queries-select`` change handler (the dropdown next to the Save / ✕ buttons in the Advanced panel), - ``.saved-chip-name`` click handler in the saved-searches bar. The badge eventually recovers because ``_renderActiveFilters`` runs inside ``renderResults`` once the search returns, but in the gap between the form being populated and the network round-trip finishing the toggle button advertises stale numbers — and the PR description explicitly promised "tracks the form before the user even runs a search," so the gap is also a documentation lie. Add a single ``_updateFilterCountBadge()`` call before each ``doSearch()`` so the badge updates synchronously with the form. No new keys, no schema change. ``app.js`` is the only file touched and the cache-bust ``v=90`` from the original PR commit still covers it (the file content keeps moving under the same query string until the PR lands). Co-Authored-By: Claude <[email protected]>
The "▾ Filters" button only flipped to btn-active when the filter row was open; how many filters were actually applied was visible only via the chip row, which itself only renders alongside search results. Open the filters, set a tag and a namespace, collapse the row, and the button looked the same as if nothing was set. Add a small accent-coloured count badge inside the toggle that mirrors the chip set in _renderActiveFilters (namespace, tag, chunk type, score threshold). The badge updates from four edges: - input on tag-filter / change on ns-filter / change on chunk-type-filter / input on score-threshold so it tracks the form even before the user runs a search, - _renderActiveFilters at search time so chip removals (clicking ✕ on a chip) keep the count honest, - _loadSearchFromURL for the URL-restored case (?type=…), - the langchange event so the aria-label localizes alongside the rest of the UI. i18n adds search.filter_count_aria_one / _other in en + ko, following the existing CLDR `_one`/`_other` pattern (see PR #608 and index.upload_usage_count_*). Cache-bust style.css to v=74 and app.js to v=90. Verified end-to-end against Mode 1 (`uv run mm web`) with Playwright MCP: badge starts hidden, shows "2" after a tag + ns are set, drops to "1" when ns is cleared via change event, and hides again when both are cleared. aria-label reads "필터 2개 적용됨" / "필터 1개 적용됨" under ko. Co-Authored-By: Claude <[email protected]>
Review (#684) caught two restore paths that set ``tag-filter`` / ``chunk-type-filter`` and call ``doSearch()`` without first telling the badge to recount: - ``saved-queries-select`` change handler (the dropdown next to the Save / ✕ buttons in the Advanced panel), - ``.saved-chip-name`` click handler in the saved-searches bar. The badge eventually recovers because ``_renderActiveFilters`` runs inside ``renderResults`` once the search returns, but in the gap between the form being populated and the network round-trip finishing the toggle button advertises stale numbers — and the PR description explicitly promised "tracks the form before the user even runs a search," so the gap is also a documentation lie. Add a single ``_updateFilterCountBadge()`` call before each ``doSearch()`` so the badge updates synchronously with the form. No new keys, no schema change. ``app.js`` is the only file touched and the cache-bust ``v=90`` from the original PR commit still covers it (the file content keeps moving under the same query string until the PR lands). Co-Authored-By: Claude <[email protected]>
b93263e to
d1f1e09
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
▾ Filterstoggle only flipped tobtn-activewhen the filterrow was open; how many filters were actually applied was visible only
via the chip row, which itself only renders alongside search results.
Open the filters, set a tag and a namespace, collapse the row, and
the toggle looked the same as if nothing was set.
mirrors the chip set in
_renderActiveFilters(namespace, tag, chunktype, score threshold).
style.css?v=73 → v=74,app.js?v=89 → v=90.Why
UX walk-through flagged this as the smallest "the toggle is lying to
me" moment in the search bar. Counting the applied filters in one
place keeps the chip row and the toggle from disagreeing.
Update edges
The badge updates from four spots so the form, the chip row, URL
restore, and language toggle all stay in sync:
inputon#tag-filter/changeon#ns-filter/changeon#chunk-type-filter/inputon#score-threshold→ tracks the form before the user even runs a search.
_renderActiveFiltersat search time → chip-✕ removals keep thecount honest.
_loadSearchFromURLfor the URL-restored case (e.g.?type=…).langchangeevent →aria-labellocalizes alongside the rest ofthe UI.
i18n
Adds
search.filter_count_aria_one/_othertoen.jsonandko.json, following the existing CLDR_one/_otherpattern (seePR #608 and
index.upload_usage_count_*).Test plan
node --check packages/memtomem/src/memtomem/web/static/app.jspython -m json.toolon both locale files (parses)uv run ruff check packages/memtomem/srcuv run pytest packages/memtomem/tests/test_i18n.py—689→691-key parity / placeholder parity / empty-value
uv run mm web) + Playwright MCP, KO locale:- Initial: badge
hidden=true,textContent=""- After
tag-filter='foo'+ns-filter=<first>: badge visible,textContent="2",aria-label="필터 2개 적용됨"- Clear
ns-filteronly:textContent="1",aria-label="필터 1개 적용됨"- Clear
tag-filtertoo:hidden=true,aria-labelremovedlangchangetoggle re-localizes thearia-labelwhile a filteris applied
🤖 Generated with Claude Code