{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "chat-app-shadcnui", "type": "registry:component", "title": "Chat App", "description": "Fully functional chat interface with animated messages", "registryDependencies": [ "button" ], "dependencies": [ "framer-motion", "react" ], "files": [ { "path": "@uitripled/react-shadcn/src/components/components/chat/chat-app.tsx", "content": "\"use client\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\nimport { Input } from \"@/components/ui/input\";\nimport { ScrollArea } from \"@/components/ui/scroll-area\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Bot, Loader2, Send, User } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\n\ntype Message = {\n id: number;\n text: string;\n sender: \"user\" | \"bot\";\n timestamp: Date;\n};\n\nconst initialMessages: Message[] = [\n {\n id: 1,\n text: \"Hello! How can I help you today?\",\n sender: \"bot\",\n timestamp: new Date(Date.now() - 60000),\n },\n {\n id: 2,\n text: \"Hi there! I was wondering about your features.\",\n sender: \"user\",\n timestamp: new Date(Date.now() - 30000),\n },\n {\n id: 3,\n text: \"Of course! What would you like to know?\",\n sender: \"bot\",\n timestamp: new Date(Date.now() - 15000),\n },\n];\n\nexport function ChatApp() {\n const [messages, setMessages] = useState(initialMessages);\n const [inputValue, setInputValue] = useState(\"\");\n const [isTyping, setIsTyping] = useState(false);\n const scrollAreaRef = useRef(null);\n const inputRef = useRef(null);\n\n useEffect(() => {\n // Auto-scroll to bottom when new messages arrive\n if (scrollAreaRef.current) {\n const scrollContainer = scrollAreaRef.current.querySelector(\n \"[data-radix-scroll-area-viewport]\"\n );\n if (scrollContainer) {\n scrollContainer.scrollTop = scrollContainer.scrollHeight;\n }\n }\n }, [messages, isTyping]);\n\n const formatTime = (date: Date): string => {\n const hours = date.getHours();\n const minutes = date.getMinutes();\n const ampm = hours >= 12 ? \"PM\" : \"AM\";\n const displayHours = hours % 12 || 12;\n const displayMinutes = minutes.toString().padStart(2, \"0\");\n return `${displayHours}:${displayMinutes} ${ampm}`;\n };\n\n const handleSend = () => {\n const trimmed = inputValue.trim();\n if (!trimmed) return;\n\n const userMessage: Message = {\n id: Date.now(),\n text: trimmed,\n sender: \"user\",\n timestamp: new Date(),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n setInputValue(\"\");\n setIsTyping(true);\n\n // Simulate bot response with typing indicator\n setTimeout(() => {\n const botMessage: Message = {\n id: Date.now() + 1,\n text: \"Thanks for your message! This is an automated response. I can help you with various tasks and answer your questions.\",\n sender: \"bot\",\n timestamp: new Date(),\n };\n setMessages((prev) => [...prev, botMessage]);\n setIsTyping(false);\n inputRef.current?.focus();\n }, 1500);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n };\n\n return (\n
\n \n {/* Header */}\n \n
\n \n \n \n \n
\n

AI Assistant

\n

\n Always here to help\n

\n
\n
\n \n\n {/* Messages */}\n \n \n \n {messages.map((message) => (\n \n \n {message.sender === \"user\" ? (\n \n ) : (\n \n )}\n \n \n \n

{message.text}

\n \n \n {formatTime(message.timestamp)}\n \n
\n \n ))}\n \n\n {/* Typing Indicator */}\n \n {isTyping && (\n \n
\n \n
\n
\n \n \n \n
\n \n )}\n
\n \n \n\n {/* Input */}\n \n
\n setInputValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Type your message...\"\n className=\"flex-1 rounded-full border-2 px-4 focus-visible:ring-2 focus-visible:ring-primary\"\n aria-label=\"Message input\"\n disabled={isTyping}\n />\n \n {isTyping ? (\n \n ) : (\n \n )}\n \n
\n \n \n \n );\n}\n", "type": "registry:component", "target": "components/uitripled/chat-app-shadcnui.tsx" } ] }