Agent Orbs
Interactive orb visualization with agent states
<script setup lang="ts">
import type { AgentState } from '@/components/elevenlabs-ui/orb'
import { Orb } from '@/components/elevenlabs-ui/orb'
import { Button } from '@/components/ui/button'
import { computed, ref } from 'vue'
const props = defineProps<{
small?: boolean
}>()
const agent = ref<AgentState>(null)
const allOrbs: [string, string][] = [
['#CADCFC', '#A0B9D1'],
['#F6E7D8', '#E0CFC2'],
['#E5E7EB', '#9CA3AF'],
]
const orbs = computed(() => (props.small ? [allOrbs[0]] : allOrbs))
</script>
<template>
<div class="bg-card w-full rounded-lg border p-6">
<div class="mb-4">
<h3 class="text-lg font-semibold">
Agent Orbs
</h3>
<p class="text-muted-foreground text-sm">
Interactive orb visualization with agent states
</p>
</div>
<div class="space-y-4">
<div class="flex justify-center gap-8">
<div
v-for="(colors, index) in orbs"
:key="index"
class="relative"
:class="index === 1 ? 'block md:block' : 'hidden md:block'"
>
<div class="bg-muted relative h-32 w-32 rounded-full p-1 shadow-[inset_0_2px_8px_rgba(0,0,0,0.1)] dark:shadow-[inset_0_2px_8px_rgba(0,0,0,0.5)]">
<div class="bg-background h-full w-full overflow-hidden rounded-full shadow-[inset_0_0_12px_rgba(0,0,0,0.05)] dark:shadow-[inset_0_0_12px_rgba(0,0,0,0.3)]">
<Orb
:colors="colors"
:seed="(index + 1) * 1000"
:agent-state="agent"
/>
</div>
</div>
</div>
</div>
<div class="flex flex-wrap justify-center gap-2">
<Button
size="sm"
variant="outline"
:disabled="agent === null"
@click="agent = null"
>
Idle
</Button>
<Button
size="sm"
variant="outline"
:disabled="agent === 'listening'"
@click="agent = 'listening'"
>
Listening
</Button>
<Button
size="sm"
variant="outline"
:disabled="agent === 'talking'"
@click="agent = 'talking'"
>
Talking
</Button>
</div>
</div>
</div>
</template>Installation
pnpm dlx elevenlabs-ui-vue@latest add orb
If you're using TypeScript, install the Three.js type definitions:
pnpm add @types/three -D
The Orb component uses TresJS, a Vue 3 custom renderer for Three.js, to create declarative 3D scenes. To ensure the component renders correctly, please configure the template compiler options based on your project type (Vue or Nuxt).
Important: This configuration is required to make the template compiler work with the TresJS custom renderer and prevent console warnings.
Vue project
If you're using Vue, you should add the TresJS template compiler options to your vite.config.ts:
import { templateCompilerOptions } from '@tresjs/core'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue({
// Other config
...templateCompilerOptions
}),
],
})See the Vue project section for more information.
Nuxt project
If you're using Nuxt, you should use the official TresJS Nuxt module for a seamless integration experience.
Install the TresJS Nuxt module and Three.js:
pnpm add @tresjs/nuxt
Add @tresjs/nuxt to the modules section of your nuxt.config.ts:
export default defineNuxtConfig({
modules: ['@tresjs/nuxt'],
})See the Nuxt project section for more information.
Usage
<script setup lang="ts">
import { Orb } from "@/components/elevenlabs-ui/orb"
</script>
<template>
<Orb />
</template>Examples
Custom Colors
<template>
<Orb :colors="['#FF6B6B', '#4ECDC4']" />
</template>With Audio Reactivity
<script setup>
function getInputVolume() {
// Return normalized volume between 0 and 1
return 0.5
}
function getOutputVolume() {
// Return normalized volume between 0 and 1
return 0.7
}
</script>
<template>
<Orb
:getInputVolume="getInputVolume"
:getOutputVolume="getOutputVolume"
/>
</template>With Custom Seed
<template>
<Orb :seed="12345" />
</template>With Agent State
<script setup lang="ts">
import { ref } from 'vue'
const agentState = ref<"thinking" | "listening" | "talking" | null>(null)
</script>
<template>
<Orb :agentState="agentState" />
</template>Manual Volume Control
<script setup lang="ts">
import { ref } from 'vue'
const inputVolume = ref(0.5)
const outputVolume = ref(0.7)
</script>
<template>
<Orb
:volume-mode="manual"
:manual-input="inputVolume"
:manual-output="outputVolume"
/>
</template>API Reference
Orb
A WebGL-based 3D orb component with audio reactivity and customizable appearance.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| colors | [string, string] | ["#CADCFC", "#A0B9D1"] | Two color values for the gradient |
| colorsRef | Ref<[string, string]> | - | Ref for dynamic color updates |
| resizeDebounce | number | 100 | Canvas resize debounce in ms |
| seed | number | Random | Seed for consistent animations |
| agentState | AgentState | null | Agent state: null, "thinking", "listening", "talking" |
| volumeMode | "auto" | "manual" | "auto" | Volume control mode |
| manualInput | number | - | Manual input volume (0-1) |
| manualOutput | number | - | Manual output volume (0-1) |
| inputVolumeRef | Ref<number> | - | Ref for input volume |
| outputVolumeRef | Ref<number> | - | Ref for output volume |
| getInputVolume | () => number | - | Function returning input volume (0-1) |
| getOutputVolume | () => number | - | Function returning output volume (0-1) |
| class | string | - | Custom CSS class |
AgentState Type
type AgentState = null | "thinking" | "listening" | "talking"Notes
- Built with Three.js and TresJS for performant 3D rendering
- Uses WebGL shaders for smooth, fluid animations
- Audio reactivity can be controlled via functions (
getInputVolume,getOutputVolume) or refs - Agent state changes affect the orb's visual appearance and animation
- Seed prop ensures consistent animation patterns across renders
- Automatically handles canvas resizing with configurable debounce
- Colors can be updated dynamically via
colorsReffor smooth transitions - Performance-optimized with proper cleanup and requestAnimationFrame usage