Skip to content
Merged

Voice #317

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5bd6fa9
New voice folder
haydenbleasel Nov 10, 2025
2c37584
Draft Audio Player component
haydenbleasel Nov 10, 2025
7bbc7db
Add support for AI SDK speech result
haydenbleasel Nov 10, 2025
d156875
Draft Mic Selector component
haydenbleasel Nov 11, 2025
3157b97
Extract PromptInputSpeechButton to SpeechInput
haydenbleasel Nov 11, 2025
b8cece4
Update speech-input.mdx
haydenbleasel Nov 11, 2025
ad9725b
Add new unit tests
haydenbleasel Nov 11, 2025
a8d0e21
Merge groups
haydenbleasel Nov 11, 2025
3307375
Fix tests
haydenbleasel Nov 11, 2025
5f9796f
Improve test coverage
haydenbleasel Nov 11, 2025
c4acb07
Run Ultracite
haydenbleasel Nov 11, 2025
d62d54f
Update mic-selector.tsx
haydenbleasel Nov 11, 2025
00485c7
Draft Voice Selector
haydenbleasel Nov 13, 2025
61539ef
Scaffold Persona
haydenbleasel Nov 13, 2025
3302f51
Update persona.tsx
haydenbleasel Nov 13, 2025
d790866
Redesign speech input as record button
haydenbleasel Nov 14, 2025
1ea0e90
Scaffold Transcription component
haydenbleasel Nov 14, 2025
69e093e
Fix unit tests
haydenbleasel Nov 14, 2025
6d2e461
Propagate changes from #233
haydenbleasel Nov 14, 2025
c97b919
Resolves #242
haydenbleasel Nov 17, 2025
93c9c17
Update mic-selector.tsx
haydenbleasel Nov 17, 2025
494aa7a
Update preview.tsx
haydenbleasel Nov 17, 2025
e1a3284
Attempt to overwrite color
haydenbleasel Nov 17, 2025
db161f7
Fix persona bugs
haydenbleasel Nov 21, 2025
39cb7c4
Remove Pal
haydenbleasel Nov 26, 2025
7e7b07e
Update persona.test.tsx
haydenbleasel Nov 26, 2025
d7cfbfa
Resolves #210
haydenbleasel Nov 26, 2025
a0c0b33
Fix non-model instances
haydenbleasel Nov 26, 2025
5750417
Rename orb to opal, change default
haydenbleasel Nov 26, 2025
bef9cf2
Performance improvements
haydenbleasel Nov 26, 2025
dc0451c
Update pnpm-lock.yaml
haydenbleasel Jan 13, 2026
09a4085
Fix navbar tracking
haydenbleasel Jan 13, 2026
cbdf098
Minor fixes
haydenbleasel Jan 13, 2026
4f3560d
Update registry mcp server
haydenbleasel Jan 14, 2026
48bdd75
Add changesets
haydenbleasel Jan 14, 2026
92ea672
Update persona.test.tsx
haydenbleasel Jan 14, 2026
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
5 changes: 5 additions & 0 deletions .changeset/bright-wolves-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-elements": patch
---

Update mcp server
5 changes: 5 additions & 0 deletions .changeset/mighty-papers-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-elements": patch
---

Add support for MediaRecorder and custom config to SpeechInput
5 changes: 5 additions & 0 deletions .changeset/soft-peaches-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ai-elements": minor
---

