Skip to content

Make the flag filters switches, and drop the half nothing asks for - #233

Merged
ssavutu merged 2 commits into
mainfrom
fix/flag-filter-toggles
Sep 4, 2026
Merged

Make the flag filters switches, and drop the half nothing asks for#233
ssavutu merged 2 commits into
mainfrom
fix/flag-filter-toggles

Conversation

@ssavutu

@ssavutu ssavutu commented Sep 4, 2026

Copy link
Copy Markdown
Member

Follow-up to #231, which shipped Breaking and Featured as three-state chip rows: All / Breaking / Not breaking, and the same for Featured.

Switches

That third state does not earn its place. The reason to open the articles screen is to find what is flagged — which stories are still breaking, what is currently pinned. "Not breaking" is a question nobody asks, and two rows of three chips cost more room in the filter bar than the one question they answer.

before                                         after

Breaking  [ All ][ Breaking ][ Not breaking ]  Flags   (=O) Breaking only
Featured  [ All ][ Featured ][ Not featured ]          (O=) Featured only

Hand-rolled rather than a dependency: there is no switch in components/ui and no @radix-ui/react-switch in the tree, and pulling one in for two toggles would be more code than the twenty lines here. role="switch" with aria-checked is what makes it announce correctly; the track and knob are aria-hidden spans inside the button rather than focusable elements of their own. Knob travel is 3px of padding on both ends — checked against the box model and rendered headless, because a hand-rolled switch is easy to get a pixel wrong.

Dropping the unflagged half

?breaking=false and ?featured=false answered with the articles that do not carry the flag. Nothing asks for that — the screen's switches cannot, and a switch is the only client there is. It was kept on the theory someone would want it later, which is how a second, subtler branch stays in the listing query earning nothing.

What goes with it is the COALESCE(col, 0) = 0 form that made it correct. Both columns are nullable and the WordPress archive holds NULL, so the unflagged half had to be spelled carefully or it would have answered with only the few hundred rows the CMS itself wrote. The remaining = 1 needs no such care — NULL simply is not 1 — so removing the half removes the trap with it.

The parameter still parses the same true spellings, including bare ?breaking. Anything else, false included, now means "do not filter", and a test pins that so it cannot quietly start inverting instead. The NULL-flagged seed row stays too: it is what proves = 1 keeps nine thousand imported rows out of a list of breaking stories.

Note on persisted filter state

The screen remembers its filters in sessionStorage. The old key (breakingFilter: "all" | "on" | "off") is no longer read; the new one defaults to off. An editor with the tab already open and "Not breaking" selected sees the filter clear itself once, which is the correct end state rather than a stale one.

Testing

Run against a real MariaDB 11.8 (CMS_TEST_DSN), not just compiled: the full server suite passes, including TestArticleFlagFiltersHTTP. Worth stating plainly because CI has no database service, so every integration test in this repo skips there — a green backend check does not mean these ran.

go build, go vet, tsc --noEmit, eslint and vitest (20 tests) all pass. swag init --parseDependency --parseInternal rerun for the docs gate; that diff is only the two reworded descriptions.

🤖 Generated with Claude Code

https://claude.ai/code/session_01L4qBhBdQto1yNp1zP7VLYc

ssavutu and others added 2 commits September 3, 2026 23:37
They shipped as three-state chip rows -- All / Breaking / Not breaking -- on the
reasoning that an editor clearing a false alarm wants the stories that are not
flagged. In use that third state earns nothing: the reason to open this screen
is to find what IS flagged, and two rows of three chips cost more room in the
filter bar than the one question they answer.

Each is now a switch: on narrows to the flagged articles, off does not filter.

Hand-rolled, because there is no switch in components/ui and no
@radix-ui/react-switch in the tree, and pulling one in for two toggles would be
more code than the twenty lines here. role="switch" with aria-checked is what
makes it announce correctly; the track and knob are aria-hidden spans inside the
button rather than focusable elements of their own.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4qBhBdQto1yNp1zP7VLYc
?breaking=false and ?featured=false answered with the articles that do NOT
carry the flag. Nothing asks for that: the screen's switches cannot, and a
switch is the only client there is. It was carried on the theory that someone
would want it later, which is how a second, subtler code path stays in the
listing query earning nothing.

What goes with it is the COALESCE(col, 0) = 0 form that made it correct. Both
columns are nullable and the WordPress archive holds NULL, so the unflagged
half had to be spelled carefully or it would have answered with only the few
hundred rows the CMS itself wrote. The remaining `= 1` needs no such care --
NULL simply is not 1 -- so removing the half removes the trap with it.

The parameter still parses the same set of true spellings, including bare
?breaking. Anything else, false included, now means "do not filter", and the
test pins that so it cannot quietly start inverting instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4qBhBdQto1yNp1zP7VLYc
@ssavutu
ssavutu force-pushed the fix/flag-filter-toggles branch from edb217b to 1dfc2a5 Compare September 4, 2026 03:38
@ssavutu ssavutu changed the title Make the breaking and featured filters toggles Make the flag filters switches, and drop the half nothing asks for Sep 4, 2026
@ssavutu
ssavutu merged commit 96dd8d3 into main Sep 4, 2026
7 checks passed
@ssavutu
ssavutu deleted the fix/flag-filter-toggles branch September 4, 2026 03:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant