加载器
一个旋转加载器组件,用于在 AI 应用程序中指示加载状态。
Loader 组件提供旋转动画来指示 AI 应用程序中的加载状态。它包括可自定义的包装组件和底层图标,以便灵活使用。
使用 CLI 安装
AI Elements Vue
shadcn-vue CLI
npx ai-elements-vue@latest add loader
npx shadcn-vue@latest add https://registry.ai-elements-vue.com/loader.json
手动安装
将以下文件复制并粘贴到同一文件夹中。
Loader.vue
LoaderIcon.vue
index.ts
<script setup lang="ts">
import { cn } from '@repo/shadcn-vue/lib/utils'
import LoaderIcon from './LoaderIcon.vue'
interface Props {
size?: number
class?: string
}
const props = withDefaults(defineProps<Props>(), {
size: 16,
})
</script>
<template>
<div
:class="cn('inline-flex animate-spin items-center justify-center', props.class)"
v-bind="$attrs"
>
<LoaderIcon :size="props.size" />
</div>
</template>
<script setup lang="ts">
interface Props {
size?: number
}
withDefaults(defineProps<Props>(), {
size: 16,
})
</script>
<template>
<svg
:height="size"
stroke-linejoin="round"
:style="{ color: 'currentcolor' }"
viewBox="0 0 16 16"
:width="size"
>
<title>Loader</title>
<g clip-path="url(#clip0_2393_1490)">
<path d="M8 0V4" stroke="currentColor" stroke-width="1.5" />
<path d="M8 16V12" opacity="0.5" stroke="currentColor" stroke-width="1.5" />
<path d="M3.29773 1.52783L5.64887 4.7639" opacity="0.9" stroke="currentColor" stroke-width="1.5" />
<path d="M12.7023 1.52783L10.3511 4.7639" opacity="0.1" stroke="currentColor" stroke-width="1.5" />
<path d="M12.7023 14.472L10.3511 11.236" opacity="0.4" stroke="currentColor" stroke-width="1.5" />
<path d="M3.29773 14.472L5.64887 11.236" opacity="0.6" stroke="currentColor" stroke-width="1.5" />
<path d="M15.6085 5.52783L11.8043 6.7639" opacity="0.2" stroke="currentColor" stroke-width="1.5" />
<path d="M0.391602 10.472L4.19583 9.23598" opacity="0.7" stroke="currentColor" stroke-width="1.5" />
<path d="M15.6085 10.4722L11.8043 9.2361" opacity="0.3" stroke="currentColor" stroke-width="1.5" />
<path d="M0.391602 5.52783L4.19583 6.7639" opacity="0.8" stroke="currentColor" stroke-width="1.5" />
</g>
<defs>
<clipPath id="clip0_2393_1490">
<rect fill="white" height="16" width="16" />
</clipPath>
</defs>
</svg>
</template>
export { default as Loader } from './Loader.vue'
与 AI SDK 一起使用
构建一个简单的聊天应用,在响应流式传输之前通过使用 status === "submitted" 显示加载器。
将以下组件添加到你的前端:
pages/index.vue
<script lang="ts" setup>
import { useChat } from '@ai-sdk/vue'
import { cn } from '@repo/shadcn-vue/lib/utils'
import { ref } from 'vue'
import { Conversation, ConversationContent, ConversationScrollButton } from '@/components/ai-elements/conversation'
import { Loader } from '@/components/ai-elements/loader'
import { Message, MessageContent } from '@/components/ai-elements/message'
import { PromptInput, PromptInputSubmit, PromptInputTextarea } from '@/components/ai-elements/prompt-input'
const input = ref('')
const { messages, sendMessage, status } = useChat()
function handleSubmit(e: Event) {
if (input.value.trim()) {
sendMessage({ text: input.value })
input.value = ''
}
}
</script>
<template>
<div
class="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"
>
<div class="flex flex-col h-full">
<Conversation>
<ConversationContent>
<Message v-for="message in messages" :key="message.id" :from="message.role">
<MessageContent>
<template v-for="(part, i) in message.parts" :key="`${message.id}-${i}`">
<div v-if="part.type === 'text'">
{{ part.text }}
</div>
</template>
</MessageContent>
</Message>
<Loader v-if="status === 'submitted'" />
</ConversationContent>
<ConversationScrollButton />
</Conversation>
<PromptInput
class="mt-4 w-full max-w-2xl mx-auto relative"
@submit.prevent="handleSubmit"
>
<PromptInputTextarea
v-model="input"
placeholder="Say something..."
class="pr-12"
/>
<PromptInputSubmit
:status="status === 'streaming' ? 'streaming' : 'ready'"
:disabled="!input.trim()"
class="absolute bottom-1 right-1"
/>
</PromptInput>
</div>
</div>
</template>
将以下路由添加到你的后端:
api/chat/route.ts
import { convertToModelMessages, streamText, UIMessage } from 'ai'
// Allow streaming responses up to 30 seconds
export 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()
}
特性
- 使用 CSS 动画的简洁现代旋转动画
- 通过
sizeprop 可配置大小 - 通过 CSS 类可自定义样式
- 内置
animate-spin动画,具有适当的居中 - 导出
AILoader包装器和LoaderIcon以便灵活使用 - 支持所有标准 HTML div 属性
- 具有适当类型定义的 TypeScript 支持
- 优化的 SVG 图标,具有多个不透明度级别以实现平滑动画
- 使用
currentColor以实现适当的主题集成 - 响应式和可访问的设计
示例
不同大小
自定义样式
Props
<Loader />
sizenumber
16classstring
''