feat: add scroll to bottom button and auto-scroll on session load
This commit is contained in:
@@ -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
@@ -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("Осмотреться вокруг")}>
|
||||
|
||||
Reference in New Issue
Block a user