Components
Loading preview...
import React, { useMemo, useRef, useEffect } from "react"
import { PromptInputBox } from "@/components/ui/chat-page"
import { MeshGradient } from "@paper-design/shaders-react"
import { cn } from "@/lib/utils"
type Role = "user" | "assistant"
interface Message {
id: string
role: Role
content: string
}
export default function DemoOne() {
const [messages, setMessages] = React.useState<Message[]>([
{ id: "m1", role: "assistant", content: "Hi! I’m your chat assistant. How can I help today?" },
])
// Suggestions and autocomplete lists (no AI SDK; simple UX helpers)
const suggestions = useMemo(
() => [
"Summarize this document",
"Brainstorm feature ideas",
"Explain like I'm five",
"Write a polite email",
"Refactor this code",
"Create a test plan",
],
[],
)
const autocompleteOptions = useMemo(
() => [
"Summarize this",
"Summarize the following",
"Explain step by step",
"Explain like I'm five",
"Outline a plan for",
"Brainstorm ideas for",
"Write a polite email about",
"Draft a message to",
"Refactor this code",
"Create a test plan",
],
[],
)
const containerRef = useRef<HTMLDivElement | null>(null)
const listRef = useRef<HTMLDivElement | null>(null)
const scrollToBottom = () => {
requestAnimationFrame(() => {
listRef.current?.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" })
})
}
useEffect(() => {
scrollToBottom()
}, [messages.length])
const handleSend = (text: string) => {
const userMsg: Message = { id: crypto.randomUUID(), role: "user", content: text }
setMessages((prev) => [...prev, userMsg])
// simple mock assistant reply
const reply = mockReply(text)
setTimeout(() => {
setMessages((prev) => [...prev, { id: crypto.randomUUID(), role: "assistant", content: reply }])
}, 500)
}
return (
<main ref={containerRef} className="relative min-h-[100svh] bg-background/20 text-foreground w-full h-full ">
{/* Paper texture shader background */}
<section className="fixed inset-0 -z-10 block">
<MeshGradient
className="absolute inset-0 w-full h-full"
colors={["#000000", "#8b5cf6", "#ffffff", "#1e1b4b", "#4c1d95"]}
speed={0.3}
backgroundColor="#000000"
/>
<MeshGradient
className="absolute inset-0 w-full h-full opacity-60"
colors={["#000000", "#ffffff", "#8b5cf6", "#000000"]}
speed={0.2}
wireframe="true"
backgroundColor="transparent"
/>
</section>
{/* Header */}
{/* Messages */}
<section className="mx-auto max-w-4xl px-4">
<div
ref={listRef}
className="mt-6 mb-28 md:mb-32 h-[calc(100svh-220px)] overflow-y-auto rounded-xl border border-border/60 bg-background/20 backdrop-blur-sm"
>
<ul className="p-4 md:p-6 space-y-4">
{messages.map((m) => (
<li key={m.id} className="flex w-full">
{m.role === "assistant" ? (
<div className="ml-0 mr-auto max-w-[88%] rounded-2xl border border-border/60 bg-card/60 backdrop-blur-sm px-4 py-3">
<p className="text-sm leading-relaxed text-foreground">{m.content}</p>
</div>
) : (
<div className="ml-auto mr-0 max-w-[88%] rounded-2xl border border-border/70 bg-primary/10 text-foreground px-4 py-3">
<p className="text-sm leading-relaxed">{m.content}</p>
</div>
)}
</li>
))}
</ul>
</div>
</section>
{/* Composer */}
<div className="fixed inset-x-0 bottom-0 z-20">
<div className="mx-auto max-w-3xl px-4 py-3">
<PromptInputBox
onSend={(msg) => handleSend(msg)}
// glassy override: keep your input’s design but make it translucent with blur
className={cn(
"!bg-background/35 !border-white/10 backdrop-blur-xl shadow-lg",
"supports-[backdrop-filter]:bg-background/35",
)}
autocompleteOptions={autocompleteOptions}
placeholder="Send a message..."
/>
<p className="mt-2 text-center text-xs text-foreground/50">
Tips: Use suggestions above or start typing — press Tab to autocomplete.
</p>
</div>
</div>
</main>
)
}
// very simple, deterministic reply for demo purposes
function mockReply(input: string): string {
const trimmed = input.trim()
if (!trimmed) return "Could you provide more details?"
if (/summarize/i.test(trimmed)) return "Sure — paste the text and I’ll summarize it concisely."
if (/brainstorm/i.test(trimmed)) return "Let’s brainstorm: 1) Define goals 2) Gather ideas 3) Group and prioritize."
if (/explain/i.test(trimmed)) return "Happy to explain — what part is most confusing?"
if (/email/i.test(trimmed)) return "What’s the context and tone you’d like? I can draft a polite email."
if (/refactor/i.test(trimmed)) return "Paste the code and I’ll suggest a clearer, more maintainable structure."
if (/test plan/i.test(trimmed)) return "We can outline objectives, scope, cases, and acceptance criteria."
return "Got it. Tell me more or drop content to work with."
}