feat(tables): name a filter whose column is off screen, and let its chip clear it

A tabletHidden/narrowHidden column below its width, or any column in a card
layout, took its header funnel with it: the rows were narrowed by a filter
nobody could see. The cue is shown by the inverse of the column's own
container query, so it agrees with the table at every width and text size.
Wired into DataTable, the playlist table and the channel cards (E28 F2).
This commit is contained in:
2026-09-27 16:22:26 +02:00
parent 27483ae1d6
commit 51f881681b
10 changed files with 342 additions and 40 deletions
+27 -11
View File
@@ -40,6 +40,7 @@ import { sortRows } from "../lib/columnSort";
import { filterRows, isActive } from "../lib/tableColumns";
import { useFilterFold } from "../lib/useFilterFold";
import { FilterFoldButton } from "./ui/FilterFold";
import { HiddenFilterCue } from "./ui/HiddenFilterCue";
import { useCardPager } from "../lib/useCardPager";
import { PageToolbar } from "./ui/PageShell";
import { PageMenu } from "./ui/PageMenu";
@@ -56,6 +57,9 @@ import { useMe } from "../lib/useMe";
export type ChannelsView = "subscribed" | "discovery" | "hidden" | "blocked";
// The tag filter has its own chip row above the list, so the hidden-filter cue does not name it again.
const SURFACED_FILTERS = ["tags"];
// The top sync chips are a controlled view over the subscribed table's `sync` column filter (shared
// via ChannelsProvider): each chip writes `filters.sync`, using the SAME vocab + predicate as the
// Sync column funnel (channelColumns.tsx) so the two can't drift. "" = all (isActive treats it as
@@ -743,19 +747,31 @@ export default function Channels() {
rowClassName={() => "group"}
keyboardNav
reveal={follow}
surfacedFilters={SURFACED_FILTERS}
/>
) : (
<ChannelLayoutGrid
rows={pagedCards}
columns={columns}
rowKey={(c) => c.id}
leadKey="priority"
aboutKey="about"
moreKey="actions"
emptyText={t("channels.empty")}
rowProps={rowMenu.triggerProps}
rowClassName={() => "group"}
/>
<>
{/* Cards have no funnels: a Priority or name filter set in the table would narrow them
unseen. The tags have their own chip row. */}
<HiddenFilterCue
columns={columns}
filters={filters}
by="cards"
surfaced={SURFACED_FILTERS}
onFilter={(key, value) => setFilters({ ...filters, [key]: value })}
/>
<ChannelLayoutGrid
rows={pagedCards}
columns={columns}
rowKey={(c) => c.id}
leadKey="priority"
aboutKey="about"
moreKey="actions"
emptyText={t("channels.empty")}
rowProps={rowMenu.triggerProps}
rowClassName={() => "group"}
/>
</>
)}
<ContextMenu menu={rowMenu} ariaLabel={t("channels.row.menu")} items={menuItems} />
</div>