feat: add scroll to bottom button and auto-scroll on session load

This commit is contained in:
Alexej Wolff
2026-02-11 16:29:50 +01:00
parent e5c7bd1b0d
commit dae3c88020
2 changed files with 63 additions and 1 deletions
+35
View File
@@ -225,6 +225,33 @@
display: flex;
flex-direction: column;
overflow: hidden;
position: relative;
}
.scroll-to-bottom-btn {
position: absolute;
bottom: 5rem;
right: 1rem;
width: 40px;
height: 40px;
background: rgba(30, 30, 30, 0.9);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 50%;
color: #fff;
font-size: 1.25rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 5;
transition: all 0.2s;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
}
.scroll-to-bottom-btn:hover {
background: rgba(50, 50, 50, 0.95);
transform: scale(1.05);
}
.messages-container {
@@ -629,4 +656,12 @@
right: 0;
left: auto;
}
.scroll-to-bottom-btn {
width: 36px;
height: 36px;
bottom: 4.5rem;
right: 0.75rem;
font-size: 1rem;
}
}
+28 -1
View File
@@ -60,8 +60,10 @@ export default function GamePage() {
const [error, setError] = useState<string | null>(null);
const [streamingContent, setStreamingContent] = useState("");
const [showSessionMenu, setShowSessionMenu] = useState(false);
const [showScrollButton, setShowScrollButton] = useState(false);
const abortControllerRef = useRef<AbortController | null>(null);
const messagesEndRef = useRef<HTMLDivElement>(null);
const messagesContainerRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
@@ -159,10 +161,25 @@ export default function GamePage() {
scrollToBottom();
}, [session?.messages]);
// Scroll to bottom on session load
useEffect(() => {
if (session && !isInitialLoading) {
setTimeout(() => scrollToBottom(), 100);
}
}, [currentSessionId, isInitialLoading]);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
};
const handleScroll = () => {
const container = messagesContainerRef.current;
if (!container) return;
const { scrollTop, scrollHeight, clientHeight } = container;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
setShowScrollButton(distanceFromBottom > 200);
};
const startStory = async (
storyData: Story,
sessionData: GameSession,
@@ -528,7 +545,11 @@ export default function GamePage() {
</header>
<div className="game-content">
<div className="messages-container">
<div
className="messages-container"
ref={messagesContainerRef}
onScroll={handleScroll}
>
{session?.messages.map((message) => (
<div key={message.id} className={`message ${message.role}`}>
<div className="message-content">
@@ -571,6 +592,12 @@ export default function GamePage() {
<div ref={messagesEndRef} />
</div>
{showScrollButton && (
<button className="scroll-to-bottom-btn" onClick={scrollToBottom}>
</button>
)}
{/* RPG кнопки скрыты — раскомментировать при необходимости
<div className="quick-actions">
<button onClick={() => handleQuickAction("Осмотреться вокруг")}>