AI Voice Elements
2 changes: 1 addition & 1 deletion apps/docs/components/custom/navbar/client-navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const ClientNavbar = ({ pages }: { pages: NavPageItem[] }) => (
{pages.map((page) => (
<Button
asChild
className="p-0 font-normal text-muted-foreground tracking-[0.13px] hover:text-foreground hover:no-underline"
className="p-0 font-normal text-muted-foreground hover:text-foreground hover:no-underline"
key={page.href}
variant="link"
>
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/components/custom/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export const Preview = async ({ path, className }: ComponentPreviewProps) => {
<CodeBlockTabsTrigger value="code">Code</CodeBlockTabsTrigger>
</CodeBlockTabsList>
<CodeBlockTab className="not-prose p-0" value="preview">
<ResizablePanelGroup direction="horizontal">
<ResizablePanelGroup direction="horizontal" id={`preview-${path}`}>
<ResizablePanel defaultSize={100}>
<div className={cn("h-[600px] overflow-auto p-4", className)}>
<Component />
Expand Down
113 changes: 43 additions & 70 deletions apps/docs/content/docs/components/(chatbot)/prompt-input.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ import {
PromptInputSelectItem,
PromptInputSelectTrigger,
PromptInputSelectValue,
PromptInputSpeechButton,
PromptInputSubmit,
PromptInputTextarea,
PromptInputFooter,
PromptInputTools,
} from '@/components/ai-elements/prompt-input';
import { GlobeIcon } from 'lucide-react';
import { useRef, useState } from 'react';
import { useState } from 'react';
import { useChat } from '@ai-sdk/react';
import {
Conversation,
Expand All @@ -62,7 +61,6 @@ const InputDemo = () => {
const [text, setText] = useState<string>('');
const [model, setModel] = useState<string>(models[0].id);
const [useWebSearch, setUseWebSearch] = useState<boolean>(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);

const { messages, status, sendMessage } = useChat();

Expand Down Expand Up @@ -126,7 +124,6 @@ const InputDemo = () => {

<PromptInputTextarea
onChange={(e) => setText(e.target.value)}
ref={textareaRef}
value={text}
/>
</PromptInputBody>
Expand All @@ -138,10 +135,6 @@ const InputDemo = () => {
<PromptInputActionAddAttachments />
</PromptInputActionMenuContent>
</PromptInputActionMenu>
<PromptInputSpeechButton
onTranscriptionChange={setText}
textareaRef={textareaRef}
/>
<PromptInputButton
onClick={() => setUseWebSearch(!useWebSearch)}
variant={useWebSearch ? 'default' : 'ghost'}
Expand Down Expand Up @@ -509,68 +502,6 @@ export async function POST(req: Request) {

Optional global provider that lifts PromptInput state outside of PromptInput. When used, it allows you to access and control the input state from anywhere within the provider tree. If not used, PromptInput stays fully self-managed.

### `<PromptInputSpeechButton />`

<TypeTable
type={{
textareaRef: {
description: 'Reference to the textarea element to insert transcribed text.',
type: 'RefObject<HTMLTextAreaElement | null>',
},
onTranscriptionChange: {
description: 'Callback fired when transcription text changes.',
type: '(text: string) => void',
},
'...props': {
description: 'Any other props are spread to the underlying PromptInputButton component.',
type: 'React.ComponentProps<typeof PromptInputButton>',
},
}}
/>

Built-in button component that provides native speech recognition using the Web Speech API. The button will be disabled if speech recognition is not supported in the browser. Displays a microphone icon and pulses while actively listening.

## Hooks

### `usePromptInputAttachments`

Access and manage file attachments within a PromptInput context.

```tsx
const attachments = usePromptInputAttachments();

// Available methods:
attachments.files // Array of current attachments
attachments.add(files) // Add new files
attachments.remove(id) // Remove an attachment by ID
attachments.clear() // Clear all attachments
attachments.openFileDialog() // Open file selection dialog
```

### `usePromptInputController`

Access the full PromptInput controller from a PromptInputProvider. Only available when using the provider.

```tsx
const controller = usePromptInputController();

// Available methods:
controller.textInput.value // Current text input value
controller.textInput.setInput(value) // Set text input value
controller.textInput.clear() // Clear text input
controller.attachments // Same as usePromptInputAttachments
```

### `useProviderAttachments`

Access attachments context from a PromptInputProvider. Only available when using the provider.

```tsx
const attachments = useProviderAttachments();

// Same interface as usePromptInputAttachments
```

### `<PromptInputHeader />`

<TypeTable
Expand Down Expand Up @@ -761,3 +692,45 @@ const attachments = useProviderAttachments();
},
}}
/>


## Hooks

### `usePromptInputAttachments`

Access and manage file attachments within a PromptInput context.

```tsx
const attachments = usePromptInputAttachments();

// Available methods:
attachments.files // Array of current attachments
attachments.add(files) // Add new files
attachments.remove(id) // Remove an attachment by ID
attachments.clear() // Clear all attachments
attachments.openFileDialog() // Open file selection dialog
```

### `usePromptInputController`

Access the full PromptInput controller from a PromptInputProvider. Only available when using the provider.

```tsx
const controller = usePromptInputController();

// Available methods:
controller.textInput.value // Current text input value
controller.textInput.setInput(value) // Set text input value
controller.textInput.clear() // Clear text input
controller.attachments // Same as usePromptInputAttachments
```

### `useProviderAttachments`

Access attachments context from a PromptInputProvider. Only available when using the provider.

```tsx
const attachments = useProviderAttachments();

// Same interface as usePromptInputAttachments
```
Loading