feat(filters): the any/all switch sits on the panel above its picker

ui/MatchToggle replaces the Combobox popover footer (Feed tags, topics,
languages; Plex collections) and PlexSidebar's own toggle (genres,
actors): shown from two picks, one wording. A closed picker had hidden
that "all" was on.
This commit is contained in:
2026-09-27 07:12:51 +02:00
parent 955c23d321
commit f48f16830e
12 changed files with 159 additions and 168 deletions
@@ -205,31 +205,6 @@ describe("Combobox", () => {
expect(onChange).toHaveBeenCalledWith(["id1"]); // single-select replaces
});
it("shows the any/all match footer only at 2+ selections and reports a mode change", () => {
// The per-category any/all toggle: meaningless below 2 selections (any === all), so it appears
// only at >= 2, and clicking 'all' reports the mode change out.
const onMatchModeChange = vi.fn();
const props = {
label: "Topic",
options: OPTIONS,
onChange: vi.fn(),
matchMode: "or" as const,
onMatchModeChange,
};
// One selection: no footer.
const { rerender } = wrap(<Combobox {...props} selected={["Drama"]} />);
fireEvent.focus(screen.getByRole("combobox"));
expect(screen.queryByText("sidebar.all")).toBeNull();
// Two selections: footer appears with an any/all segment.
rerender(<FloatingTree>{<Combobox {...props} selected={["Drama", "Action"]} />}</FloatingTree>);
fireEvent.focus(screen.getByRole("combobox"));
const all = screen.getByText("sidebar.all");
expect(all).toBeTruthy();
fireEvent.click(all);
expect(onMatchModeChange).toHaveBeenCalledWith("and");
});
it("single-select: picking replaces the value and closes the list", () => {
const onChange = vi.fn();
wrap(