diff --git a/frontend/src/components/Channels.tsx b/frontend/src/components/Channels.tsx
index bc5290a7..9daa0461 100644
--- a/frontend/src/components/Channels.tsx
+++ b/frontend/src/components/Channels.tsx
@@ -37,7 +37,9 @@ import ChannelStatsPopover from "./ChannelStatsPopover";
import Pager from "./ui/Pager";
import { CHANNEL_LAYOUTS, type ChannelLayout } from "../lib/channelLayout";
import { sortRows } from "../lib/columnSort";
-import { filterRows } from "../lib/tableColumns";
+import { filterRows, isActive } from "../lib/tableColumns";
+import { useFilterFold } from "../lib/useFilterFold";
+import { FilterFoldButton } from "./ui/FilterFold";
import { useCardPager } from "../lib/useCardPager";
import { PageToolbar } from "./ui/PageShell";
import { PageMenu } from "./ui/PageMenu";
@@ -243,6 +245,13 @@ export default function Channels() {
// funnel share ONE state and stay in sync (bidirectional). Toggling a chip rewrites `filters.tags`;
// filterRows / DataTable then applies it. Channel-name search stays separate (the shared top box).
const tagFilter = Array.isArray(filters.tags) ? filters.tags : [];
+ // B4 (E28 review L7): on a short window the band's filters — the tag chip lane and the status /
+ // pager row — fold behind one "Filters · n"; the tabs and the TAGS editor stay. n = each picked tag,
+ // plus every other active column filter (the status chips are the Sync column's).
+ const fold = useFilterFold();
+ const foldCount =
+ tagFilter.length +
+ Object.entries(filters).filter(([k, v]) => k !== "tags" && isActive(v)).length;
// Picking a real tag drops the "No tag" sentinel (item B) — they're mutually exclusive, as in the feed.
const toggleTagFilter = (tagId: number) => {
const id = String(tagId);
@@ -609,8 +618,9 @@ export default function Channels() {
{t("channels.tags.label")}
-
- {tagFilter.length > 0 && (
+
+ {!fold.folded && }
+ {!fold.folded && tagFilter.length > 0 && (