mirror of
https://github.com/meta-llama/llama-stack.git
synced 2025-08-12 04:50:39 +00:00
# What does this PR do? I've been tinkering a little with a simple chat playground in the UI, so I'm opening the PR with what's kind of a WIP. If you look at the first commit, that includes the big part of the changes. The rest of the files changed come from adding installing the `shadcn` components. Note this is missing a lot; e.g., - sessions - document upload - audio (the shadcn components install these by default from https://shadcn-chatbot-kit.vercel.app/docs/components/chat) I still need to wire up a lot more to make it actually fully functional but it does basic chat using the LS Typescript Client. Basic demo: <img width="1329" height="1430" alt="Image" src="https://github.com/user-attachments/assets/917a2096-36d4-4925-b83b-f1f2cda98698" /> <img width="1319" height="1424" alt="Image" src="https://github.com/user-attachments/assets/fab1583b-1c72-4bf3-baf2-405aee13c6bb" /> <!-- If resolving an issue, uncomment and update the line below --> <!-- Closes #[issue-number] --> ## Test Plan <!-- Describe the tests you ran to verify your changes with result summaries. *Provide clear instructions so the plan can be easily re-executed.* --> --------- Signed-off-by: Francisco Javier Arceo <farceo@redhat.com>
73 lines
2 KiB
TypeScript
73 lines
2 KiB
TypeScript
import { useEffect, useRef, useState } from "react"
|
|
|
|
// How many pixels from the bottom of the container to enable auto-scroll
|
|
const ACTIVATION_THRESHOLD = 50
|
|
// Minimum pixels of scroll-up movement required to disable auto-scroll
|
|
const MIN_SCROLL_UP_THRESHOLD = 10
|
|
|
|
export function useAutoScroll(dependencies: React.DependencyList) {
|
|
const containerRef = useRef<HTMLDivElement | null>(null)
|
|
const previousScrollTop = useRef<number | null>(null)
|
|
const [shouldAutoScroll, setShouldAutoScroll] = useState(true)
|
|
|
|
const scrollToBottom = () => {
|
|
if (containerRef.current) {
|
|
containerRef.current.scrollTop = containerRef.current.scrollHeight
|
|
}
|
|
}
|
|
|
|
const handleScroll = () => {
|
|
if (containerRef.current) {
|
|
const { scrollTop, scrollHeight, clientHeight } = containerRef.current
|
|
|
|
const distanceFromBottom = Math.abs(
|
|
scrollHeight - scrollTop - clientHeight
|
|
)
|
|
|
|
const isScrollingUp = previousScrollTop.current
|
|
? scrollTop < previousScrollTop.current
|
|
: false
|
|
|
|
const scrollUpDistance = previousScrollTop.current
|
|
? previousScrollTop.current - scrollTop
|
|
: 0
|
|
|
|
const isDeliberateScrollUp =
|
|
isScrollingUp && scrollUpDistance > MIN_SCROLL_UP_THRESHOLD
|
|
|
|
if (isDeliberateScrollUp) {
|
|
setShouldAutoScroll(false)
|
|
} else {
|
|
const isScrolledToBottom = distanceFromBottom < ACTIVATION_THRESHOLD
|
|
setShouldAutoScroll(isScrolledToBottom)
|
|
}
|
|
|
|
previousScrollTop.current = scrollTop
|
|
}
|
|
}
|
|
|
|
const handleTouchStart = () => {
|
|
setShouldAutoScroll(false)
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (containerRef.current) {
|
|
previousScrollTop.current = containerRef.current.scrollTop
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (shouldAutoScroll) {
|
|
scrollToBottom()
|
|
}
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, dependencies)
|
|
|
|
return {
|
|
containerRef,
|
|
scrollToBottom,
|
|
handleScroll,
|
|
shouldAutoScroll,
|
|
handleTouchStart,
|
|
}
|
|
}
|