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 && (