feat(feed): removable active-filter chips above the feed

With the filter panel now collapsed to a tab, there was no way to see what was
narrowing the feed without opening it. Every applied filter is now a chip you
can drop on its own, with a Clear all when more than one is on.

The panel's count badge and the chip row read the SAME list (lib/useActiveFilters),
so they can't disagree about what's applied; that list also owns the reset both
"Clear all"s share. Replaces the hand-summed activeCount in Sidebar.
This commit is contained in:
2026-07-15 22:11:44 +02:00
parent 837b48cbfa
commit 644d65a3fd
6 changed files with 212 additions and 28 deletions
+5
View File
@@ -14,6 +14,8 @@ import {
SORT_KEYS,
type SortKey,
} from "../lib/feedSort";
import { clearedFilters, useActiveFilters } from "../lib/useActiveFilters";
import ActiveFilterChips from "./ActiveFilterChips";
import VirtualFeed from "./VirtualFeed";
// Lazy: the in-app YouTube player (IFrame API) loads only when a video is first opened.
const PlayerModal = lazy(() => import("./PlayerModal"));
@@ -84,6 +86,8 @@ export default function Feed({
channelScoped?: boolean;
}) {
const { t } = useTranslation();
// Same list the panel's badge counts — see lib/useActiveFilters.
const activeFilters = useActiveFilters(filters, setFilters);
const sortKeys = channelScoped
? SORT_KEYS.filter((k) => k !== "subscribers" && k !== "priority")
: SORT_KEYS;
@@ -625,6 +629,7 @@ export default function Feed({
return (
<div className="p-4">
{toolbar}
<ActiveFilterChips filters={activeFilters} onClearAll={() => setFilters(clearedFilters(filters))} />
{items.length === 0 ? (
<div className="py-16 text-center text-muted">
<p>{t("feed.noMatches")}</p>