From eb339195c72273e693a03830ea20476d810a95f2 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sun, 27 Sep 2026 15:06:32 +0200 Subject: [PATCH] feat(channels): the band's tag chips and status row fold on a short window (B4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every other page band folds its filter row below ~600px of height; the Channels band never did, so its tag chip lane and status / pager row kept a short laptop window for themselves. They fold behind one "Filters · n" (n = picked tags + other active column filters); the tabs and the TAGS editor stay, and a folded table keeps its controls at the list's end. --- frontend/src/components/Channels.tsx | 21 ++++++++++++++----- .../channelsTagRow.contract.test.ts | 13 ++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) 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 && (