Move scroll-to-bottom button to issue detail and run pages

Removed the scroll-to-bottom button from IssuesList (wrong location)
and created a shared ScrollToBottom component. Added it to IssueDetail
and RunDetail pages. On mobile, the button sits above the bottom nav
to avoid overlap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dotta
2026-03-07 20:07:39 -06:00
parent a96556b8f4
commit 45473b3e72
4 changed files with 45 additions and 28 deletions

View File

@@ -18,7 +18,7 @@ import { Input } from "@/components/ui/input";
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover";
import { Checkbox } from "@/components/ui/checkbox";
import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "@/components/ui/collapsible";
import { CircleDot, Plus, Filter, ArrowUpDown, Layers, Check, X, ChevronRight, List, Columns3, User, Search, ArrowDown } from "lucide-react";
import { CircleDot, Plus, Filter, ArrowUpDown, Layers, Check, X, ChevronRight, List, Columns3, User, Search } from "lucide-react";
import { KanbanBoard } from "./KanbanBoard";
import type { Issue } from "@paperclipai/shared";
@@ -234,24 +234,6 @@ export function IssuesList({
const activeFilterCount = countActiveFilters(viewState);
const [showScrollBottom, setShowScrollBottom] = useState(false);
useEffect(() => {
const el = document.getElementById("main-content");
if (!el) return;
const check = () => {
const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
setShowScrollBottom(distanceFromBottom > 300);
};
check();
el.addEventListener("scroll", check, { passive: true });
return () => el.removeEventListener("scroll", check);
}, [filtered.length]);
const scrollToBottom = useCallback(() => {
const el = document.getElementById("main-content");
if (el) el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
}, []);
const groupedContent = useMemo(() => {
if (viewState.groupBy === "none") {
return [{ key: "__all", label: null as string | null, items: filtered }];
@@ -755,15 +737,6 @@ export function IssuesList({
</Collapsible>
))
)}
{showScrollBottom && (
<button
onClick={scrollToBottom}
className="fixed bottom-6 right-6 z-40 flex h-9 w-9 items-center justify-center rounded-full border border-border bg-background shadow-md hover:bg-accent transition-colors"
aria-label="Scroll to bottom"
>
<ArrowDown className="h-4 w-4" />
</button>
)}
</div>
);
}

View File

@@ -0,0 +1,40 @@
import { useCallback, useEffect, useState } from "react";
import { ArrowDown } from "lucide-react";
/**
* Floating scroll-to-bottom button that appears when the user is far from the
* bottom of the `#main-content` scroll container. Hides when within 300px of
* the bottom. Positioned to avoid the mobile bottom nav.
*/
export function ScrollToBottom() {
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = document.getElementById("main-content");
if (!el) return;
const check = () => {
const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
setVisible(distance > 300);
};
check();
el.addEventListener("scroll", check, { passive: true });
return () => el.removeEventListener("scroll", check);
}, []);
const scroll = useCallback(() => {
const el = document.getElementById("main-content");
if (el) el.scrollTo({ top: el.scrollHeight, behavior: "smooth" });
}, []);
if (!visible) return null;
return (
<button
onClick={scroll}
className="fixed bottom-[calc(1.5rem+5rem+env(safe-area-inset-bottom))] right-6 z-40 flex h-9 w-9 items-center justify-center rounded-full border border-border bg-background shadow-md hover:bg-accent transition-colors md:bottom-6"
aria-label="Scroll to bottom"
>
<ArrowDown className="h-4 w-4" />
</button>
);
}