Aesthe UI

AI Input

Modern AI-powered input fields with auto-resize and file upload capabilities

Overview

Beautiful, modern AI input components with auto-resizing textarea, smooth animations, and optional file upload support. Perfect for chat interfaces, AI assistants, and messaging applications.

Variants

AI Input 01 - Basic Chat Input

A clean, minimalist chat input with auto-resize functionality and microphone icon.


AI Input 02 - File Upload Chat Input

Advanced chat input with file attachment functionality and file preview.

Dependencies

These components require the following custom hooks:

useAutoResizeTextarea Hook

// hooks/use-auto-resize-textarea.ts
import { useRef } from 'react'

interface UseAutoResizeTextareaOptions {
  minHeight?: number
  maxHeight?: number
}

export function useAutoResizeTextarea({
  minHeight = 52,
  maxHeight = 200,
}: UseAutoResizeTextareaOptions = {}) {
  const textareaRef = useRef<HTMLTextAreaElement>(null)

  const adjustHeight = (reset = false) => {
    const textarea = textareaRef.current
    if (!textarea) return

    if (reset) {
      textarea.style.height = `${minHeight}px`
      return
    }

    textarea.style.height = 'auto'
    const newHeight = Math.min(Math.max(textarea.scrollHeight, minHeight), maxHeight)
    textarea.style.height = `${newHeight}px`
  }

  return { textareaRef, adjustHeight }
}

useFileInput Hook

// hooks/use-file-input.ts
import { useRef, useState } from 'react'

interface UseFileInputOptions {
  accept?: string
  maxSize?: number // in MB
  onFileSelect?: (file: File) => void
}

export function useFileInput({
  accept = '*',
  maxSize = 5,
  onFileSelect,
}: UseFileInputOptions = {}) {
  const [fileName, setFileName] = useState<string>('')
  const fileInputRef = useRef<HTMLInputElement>(null)

  const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0]
    if (!file) return

    if (file.size > maxSize * 1024 * 1024) {
      alert(`File size must be less than ${maxSize}MB`)
      return
    }

    setFileName(file.name)
    onFileSelect?.(file)
  }

  const clearFile = () => {
    setFileName('')
    if (fileInputRef.current) {
      fileInputRef.current.value = ''
    }
  }

  return {
    fileName,
    fileInputRef,
    handleFileSelect,
    clearFile,
  }
}

Installation

npm install lucide-react clsx tailwind-merge

Copy the component code and the required hooks to your project.