feat(channels): fix the manager header, scroll only the table rows
Lift the whole subscribed-view header — tabs, sync stats + actions, the intro, the tag chips and the sync-status chips — into the shell's fixed band via PageToolbar. Combined with the sticky table header row, only the channel rows scroll now; everything above them stays put. The status chips move out of DataTable's controlsLeading into the fixed chrome (they belong above the header, not in the scrolling controls row). Note: the DataTable pager (rows-per-page / pagination) stays in the scroller for now — it rarely shows on the manager (few channels = one page). The discovery sub-view's chrome is still inline (separate component, handled in the sweep). Suite 15/15, tsc + knip clean.
This commit is contained in:
@@ -25,6 +25,7 @@ import { subsColumn } from "./channelColumns";
|
||||
import { notify } from "../lib/notifications";
|
||||
import Tooltip from "./Tooltip";
|
||||
import DataTable, { type Column } from "./DataTable";
|
||||
import { PageToolbar } from "./PageShell";
|
||||
import ChannelLink from "./ChannelLink";
|
||||
import ChannelDiscovery from "./ChannelDiscovery";
|
||||
import TagManager from "./TagManager";
|
||||
@@ -415,8 +416,12 @@ export default function Channels({
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* The whole manager header — tabs, stats, description, tags, status chips — is fixed chrome:
|
||||
it portals into the shell's fixed band, so only the table rows scroll (under the sticky
|
||||
header row). */}
|
||||
<PageToolbar>
|
||||
{tabs}
|
||||
<div className="px-4 pb-4 pt-3 max-w-7xl mx-auto">
|
||||
<div className="px-4 pt-3 pb-2 max-w-7xl mx-auto">
|
||||
{/* Per-user sync status + catalog-wide actions on one row (search/tags filtering
|
||||
now lives in the table headers). */}
|
||||
<div className="flex items-start justify-between gap-4 flex-wrap mb-4">
|
||||
@@ -535,11 +540,16 @@ export default function Channels({
|
||||
{t("channels.tags.manage")}
|
||||
</button>
|
||||
</div>
|
||||
{tagManagerOpen && (
|
||||
<TagManager onClose={() => setTagManagerOpen(false)} onFocusChannel={onFocusChannel} />
|
||||
)}
|
||||
{/* Sync-status chips — the last band of fixed chrome, right above the table header. */}
|
||||
{statusChips}
|
||||
</div>
|
||||
</PageToolbar>
|
||||
{tagManagerOpen && (
|
||||
<TagManager onClose={() => setTagManagerOpen(false)} onFocusChannel={onFocusChannel} />
|
||||
)}
|
||||
|
||||
{/* Channel table */}
|
||||
<div className="px-4 pb-4 pt-2 max-w-7xl mx-auto">
|
||||
{/* Channel table — only the rows scroll; the header row is sticky (see DataTable). */}
|
||||
{channelsQuery.isLoading ? (
|
||||
<div className="text-muted py-8">{t("channels.loading")}</div>
|
||||
) : (
|
||||
@@ -549,7 +559,6 @@ export default function Channels({
|
||||
rowKey={(c) => c.id}
|
||||
persistKey={accountKey(LS.channelsTable) ?? undefined}
|
||||
controlsPosition="top"
|
||||
controlsLeading={statusChips}
|
||||
rowClassName={(c) => (c.hidden ? "opacity-60" : "")}
|
||||
emptyText={t("channels.empty")}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user