This component no longer exists. It was in ruixen-ui’s manifest when we first indexed it and is not there now — the registry served its inventory on 2026-08-12 and this item was not on it. The install command below will fail. It is kept here because a tutorial somewhere still tells people to run it.
AI Chat Input
ruixen-ui/ai-chat-inputRemovedComponent
Vanishing chat input with rotating placeholders, pixel-scatter submit, and spring-timed interactions.
Live preview
live · rendered by the registry
Rendered by ruixen-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ruixen.com/r/ai-chat-input.jsonSource
1"use client";23import * as React from "react";4import { AnimatePresence, motion } from "motion/react";5import { cn } from "@/lib/utils";67export interface AiChatInputProps {8 /** Rotating placeholder strings */9 placeholders?: string[];10 /** Callback with the submitted value */11 onSubmit?: (value: string) => void;12 /** Callback fired on every keystroke */13 onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;14 /** Additional CSS classes */15 className?: string;16}1718export default function AiChatInput({19 placeholders = [20 "Ask me anything...",21 "Describe what you need built",22 "Summarize this document for me",23 "Write a function that...",24 "Explain how this works",25 ],26 onSubmit,27 onChange,28 className,29}: AiChatInputProps) {30 const canvasRef = React.useRef<HTMLCanvasElement>(null);31 const inputRef = React.useRef<HTMLInputElement>(null);32 const newDataRef = React.useRef<33 Array<{34 x: number;35 y: number;36 r: number;37 color: string;38 vx: number;39 vy: number;40 }>41 >([]);42 const [value, setValue] = React.useState("");43 const [animating, setAnimating] = React.useState(false);44 const [placeholderIndex, setPlaceholderIndex] = React.useState(0);4546 /* ---- rotating placeholders ---- */47 React.useEffect(() => {48 const id = setInterval(() => {49 setPlaceholderIndex((i) => (i + 1) % placeholders.length);50 }, 3000);51 return () => clearInterval(id);52 }, [placeholders.length]);5354 /* ---- canvas setup ---- */55 const startAnimation = React.useCallback(() => {56 const cvs = canvasRef.current;57 const input = inputRef.current;58 if (!cvs || !input) return;5960 cvs.width = 800;61 cvs.height = 800;6263 const ctx = cvs.getContext("2d", { willReadFrequently: true });64 if (!ctx) return;6566 ctx.clearRect(0, 0, 800, 800);6768 const style = getComputedStyle(input);69 const fontSize = parseFloat(style.getPropertyValue("font-size"));7071 ctx.font = `${fontSize * 2}px ${style.fontFamily}`;72 ctx.fillStyle = style.color;73 ctx.fillText(value, 0, fontSize * 2);7475 const imageData = ctx.getImageData(0, 0, 800, 800);76 const pixelData = imageData.data;77 const pixels: Array<{78 x: number;79 y: number;80 r: number;81 color: string;82 vx: number;83 vy: number;84 }> = [];8586 for (let y = 0; y < 800; y += 2) {87 for (let x = 0; x < 800; x++) {88 const idx = (y * 800 + x) * 4;89 if (pixelData[idx + 3] > 128) {90// … truncated
What it pulls in
npm packages
