feat(managers): actions-first discovery table, tabs in the back chain, pager scrolls to top

UAT round 4:
- Discovery table: move Actions to the first column, mirroring the Subscriptions
  table (where it sits right after Prio) so both tabs' actions line up.
- The manager's tabs now ride in history.state (`_chTab`), the same way the channel
  page (`_chan`) and the live search (`_yt`) already do — so Back steps back through
  the tabs you visited before it leaves the module. Arriving from elsewhere stamps
  the entry setPage pushed (one navigation never costs two Back presses).
- Turning a page now scrolls the list back to its top (both the tables and the card
  grid, since they share Pager) — landing mid-list in an unseen page is disorienting.
This commit is contained in:
2026-07-20 00:14:23 +02:00
parent dff4152522
commit a50608d026
3 changed files with 70 additions and 29 deletions
+11 -3
View File
@@ -34,9 +34,17 @@ export default function Pager({
// Local text for the editable "jump to page" box (committed on Enter/blur).
const [pageInput, setPageInput] = useState(String(safePage + 1));
useEffect(() => setPageInput(String(safePage + 1)), [safePage]);
// Turning the page swaps the whole list, so put the reader at its top — landing mid-list in a page
// you haven't seen is disorienting. The page scroller is the app's <main> (the same implicit
// contract BackToTop and VirtualGrid's getScrollParent rely on).
function goToPage(p: number) {
onPageChange(p);
document.querySelector("main")?.scrollTo({ top: 0 });
}
function commitPageInput() {
const n = parseInt(pageInput, 10);
if (!isNaN(n)) onPageChange(Math.min(totalPages - 1, Math.max(0, n - 1)));
if (!isNaN(n)) goToPage(Math.min(totalPages - 1, Math.max(0, n - 1)));
else setPageInput(String(safePage + 1));
}
@@ -46,7 +54,7 @@ export default function Pager({
{totalPages > 1 && (
<div className="flex items-center gap-2">
<button
onClick={() => onPageChange(Math.max(0, safePage - 1))}
onClick={() => goToPage(Math.max(0, safePage - 1))}
disabled={safePage === 0}
className="glass-card glass-hover flex items-center gap-1 px-3 py-1.5 rounded-lg disabled:opacity-40 transition"
>
@@ -69,7 +77,7 @@ export default function Pager({
{t("datatable.pager.ofTotal", { total: totalPages })}
</span>
<button
onClick={() => onPageChange(Math.min(totalPages - 1, safePage + 1))}
onClick={() => goToPage(Math.min(totalPages - 1, safePage + 1))}
disabled={safePage >= totalPages - 1}
className="glass-card glass-hover flex items-center gap-1 px-3 py-1.5 rounded-lg disabled:opacity-40 transition"
>