Chat-style AI composer with agent and model chips and an Apple Intelligence-style gradient wave on send.
npx shadcn@latest add @iconiq/ai-input"use client";
import { Archive, Camera, LayoutGrid, Paperclip, Plug } from "lucide-react";
import {
AIInput,
type AIInputMenuItem,
type PromptSettingGroup,
} from "@/components/ui/ai-input";
// Featured row for the selected model, submenu for effort level.
const settingGroups: PromptSettingGroup[] = [
{
id: "model",
label: "Model",
display: "featured",
options: [
{ value: "claude-5", label: "Claude 5", description: "Most capable" },
{ value: "claude-5-fast", label: "Claude 5 Fast", description: "Faster" },
],
},
{
id: "effort",
label: "Effort",
display: "submenu",
options: [
{ value: "high", label: "High" },
{ value: "medium", label: "Medium" },
{ value: "low", label: "Low" },
],
},
];
// Use `shortcut` to show a keyboard hint. Pass `items` for a one-level submenu.
const menuItems: AIInputMenuItem[] = [
{ value: "add-files", label: "Add files or photos", icon: Paperclip, shortcut: "⌘U" },
{ value: "screenshot", label: "Take a screenshot", icon: Camera },
{
value: "add-to-project",
label: "Add to project",
icon: Archive,
items: [
{ value: "new-project", label: "New project" },
{ value: "existing-project", label: "Existing project" },
],
},
{ value: "sep-1", type: "separator" },
{
value: "skills",
label: "Skills",
icon: LayoutGrid,
items: [
{ value: "skill-creator", label: "skill-creator" },
{ value: "manage-skills", label: "Manage skills" },
{ value: "browse-skills", label: "Browse skills" },
],
},
{ value: "add-connector", label: "Add connector", icon: Plug },
];
export function AIInputPreview() {
return (
<div className="mx-auto w-full max-w-2xl px-4 py-10">
<AIInput
menuItems={menuItems}
settingGroups={settingGroups}
onMenuSelect={(value) => console.log("menu:", value)}
onSettingsChange={(settings) => console.log("settings:", settings)}
onSend={(message, meta) => console.log(message, meta)}
placeholder="Ask for follow-up changes"
/>
</div>
);
}agentsOptions for the agent chip on the left of the footer. Each option has `value` and `label`. Omit to hide the chip.
Type AIInputOption[]
defaultAgentInitially selected agent value. Falls back to the first agent option.
Type string
modelsOptions for the model chip on the right of the footer. Omit to hide the chip.
Type AIInputOption[]
defaultModelInitially selected model value. Falls back to the first model option.
Type string
menuItemsItems for the plus menu. Each item has `value`, `label`, and optional `icon`. Set `type` to `"toggle"` for a switch row (with optional `defaultChecked`) or `"separator"` for a divider. Action items accept a per-item `onClick` and toggles a per-item `onCheckedChange`, firing alongside the component-level callbacks. Pass nested `items` to turn an action into a one-level submenu with a slide transition and back button. Omit to make the plus button a plain attachment button.
Type AIInputMenuItem[]
placeholderPlaceholder copy for the textarea.
Type string·Default "Ask for follow-up changes"
showMessagesRender sent messages as right-aligned chat bubbles above the composer. Disable when you render your own thread.
Type boolean·Default true
onSendCalled with the trimmed message and the current agent and model picks when the user presses Enter or clicks send.
Type (message: string, meta: { agent: string; model: string }) => void
onMicClickCalled when the microphone button is clicked.
Type () => void
onPlusClickCalled when the plus button is clicked and no `menuItems` are provided.
Type () => void
onMenuSelectCalled with the item's `value` when an action item — top-level or inside a submenu — is selected in the plus menu.
Type (value: string) => void
onMenuToggleCalled when a toggle item in the plus menu is switched on or off.
Type (value: string, checked: boolean) => void
onAgentChangeCalled with the new agent value when the agent chip selection changes.
Type (value: string) => void
onModelChangeCalled with the new model value when the model chip selection changes.
Type (value: string) => void
classNameExtra classes for the outer wrapper.
Type string
Install the exact registry entry shown on the right when you want the component file and its declared runtime dependencies together.
Dependencies: motion, lucide-react.
Contact
Additionally, if you find any bug or issue, feel free to raise an issue.