# Chat Dictation Button

## Usage

ChatDictationButton is a toggle button that starts and stops voice dictation inside a chat composer. It pairs with `useChatDictation` to show a microphone icon when idle and animated frequency bars when listening. Place it in the `sendActions` slot of ChatComposer.

```ts
import { ChatDictationButton } from '@astryx-vue/core/Chat'
```

### Anatomy

- **Microphone icon**: Shown in the idle state. Indicates that tapping will start voice input.
- **Frequency bars**: Animated equalizer bars that replace the icon during listening. React to real microphone volume.
- **Ghost button**: The underlying Button with ghost variant and isIconOnly, providing the hit target and focus ring.

## Best practices

| Guidance | Practices |
| --- | --- |
| Do | Place the dictation button in the `sendActions` slot of ChatComposer so it sits next to the send button where users expect voice input controls. |
| Do | Pass the input handle to `useChatDictation` so interim transcripts appear as ghost text in the composer input while the user speaks. |
| Do | Enable `hasSounds` on `useChatDictation` to give users audio feedback when dictation starts and stops. This is especially helpful when the button's visual change is subtle. |
| Don't | Don't use the dictation button outside a chat composer context. It's designed for the composer's send-action layout, not as a standalone recording control. |
| Don't | Don't forget to handle the unsupported case. The button hides itself by default when the browser lacks SpeechRecognition, but you should still design the composer to work without it. |

## Examples

Common configurations, variations, and states.

### ChatDictationButton — Basic

A dictation button wired to useChatDictation and placed in the sendActions slot of a ChatComposer. Click the microphone to transcribe speech into the input.

```vue
<script setup lang="ts">
import type { ChatComposerInputHandle } from '@astryx-vue/core/Chat'
import { ChatComposer, ChatComposerInput, ChatDictationButton, useChatDictation } from '@astryx-vue/core/Chat'
import { reactive, ref } from 'vue'

const input = ref<ChatComposerInputHandle | null>(null)
const dictation = reactive(useChatDictation({ input }))
</script>

<template>
  <ChatComposer>
    <template #input>
      <ChatComposerInput ref="input" />
    </template>
    <template #sendActions>
      <ChatDictationButton :dictation="dictation" />
    </template>
  </ChatComposer>
</template>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `dictation` | `{ isSupported, isListening, bands, volume, toggle }` | — | Required. The return value of `useChatDictation` or `useSpeechRecognition`. A `reactive()` copy works: each field is read as it changes. |
| `size` | `'sm' \| 'md'` | `'md'` | Button size, forwarded to `Button`. Also sets the bar width and height. |
| `isHiddenWhenUnsupported` | `boolean` | `true` | Hide the control when speech recognition is missing. Set it to `false` to keep the control visible and disabled. |
| `label` | `string` | Localized “Start dictation” / “Stop dictation” | Accessible name of the button. |

The button paints the accent color while it listens. When the input level goes past the clipping threshold, the bars mix toward the error color, so a loud microphone is visible at a glance.
