Skip to content
Components

Scroll to bottom

A small animated invitation to return to the latest content.

TS
import { … } from "@fungi.computer/caps/components/scroll-to-bottom-blob";

Hero

TSX
import { ScrollToBottomBlob } from "@fungi.computer/caps/components/scroll-to-bottom-blob";
import { useRef } from "react";
export default function Hero() {
const scroller = useRef<HTMLDivElement>(null);
return (
<div className="relative h-40 w-72 rounded-box border border-base-300 bg-base-100">
<div ref={scroller} className="h-full overflow-y-auto p-md" tabIndex={-1}>
{Array.from({ length: 20 }, (_, index) => (
<p className="py-xs text-sm" key={index}>
Message {index + 1}
</p>
))}
</div>
<ScrollToBottomBlob
scrollerRef={scroller}
unread={3}
onJump={() => undefined}
/>
</div>
);
}

Jump

TSX
import { Button } from "@fungi.computer/caps/components/button";
import { ScrollToBottomBlob } from "@fungi.computer/caps/components/scroll-to-bottom-blob";
import { useRef, useState } from "react";
export default function Jump() {
const scroller = useRef<HTMLDivElement>(null);
const [unread, setUnread] = useState(0);
return (
<div className="grid max-w-sm gap-sm">
<Button
size="sm"
onClick={() => {
setUnread((value) => value + 1);
}}
>
New message
</Button>
<div className="relative h-40 rounded-box border border-base-300 bg-base-100">
<div
ref={scroller}
className="h-full overflow-y-auto p-md"
tabIndex={-1}
>
{Array.from({ length: 20 }, (_, index) => (
<p className="py-xs text-sm" key={index}>
Message {index + 1}
</p>
))}
</div>
<ScrollToBottomBlob
scrollerRef={scroller}
unread={unread}
onJump={() => {
setUnread(0);
scroller.current?.scrollTo({
top: scroller.current.scrollHeight,
behavior: "smooth",
});
}}
/>
</div>
</div>
);
}