Chatbot
Suggestion
A suggestion component that displays a horizontal row of clickable suggestions for user interaction.
The Suggestion component displays a horizontal row of clickable suggestions for user interaction.
"use client";import { Suggestion, Suggestions } from "@/components/ai-elements/elements/suggestion";const suggestions = [ "What are the latest trends in AI?", "How does machine learning work?", "Explain quantum computing", "Best practices for React development", "Tell me about TypeScript benefits", "How to optimize database queries?", "What is the difference between SQL and NoSQL?", "Explain cloud computing basics",];const Example = () => { const handleSuggestionClick = (suggestion: string) => { console.log("Selected suggestion:", suggestion); }; return ( <Suggestions> {suggestions.map((suggestion) => ( <Suggestion key={suggestion} onClick={handleSuggestionClick} suggestion={suggestion} /> ))} </Suggestions> );};export default Example;Installation
npx ai-elements@latest add suggestionnpx shadcn@latest add @ai-elements/suggestion"use client";import { Button } from "@repo/shadcn-ui/components/ui/button";import { ScrollArea, ScrollBar,} from "@repo/shadcn-ui/components/ui/scroll-area";import { cn } from "@repo/shadcn-ui/lib/utils";import type { ComponentProps } from "react";export type SuggestionsProps = ComponentProps<typeof ScrollArea>;export const Suggestions = ({ className, children, ...props}: SuggestionsProps) => ( <ScrollArea className="w-full overflow-x-auto whitespace-nowrap" {...props}> <div className={cn("flex w-max flex-nowrap items-center gap-2", className)}> {children} </div> <ScrollBar className="hidden" orientation="horizontal" /> </ScrollArea>);export type SuggestionProps = Omit<ComponentProps<typeof Button>, "onClick"> & { suggestion: string; onClick?: (suggestion: string) => void;};export const Suggestion = ({ suggestion, onClick, className, variant = "outline", size = "sm", children, ...props}: SuggestionProps) => { const handleClick = () => { onClick?.(suggestion); }; return ( <Button className={cn("cursor-pointer rounded-full px-4", className)} onClick={handleClick} size={size} type="button" variant={variant} {...props} > {children || suggestion} </Button> );};Usage
import { Suggestion, Suggestions } from '@/components/ai-elements/suggestion';<Suggestions>
<Suggestion suggestion="What are the latest trends in AI?" />
</Suggestions>Usage with AI SDK
Build a simple input with suggestions users can click to send a message to the LLM.
Add the following component to your frontend:
'use client';
import {
Input,
PromptInputTextarea,
PromptInputSubmit,
} from '@/components/ai-elements/prompt-input';
import { Suggestion, Suggestions } from '@/components/ai-elements/suggestion';
import { useState } from 'react';
import { useChat } from '@ai-sdk/react';
const suggestions = [
'Can you explain how to play tennis?',
'What is the weather in Tokyo?',
'How do I make a really good fish taco?',
];
const SuggestionDemo = () => {
const [input, setInput] = useState('');
const { sendMessage, status } = useChat();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
sendMessage({ text: input });
setInput('');
}
};
const handleSuggestionClick = (suggestion: string) => {
sendMessage({ text: suggestion });
};
return (
<div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]">
<div className="flex flex-col h-full">
<div className="flex flex-col gap-4">
<Suggestions>
{suggestions.map((suggestion) => (
<Suggestion
key={suggestion}
onClick={handleSuggestionClick}
suggestion={suggestion}
/>
))}
</Suggestions>
<Input
onSubmit={handleSubmit}
className="mt-4 w-full max-w-2xl mx-auto relative"
>
<PromptInputTextarea
value={input}
placeholder="Say something..."
onChange={(e) => setInput(e.currentTarget.value)}
className="pr-12"
/>
<PromptInputSubmit
status={status === 'streaming' ? 'streaming' : 'ready'}
disabled={!input.trim()}
className="absolute bottom-1 right-1"
/>
</Input>
</div>
</div>
</div>
);
};
export default SuggestionDemo;Features
- Horizontal row of clickable suggestion buttons
- Customizable styling with variant and size options
- Flexible layout that wraps suggestions on smaller screens
- onClick callback that emits the selected suggestion string
- Support for both individual suggestions and suggestion lists
- Clean, modern styling with hover effects
- Responsive design with mobile-friendly touch targets
- TypeScript support with proper type definitions
Examples
Usage with AI Input
"use client";import { PromptInput, PromptInputButton, PromptInputFooter, type PromptInputMessage, PromptInputModelSelect, PromptInputModelSelectContent, PromptInputModelSelectItem, PromptInputModelSelectTrigger, PromptInputModelSelectValue, PromptInputSubmit, PromptInputTextarea, PromptInputTools,} from "@/components/ai-elements/elements/prompt-input";import { Suggestion, Suggestions } from "@/components/ai-elements/elements/suggestion";import { GlobeIcon, MicIcon, PlusIcon, SendIcon } from "lucide-react";import { nanoid } from "nanoid";import { useState } from "react";const suggestions: { key: string; value: string }[] = [ { key: nanoid(), value: "What are the latest trends in AI?" }, { key: nanoid(), value: "How does machine learning work?" }, { key: nanoid(), value: "Explain quantum computing" }, { key: nanoid(), value: "Best practices for React development" }, { key: nanoid(), value: "Tell me about TypeScript benefits" }, { key: nanoid(), value: "How to optimize database queries?" }, { key: nanoid(), value: "What is the difference between SQL and NoSQL?" }, { key: nanoid(), value: "Explain cloud computing basics" },];const models = [ { id: "gpt-4", name: "GPT-4" }, { id: "gpt-3.5-turbo", name: "GPT-3.5 Turbo" }, { id: "claude-2", name: "Claude 2" }, { id: "claude-instant", name: "Claude Instant" }, { id: "palm-2", name: "PaLM 2" }, { id: "llama-2-70b", name: "Llama 2 70B" }, { id: "llama-2-13b", name: "Llama 2 13B" }, { id: "cohere-command", name: "Command" }, { id: "mistral-7b", name: "Mistral 7B" },];const Example = () => { const [model, setModel] = useState<string>(models[0].id); const [text, setText] = useState<string>(""); const handleSubmit = (message: PromptInputMessage) => { const hasText = Boolean(message.text); const hasAttachments = Boolean(message.files?.length); if (!(hasText || hasAttachments)) { return; } console.log("Submitted message:", message.text || "Sent with attachments"); console.log("Attached files:", message.files); }; const handleSuggestionClick = (suggestion: string) => { setText(suggestion); }; return ( <div className="grid gap-4"> <Suggestions> {suggestions.map((suggestion) => ( <Suggestion key={suggestion.key} onClick={handleSuggestionClick} suggestion={suggestion.value} /> ))} </Suggestions> <PromptInput onSubmit={handleSubmit}> <PromptInputTextarea onChange={(e) => setText(e.target.value)} placeholder="Ask me about anything..." value={text} /> <PromptInputFooter> <PromptInputTools> <PromptInputButton> <PlusIcon size={16} /> </PromptInputButton> <PromptInputButton> <MicIcon size={16} /> </PromptInputButton> <PromptInputButton> <GlobeIcon size={16} /> <span>Search</span> </PromptInputButton> <PromptInputModelSelect onValueChange={setModel} value={model}> <PromptInputModelSelectTrigger> <PromptInputModelSelectValue /> </PromptInputModelSelectTrigger> <PromptInputModelSelectContent> {models.map((model) => ( <PromptInputModelSelectItem key={model.id} value={model.id}> {model.name} </PromptInputModelSelectItem> ))} </PromptInputModelSelectContent> </PromptInputModelSelect> </PromptInputTools> <PromptInputSubmit> <SendIcon size={16} /> </PromptInputSubmit> </PromptInputFooter> </PromptInput> </div> );};export default Example;Props
<Suggestions />
Prop
Type
<Suggestion />
Prop
Type