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 { notify } from "../lib/notifications";
|
||||||
import Tooltip from "./Tooltip";
|
import Tooltip from "./Tooltip";
|
||||||
import DataTable, { type Column } from "./DataTable";
|
import DataTable, { type Column } from "./DataTable";
|
||||||
|
import { PageToolbar } from "./PageShell";
|
||||||
import ChannelLink from "./ChannelLink";
|
import ChannelLink from "./ChannelLink";
|
||||||
import ChannelDiscovery from "./ChannelDiscovery";
|
import ChannelDiscovery from "./ChannelDiscovery";
|
||||||
import TagManager from "./TagManager";
|
import TagManager from "./TagManager";
|
||||||
@@ -415,8 +416,12 @@ export default function Channels({
|
|||||||
|
|
||||||
return (
|
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}
|
{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
|
{/* Per-user sync status + catalog-wide actions on one row (search/tags filtering
|
||||||
now lives in the table headers). */}
|
now lives in the table headers). */}
|
||||||
<div className="flex items-start justify-between gap-4 flex-wrap mb-4">
|
<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")}
|
{t("channels.tags.manage")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{tagManagerOpen && (
|
{/* Sync-status chips — the last band of fixed chrome, right above the table header. */}
|
||||||
<TagManager onClose={() => setTagManagerOpen(false)} onFocusChannel={onFocusChannel} />
|
{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 ? (
|
{channelsQuery.isLoading ? (
|
||||||
<div className="text-muted py-8">{t("channels.loading")}</div>
|
<div className="text-muted py-8">{t("channels.loading")}</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -549,7 +559,6 @@ export default function Channels({
|
|||||||
rowKey={(c) => c.id}
|
rowKey={(c) => c.id}
|
||||||
persistKey={accountKey(LS.channelsTable) ?? undefined}
|
persistKey={accountKey(LS.channelsTable) ?? undefined}
|
||||||
controlsPosition="top"
|
controlsPosition="top"
|
||||||
controlsLeading={statusChips}
|
|
||||||
rowClassName={(c) => (c.hidden ? "opacity-60" : "")}
|
rowClassName={(c) => (c.hidden ? "opacity-60" : "")}
|
||||||
emptyText={t("channels.empty")}
|
emptyText={t("channels.empty")}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user