Skip to content

Commit 932648c

Browse files
committed
feat: migrate to AI elements;
1 parent 539b48e commit 932648c

File tree

20 files changed

+2747
-245
lines changed

20 files changed

+2747
-245
lines changed

apps/dashboard/app/(main)/websites/[id]/assistant/components/chat-section.tsx

Lines changed: 45 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@ import {
1414
import { useAtom } from 'jotai';
1515
import { useEffect, useRef, useState } from 'react';
1616
import { Button } from '@/components/ui/button';
17-
import { Input } from '@/components/ui/input';
1817
import { Skeleton } from '@/components/ui/skeleton';
18+
import {
19+
PromptInput,
20+
PromptInputTextarea,
21+
PromptInputSubmit,
22+
PromptInputToolbar,
23+
} from '@/components/ai-elements/prompt-input';
24+
import {
25+
Conversation,
26+
ConversationContent,
27+
ConversationScrollButton,
28+
} from '@/components/ai-elements/conversation';
29+
import { Suggestions, Suggestion } from '@/components/ai-elements/suggestion';
1930
import { cn } from '@/lib/utils';
2031
import {
2132
inputValueAtom,
@@ -81,7 +92,7 @@ export default function ChatSection() {
8192
const [selectedModel] = useAtom(modelAtom);
8293
const [websiteData] = useAtom(websiteDataAtom);
8394

84-
const inputRef = useRef<HTMLInputElement>(null);
95+
const inputRef = useRef<HTMLTextAreaElement>(null);
8596
const bottomRef = useRef<HTMLDivElement>(null);
8697
const { sendMessage, handleKeyPress, scrollToBottom, resetChat } = useChat();
8798
const [showChatHistory, setShowChatHistory] = useState(false);
@@ -201,12 +212,9 @@ export default function ChatSection() {
201212
</div>
202213

203214
{/* Messages Area */}
204-
<div
205-
className="min-h-0 flex-1 overflow-y-auto overscroll-contain"
206-
ref={scrollAreaRef}
207-
>
208-
{/* Welcome State */}
209-
<div className="min-h-full px-4 py-3">
215+
<Conversation className="min-h-0 flex-1">
216+
<ConversationContent className="min-h-full">
217+
<ConversationScrollButton />
210218
{!(hasMessages || isLoading) && (
211219
<div className="fade-in-0 slide-in-from-bottom-4 h-full animate-in space-y-6 duration-500">
212220
<div className="flex h-full flex-col justify-between">
@@ -232,37 +240,24 @@ export default function ChatSection() {
232240
<LightningIcon className="h-4 w-4" weight="duotone" />
233241
<span>Try these examples:</span>
234242
</div>
235-
<div className="grid grid-cols-1 gap-2 md:grid-cols-2">
236-
{quickQuestions.map((question, index) => (
237-
<Button
238-
className={cn(
239-
'h-auto px-4 py-3 text-left font-normal text-sm',
240-
'hover:bg-gradient-to-r hover:from-primary/5 hover:to-accent/5',
241-
'border-dashed transition-all duration-300 hover:border-solid',
242-
'fade-in-0 slide-in-from-left-2 animate-in'
243-
)}
244-
disabled={isLoading || isRateLimited}
243+
<Suggestions>
244+
{quickQuestions.map((question) => (
245+
<Suggestion
245246
key={question.text}
246-
onClick={() => {
247+
suggestion={question.text}
248+
disabled={isLoading || isRateLimited}
249+
onClick={(suggestion) => {
247250
if (!(isLoading || isRateLimited)) {
248-
sendMessage(question.text);
251+
sendMessage(suggestion);
249252
scrollToBottom();
250253
}
251254
}}
252-
size="sm"
253-
style={{ animationDelay: `${index * 100}ms` }}
254-
variant="outline"
255255
>
256-
<question.icon className="mr-3 h-4 w-4 flex-shrink-0 text-primary/70" />
257-
<div className="flex-1">
258-
<div className="font-medium">{question.text}</div>
259-
<div className="text-muted-foreground text-xs capitalize">
260-
{question.type} response
261-
</div>
262-
</div>
263-
</Button>
256+
<question.icon className="mr-2 h-4 w-4 text-primary/70" />
257+
{question.text}
258+
</Suggestion>
264259
))}
265-
</div>
260+
</Suggestions>
266261
</div>
267262
</div>
268263
</div>
@@ -274,33 +269,23 @@ export default function ChatSection() {
274269
{messages.map((message) => (
275270
<MessageBubble key={message.id} message={message} />
276271
))}
277-
<div ref={bottomRef} />
278272
</div>
279273
)}
280-
</div>
281-
</div>
274+
</ConversationContent>
275+
</Conversation>
282276

283277
{/* Enhanced Input Area */}
284278
<div className="flex-shrink-0 border-t bg-gradient-to-r from-muted/10 to-muted/5 p-4">
285279
<div className="relative">
286-
<div className={cn('flex gap-3')}>
287-
<Input
288-
className={cn(
289-
'h-11 flex-1 rounded-xl border-2 bg-background/50 backdrop-blur-sm',
290-
'placeholder:text-muted-foreground/60',
291-
'focus:border-primary/30 focus:bg-background/80',
292-
'transition-all duration-200'
293-
)}
280+
<PromptInput
281+
onSubmit={(e) => {
282+
e.preventDefault();
283+
handleSend();
284+
}}
285+
>
286+
<PromptInputTextarea
294287
disabled={isLoading || isRateLimited}
295288
onChange={(e) => setInputValue(e.target.value)}
296-
onKeyDown={(e) => {
297-
if (e.key === 'Enter' && !e.shiftKey) {
298-
e.preventDefault();
299-
handleSend();
300-
} else {
301-
handleKeyPress(e);
302-
}
303-
}}
304289
placeholder={
305290
isLoading
306291
? 'Databunny is thinking...'
@@ -310,34 +295,17 @@ export default function ChatSection() {
310295
}
311296
ref={inputRef}
312297
value={inputValue}
298+
minHeight={44}
299+
maxHeight={120}
313300
/>
314-
<Button
315-
className={cn(
316-
'h-11 w-11 flex-shrink-0 rounded-xl',
317-
'bg-gradient-to-r from-primary to-primary/80',
318-
'hover:from-primary/90 hover:to-primary/70',
319-
'shadow-lg transition-all duration-200',
320-
(!inputValue.trim() || isRateLimited) &&
321-
!isLoading &&
322-
'opacity-50'
323-
)}
324-
disabled={!inputValue.trim() || isLoading || isRateLimited}
325-
onClick={handleSend}
326-
size="icon"
327-
title="Send message"
328-
>
329-
<PaperPlaneRightIcon
330-
className={cn(
331-
'h-4 w-4',
332-
inputValue.trim() &&
333-
!isLoading &&
334-
!isRateLimited &&
335-
'scale-110'
336-
)}
337-
weight="duotone"
301+
<PromptInputToolbar>
302+
<div />
303+
<PromptInputSubmit
304+
disabled={!inputValue.trim() || isLoading || isRateLimited}
305+
status={isLoading ? 'submitted' : undefined}
338306
/>
339-
</Button>
340-
</div>
307+
</PromptInputToolbar>
308+
</PromptInput>
341309

342310
{/* Helper text */}
343311
<div className="mt-3 flex flex-wrap items-center justify-between gap-2 text-xs">

0 commit comments

Comments
 (0)