--- title: Prompt Input description: A composable chat input with auto-resizing textarea and action slots --- import PromptInputDefault from "@/components/nexus-ui/examples/prompt-input/default"; import PromptInputBasic from "@/components/nexus-ui/examples/prompt-input/basic"; import GeminiInput from "@/components/nexus-ui/examples/prompt-input/gemini-input"; import PromptInputMultipleActions from "@/components/nexus-ui/examples/prompt-input/multiple-actions"; import PromptInputWithTooltips from "@/components/nexus-ui/examples/prompt-input/with-tooltips"; A flexible, composable input component for building chat interfaces. Includes an auto-resizing textarea with scroll support and customizable action slots for buttons like send, attach, and more. ## Installation ```bash npx shadcn@latest add @nexus-ui/prompt-input ``` ```bash pnpm dlx shadcn@latest add @nexus-ui/prompt-input ``` ```bash yarn dlx shadcn@latest add @nexus-ui/prompt-input ``` ```bash bunx shadcn@latest add @nexus-ui/prompt-input ```

Copy and paste the following code into your project.

Update the import paths to match your project setup.

## Usage ```tsx keepBackground import PromptInput, { PromptInputTextarea, PromptInputActions, PromptInputActionGroup, PromptInputAction, } from "@/components/nexus-ui/prompt-input"; ``` ```tsx keepBackground {/* Left-aligned actions */} {/* Right-aligned actions */} ``` ## Examples ### Basic A minimal prompt input with just a textarea and send button. ### With Multiple Actions Combine multiple action buttons in a single group. ### With Tooltips Action buttons wrapped in shadcn tooltips for descriptive hover labels. ## Vercel AI SDK Integration Connect Prompt Input to the [Vercel AI SDK](https://sdk.vercel.ai) for streaming chat interfaces.

Install the AI SDK

```bash npm install ai @ai-sdk/react @ai-sdk/openai ```

Create your chat API route

```ts title="app/api/chat/route.ts" import { convertToModelMessages, streamText, UIMessage } from "ai"; import { openai } from "@ai-sdk/openai"; export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json(); const result = streamText({ model: openai("gpt-4o-mini"), system: "You are a helpful assistant.", messages: await convertToModelMessages(messages), }); return result.toUIMessageStreamResponse(); } ```

Wire Prompt Input to `useChat`

Use `onSubmit` for Enter-to-submit. Shift+Enter inserts a new line. ```tsx "use client"; import { useState, useCallback } from "react"; import { useChat } from "@ai-sdk/react"; import { DefaultChatTransport } from "ai"; import { Button } from "@/components/ui/button"; import PromptInput, { PromptInputActions, PromptInputAction, PromptInputActionGroup, PromptInputTextarea, } from "@/components/nexus-ui/prompt-input"; import { ArrowUp02Icon, SquareIcon } from "@hugeicons/core-free-icons"; import { HugeiconsIcon } from "@hugeicons/react"; export default function ChatWithPromptInput() { const { sendMessage, status } = useChat({ transport: new DefaultChatTransport({ api: "/api/chat" }), }); const [input, setInput] = useState(""); const isLoading = status !== "ready"; const handleSubmit = useCallback( (value?: string) => { const trimmed = (value ?? input).trim(); if (trimmed) { sendMessage({ text: trimmed }); setInput(""); } }, [input, sendMessage], ); return (
{ e.preventDefault(); handleSubmit(); }} className="w-full"> setInput(e.target.value)} placeholder="Ask anything..." disabled={isLoading} />
); } ```
## API Reference ### PromptInput The root container that wraps the textarea and action bar. void (optional)", description: "Called when Enter is pressed in the textarea (without Shift). Receives the current textarea value. Use with value/onChange on PromptInputTextarea for controlled mode. Shift+Enter inserts a new line.", }, className: { type: "string", description: "Additional CSS classes to apply to the container.", }, onClick: { type: "React.MouseEventHandler", description: "Called after the internal click handler. The internal handler focuses the textarea when clicking non-interactive areas.", }, }} /> ### PromptInputTextarea An auto-resizing textarea wrapped in a scroll area. Accepts all standard `textarea` props including `disabled` and `onKeyDown`. Use `onSubmit` on PromptInput for Enter-to-submit; Shift+Enter inserts a new line. ", description: "Called when the value changes. Use with value for controlled mode.", }, onKeyDown: { type: "React.KeyboardEventHandler", description: "Called when a key is pressed. Fired after the internal Enter/Shift+Enter handler.", }, placeholder: { type: "string", default: '"How can I help you today?"', description: "Placeholder text displayed when the textarea is empty.", }, ref: { type: "React.Ref", description: "Forwarded ref to the textarea element. Merged with the internal ref used for click-to-focus.", }, value: { type: "string", description: "Controlled value. Use with onChange for controlled mode.", }, }} /> ### PromptInputActions A flex container for action buttons. Uses `justify-between` to position child groups at opposite ends. ### PromptInputActionGroup Groups related action buttons together with a horizontal layout. ### PromptInputAction A wrapper for individual action buttons. Supports polymorphism via `asChild`.