Join our Discord Community

React AI Prompt Input

Auto-resizing textarea with toolbar for chat interfaces. Build conversational UIs with React, Next.js, and TypeScript, featuring submit buttons, model selection, and keyboard shortcuts for shadcn/ui applications.

Trying to implement AI Elements?

Join our Discord community for help from other developers.


Auto-resizing textarea with toolbar for AI prompts in conversational AI applications. This free open source React component handles Enter submits, Shift+Enter adds new lines, and includes model selection with proper form handling for Next.js projects.

Auto-resizing prompt input with toolbar

Textarea with submit button and model selection:

Loading component...

Automatically adjusts height based on content in React applications, handles Enter/Shift+Enter shortcuts correctly in TypeScript components, and provides a flexible toolbar system for JavaScript frameworks. Integrates seamlessly with Vercel AI SDK status.

Installation

npx shadcn@latest add https://www.shadcn.io/registry/ai.json
npx shadcn@latest add https://www.shadcn.io/registry/ai.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/ai.json
bunx shadcn@latest add https://www.shadcn.io/registry/ai.json

Usage

import {
  PromptInput,
  PromptInputTextarea,
  PromptInputToolbar,
  PromptInputSubmit,
} from "@/components/ai/prompt-input";

<PromptInput onSubmit={() => {}}>
  <PromptInputTextarea
    value={input}
    onChange={(e) => setInput(e.currentTarget.value)}
    placeholder="Type your message..."
  />
  <PromptInputToolbar>
    <PromptInputSubmit disabled={!input.trim()} />
  </PromptInputToolbar>
</PromptInput>;

Why not just use a regular textarea?

Fixed-height textareas cut off AI prompts in React applications. Users write long, complex prompts and need to see what they're typing without scrolling in a tiny box in Next.js projects.

Enter/Shift+Enter behavior has to be right in JavaScript implementations. Users expect Enter to submit, Shift+Enter for new lines in TypeScript components. Get this wrong and your chat feels broken.

Usage with Vercel AI SDK

Complete chat interface using Vercel AI SDK with model selection and status integration in React applications:

"use client";

import {
  PromptInput,
  PromptInputTextarea,
  PromptInputToolbar,
  PromptInputTools,
  PromptInputButton,
  PromptInputSubmit,
  PromptInputModelSelect,
  PromptInputModelSelectTrigger,
  PromptInputModelSelectContent,
  PromptInputModelSelectItem,
  PromptInputModelSelectValue,
} from "@/components/ai/prompt-input";
import {
  Conversation,
  ConversationContent,
} from "@/components/ai/conversation";
import { Message, MessageContent } from "@/components/ai/message";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";
import { MicIcon, PaperclipIcon } from "lucide-react";

const models = [
  { id: "gpt-4o", name: "GPT-4o" },
  { id: "claude-3-5-sonnet-20241022", name: "Claude 3.5 Sonnet" },
];

