feat(UI): adding MVP playground UI (#2828)

# 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>
This commit is contained in:
Francisco Arceo 2025-07-30 22:44:16 -04:00 committed by GitHub
parent d6ae2b0f47
commit f3d5459647
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 4876 additions and 31 deletions

View file

@ -0,0 +1,39 @@
import { useLayoutEffect, useRef } from "react"
interface UseAutosizeTextAreaProps {
ref: React.RefObject<HTMLTextAreaElement | null>
maxHeight?: number
borderWidth?: number
dependencies: React.DependencyList
}
export function useAutosizeTextArea({
ref,
maxHeight = Number.MAX_SAFE_INTEGER,
borderWidth = 0,
dependencies,
}: UseAutosizeTextAreaProps) {
const originalHeight = useRef<number | null>(null)
useLayoutEffect(() => {
if (!ref.current) return
const currentRef = ref.current
const borderAdjustment = borderWidth * 2
if (originalHeight.current === null) {
originalHeight.current = currentRef.scrollHeight - borderAdjustment
}
currentRef.style.removeProperty("height")
const scrollHeight = currentRef.scrollHeight
// Make sure we don't go over maxHeight
const clampedToMax = Math.min(scrollHeight, maxHeight)
// Make sure we don't go less than the original height
const clampedToMin = Math.max(clampedToMax, originalHeight.current)
currentRef.style.height = `${clampedToMin + borderAdjustment}px`
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [maxHeight, ref, ...dependencies])
}