Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 35 additions & 20 deletions apps/www/registry/elevenlabs-ui/ui/conversation-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client"

import * as React from "react"
import { useCallback } from "react"
import { useConversation } from "@elevenlabs/react"
import {
ArrowUpIcon,
Expand Down Expand Up @@ -91,20 +92,25 @@ export const ConversationBar = React.forwardRef<
const [textInput, setTextInput] = React.useState("")
const mediaStreamRef = React.useRef<MediaStream | null>(null)

const conversation = useConversation({
onConnect: () => {
onConnect?.()
},
onDisconnect: () => {
setAgentState("disconnected")
onDisconnect?.()
setKeyboardOpen(false)
},
onMessage: (message) => {
const handleConnect = useCallback(() => {
onConnect?.()
}, [onConnect])

const handleDisconnect = useCallback(() => {
setAgentState("disconnected")
onDisconnect?.()
setKeyboardOpen(false)
}, [onDisconnect])

const handleMessage = useCallback(
(message: { source: "user" | "ai"; message: string }) => {
onMessage?.(message)
},
micMuted: isMuted,
onError: (error: unknown) => {
[onMessage]
)

const handleError = useCallback(
(error: unknown) => {
console.error("Error:", error)
setAgentState("disconnected")
const errorObj =
Expand All @@ -115,9 +121,18 @@ export const ConversationBar = React.forwardRef<
)
onError?.(errorObj)
},
[onError]
)

const conversation = useConversation({
onConnect: handleConnect,
onDisconnect: handleDisconnect,
onMessage: handleMessage,
onError: handleError,
micMuted: isMuted,
})

const getMicStream = React.useCallback(async () => {
const getMicStream = useCallback(async () => {
if (mediaStreamRef.current) return mediaStreamRef.current

const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
Expand All @@ -126,7 +141,7 @@ export const ConversationBar = React.forwardRef<
return stream
}, [])

const startConversation = React.useCallback(async () => {
const startConversation = useCallback(async () => {
try {
setAgentState("connecting")

Expand All @@ -144,7 +159,7 @@ export const ConversationBar = React.forwardRef<
}
}, [conversation, getMicStream, agentId, onError])

const handleEndSession = React.useCallback(() => {
const handleEndSession = useCallback(() => {
conversation.endSession()
setAgentState("disconnected")

Expand All @@ -154,19 +169,19 @@ export const ConversationBar = React.forwardRef<
}
}, [conversation])

const toggleMute = React.useCallback(() => {
const toggleMute = useCallback(() => {
setIsMuted((prev) => !prev)
}, [])

const handleStartOrEnd = React.useCallback(() => {
const handleStartOrEnd = useCallback(() => {
if (agentState === "connected" || agentState === "connecting") {
handleEndSession()
} else if (agentState === "disconnected") {
startConversation()
}
}, [agentState, handleEndSession, startConversation])

const handleSendText = React.useCallback(() => {
const handleSendText = useCallback(() => {
if (!textInput.trim()) return

const messageToSend = textInput
Expand All @@ -177,7 +192,7 @@ export const ConversationBar = React.forwardRef<

const isConnected = agentState === "connected"

const handleTextChange = React.useCallback(
const handleTextChange = useCallback(
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
const value = e.target.value
setTextInput(value)
Expand All @@ -189,7 +204,7 @@ export const ConversationBar = React.forwardRef<
[conversation, isConnected]
)

const handleKeyDown = React.useCallback(
const handleKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault()
Expand Down