Loader
The Loader
component provides a spinning animation to indicate loading states in your AI applications. It includes both a customizable wrapper component and the underlying icon for flexible usage.
Installation
npx ai-elements@latest add loader
Usage
import { Loader } from '@/components/ai-elements/loader';
<Loader />
Usage with AI SDK
Build a simple chat app that displays a loader before it the response streans by using status === "submitted"
.
Add the following component to your frontend:
app/page.tsx
'use client';
import { Conversation, ConversationContent, ConversationScrollButton,} from '@/components/ai-elements/conversation';import { Message, MessageContent } from '@/components/ai-elements/message';import { Input, PromptInputTextarea, PromptInputSubmit,} from '@/components/ai-elements/prompt-input';import { Loader } from '../ai-elements/loader';import { useState } from 'react';import { useChat } from '@ai-sdk/react';
const LoaderDemo = () => { const [input, setInput] = useState(''); const { messages, sendMessage, status } = useChat();
const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (input.trim()) { sendMessage({ text: input }); setInput(''); } };
return ( <div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"> <div className="flex flex-col h-full"> <Conversation> <ConversationContent> {messages.map((message) => ( <Message from={message.role} key={message.id}> <MessageContent> {message.parts.map((part, i) => { switch (part.type) { case 'text': return ( <div key={`${message.id}-${i}`}>{part.text}</div> ); default: return null; } })} </MessageContent> </Message> ))} {status === 'submitted' && <Loader />} </ConversationContent> <ConversationScrollButton /> </Conversation>
<Input onSubmit={handleSubmit} className="mt-4 w-full max-w-2xl mx-auto relative" > <PromptInputTextarea value={input} placeholder="Say something..." onChange={(e) => setInput(e.currentTarget.value)} className="pr-12" /> <PromptInputSubmit status={status === 'streaming' ? 'streaming' : 'ready'} disabled={!input.trim()} className="absolute bottom-1 right-1" /> </Input> </div> </div> );};
export default LoaderDemo;
Add the following route to your backend:
app/api/chat/route.ts
import { streamText, UIMessage, convertToModelMessages } from 'ai';
// Allow streaming responses up to 30 secondsexport const maxDuration = 30;
export async function POST(req: Request) { const { model, messages }: { messages: UIMessage[]; model: string } = await req.json();
const result = streamText({ model: 'openai/gpt-4o', messages: convertToModelMessages(messages), });
return result.toUIMessageStreamResponse();}
Features
- Clean, modern spinning animation using CSS animations
- Configurable size with the
size
prop - Customizable styling with CSS classes
- Built-in
animate-spin
animation with proper centering - Exports both
AILoader
wrapper andLoaderIcon
for flexible usage - Supports all standard HTML div attributes
- TypeScript support with proper type definitions
- Optimized SVG icon with multiple opacity levels for smooth animation
- Uses
currentColor
for proper theme integration - Responsive and accessible design
Examples
Different Sizes
Small (16px)
Medium (24px)
Large (32px)
Extra Large (48px)
Custom Styling
Blue
Green
Purple
Orange
Slow Animation
Fast Animation
With Background
Dark Background
Props
<Loader />
size?:
number
The size (width and height) of the loader in pixels. Defaults to 16.
[...props]?:
React.HTMLAttributes<HTMLDivElement>
Any other props are spread to the root div.