export default function Chat() {
  const [input, setInput] = useState("");
  const [selectedModel, setSelectedModel] = useState(models[0].id);

  const { messages, append, status } = useChat({
    body: { model: selectedModel },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (input.trim()) {
      append({ role: "user", content: input });
      setInput("");
    }
  };

  return (
    <div className="flex flex-col h-full max-w-4xl mx-auto">
      <Conversation>
        <ConversationContent>
          {messages.map((message) => (
            <Message from={message.role} key={message.id}>
              <MessageContent>{message.content}</MessageContent>
            </Message>
          ))}
        </ConversationContent>
      </Conversation>

      <PromptInput onSubmit={handleSubmit}>
        <PromptInputTextarea
          value={input}
          onChange={(e) => setInput(e.currentTarget.value)}
          placeholder="Type your message..."
        />
        <PromptInputToolbar>
          <PromptInputTools>
            <PromptInputButton>
              <PaperclipIcon size={16} />
            </PromptInputButton>
            <PromptInputButton>
              <MicIcon size={16} />
              <span>Voice</span>
            </PromptInputButton>
            <PromptInputModelSelect
              value={selectedModel}
              onValueChange={setSelectedModel}
            >
              <PromptInputModelSelectTrigger>
                <PromptInputModelSelectValue />
              </PromptInputModelSelectTrigger>
              <PromptInputModelSelectContent>
                {models.map((model) => (
                  <PromptInputModelSelectItem key={model.id} value={model.id}>
                    {model.name}
                  </PromptInputModelSelectItem>
                ))}
              </PromptInputModelSelectContent>
            </PromptInputModelSelect>
          </PromptInputTools>
          <PromptInputSubmit disabled={!input.trim()} status={status} />
        </PromptInputToolbar>
      </PromptInput>
    </div>
  );
}

Backend route handling model selection:

// app/api/chat/route.ts
import { streamText, convertToModelMessages } from "ai";

export async function POST(req: Request) {
  const { messages, model } = await req.json();

  const result = streamText({
    model: model || "openai/gpt-4o",
    messages: convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}

Features

  • Auto-resizing textarea with configurable min/max height (prevents layout jumps) in React applications
  • Keyboard shortcuts that work like users expect (Enter to submit, Shift+Enter for new lines) in TypeScript components
  • Submit button states that integrate with Vercel AI SDK status in Next.js projects
  • Flexible toolbar system for custom actions and model selection in JavaScript frameworks
  • Form validation that prevents empty submissions
  • Proper focus management for continuous conversation
  • Works with any Vercel AI SDK setup and AI chat applications
  • Free open source component designed for conversational AI interfaces and prompt-based applications

API Reference

PromptInput

Form container for the prompt input system.

PropTypeDescription
onSubmitFormEventHandlerForm submission handler
classNamestringAdditional CSS classes
...propsHTMLAttributes<HTMLFormElement>Standard form attributes

PromptInputTextarea

Auto-resizing textarea with keyboard shortcuts.

PropTypeDefaultDescription
placeholderstring"What would you like to know?"Placeholder text
minHeightnumber48Minimum height in pixels
maxHeightnumber164Maximum height in pixels
classNamestring-Additional CSS classes
...propsComponentProps<typeof Textarea>-Textarea component props

PromptInputToolbar

Container for toolbar actions and submit button.

PropTypeDescription
classNamestringAdditional CSS classes
...propsHTMLAttributes<HTMLDivElement>Standard div attributes

PromptInputTools

Container for tool buttons and controls.

PropTypeDescription
classNamestringAdditional CSS classes
...propsHTMLAttributes<HTMLDivElement>Standard div attributes

PromptInputButton

Toolbar button with automatic sizing.

PropTypeDefaultDescription
variantButtonVariant"ghost"Button style variant
sizeButtonSize"icon" (auto)Button size
classNamestring-Additional CSS classes
...propsComponentProps<typeof Button>-Button component props

PromptInputSubmit

Submit button with status indicators.

PropTypeDefaultDescription
statusChatStatus-Current chat status for icon display
variantButtonVariant"default"Button style variant
sizeButtonSize"icon"Button size
classNamestring-Additional CSS classes
...propsComponentProps<typeof Button>-Button component props

Model Selection Components

All model selection components forward props to their underlying shadcn/ui Select components:

  • PromptInputModelSelect - Select root component
  • PromptInputModelSelectTrigger - Select trigger with custom styling
  • PromptInputModelSelectContent - Select dropdown content
  • PromptInputModelSelectItem - Individual model option
  • PromptInputModelSelectValue - Selected value display

Keyboard interactions

KeyDescription
EnterSubmit form (when not in composition)
Shift + EnterInsert new line
TabNavigate between toolbar elements
EscapeBlur textarea

Prompt input gotchas

Unconstrained auto-resize breaks layouts: Set reasonable minHeight/maxHeight in React applications. Long AI prompts can grow to 500+ lines without constraints in TypeScript components.

Mobile keyboard inconsistency: Enter behavior varies across mobile keyboards in JavaScript implementations. Test on real devices, not just desktop browsers in Next.js projects.

Empty input submission: Users will hit Enter on empty textareas in React applications. Validate and disable submit for empty/whitespace-only input.

Model selection persistence: Consider saving user's model preference to localStorage in TypeScript projects. They don't want to reselect every session.

Focus management after submit: Return focus to the textarea after successful submission in React components so users can continue the conversation.

Integration with other components

Works great with Conversation for scrolling chat interfaces in React applications. Combine with Message for complete chat UI in Next.js projects. Add Actions for message interactions like copy, regenerate, or edit. This free open source component integrates seamlessly with modern JavaScript frameworks.

Questions developers actually ask