> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Prompt Bar – Code

> The PromptBar provides a controlled composer for text, voice capture, and sending.

<Tabs>
  <Tab title="Implementation">
    ```tsx theme={null}
    import { useState } from "react";
    import { PromptBar } from "@servicetitan/anvil2-rn";

    function App() {
      const [value, setValue] = useState("");

      return (
        <PromptBar
          value={value}
          onChange={setValue}
          onSend={() => send(value)}
          placeholder="Ask anything…"
        />
      );
    }
    ```

    ## Common Examples

    To use the `PromptBar`, pass controlled `value` and `onChange`. The Send button stays disabled until `onSend` is wired. Sending is allowed when the draft has trimmed text, unless you override `canSend`.

    ```tsx theme={null}
    import { useState } from "react";
    import { PromptBar } from "@servicetitan/anvil2-rn";

    function ExampleComponent() {
      const [value, setValue] = useState("");

      return (
        <PromptBar
          value={value}
          onChange={setValue}
          onSend={() => send(value)}
        />
      );
    }
    ```

    The editor grows until `maxRows` (default `8`), then it scrolls.

    ### Stop

    While `isSending` is true, sending is withheld. Wire `onStop` to surface Stop instead of Send.

    ```tsx theme={null}
    <PromptBar
      value={value}
      onChange={setValue}
      isSending
      onStop={() => cancel()}
    />
    ```

    ### Voice

    The kit does not record or transcribe. Wire `onStartVoice` to show a mic. Drive `voiceState` (`"idle"`, `"listening"`, `"transcribing"`) from the host. Pass `audioLevel` (0–1) while listening and `transcript` while transcribing. Wire `onAcceptVoice` and `onCancelVoice` to show those listening-row controls.

    ```tsx theme={null}
    <PromptBar
      value={value}
      onChange={setValue}
      onStartVoice={startMic}
      voiceState="listening"
      audioLevel={0.6}
      onAcceptVoice={accept}
      onCancelVoice={cancel}
    />
    ```

    Attachments and the web waveform are not part of the React Native surface yet.

    ### Disclaimer

    Pass a plain-string `disclaimer` to show fine print under the bar. Omit it to hide the line. Rich-text and link support are not ported.

    ```tsx theme={null}
    <PromptBar
      value={value}
      onChange={setValue}
      onSend={() => {}}
      disclaimer="AI responses may be inaccurate."
    />
    ```

    ### Disabled

    `disabled` disables the editor, send, and mic.

    Built-in action labels (`sendLabel`, `stopLabel`, `startVoiceLabel`, and the voice-row labels) default to English. Override them for localized copy.

    ## Accessibility

    * `placeholder` is the editor's accessible name.
    * While listening, `listeningLabel` is announced through a polite live region because the level meter is decorative.
    * While transcribing, `transcribingLabel` names the row until `transcript` arrives.
    * Send, Stop, mic, accept, and cancel use the corresponding label props as accessible names.
  </Tab>

  <Tab title="PromptBar Props">
    ```tsx theme={null}
    <PromptBar
      value={value}
      onChange={setValue}
      onSend={() => send(value)}
      placeholder="Ask anything…"
    />
    ```

    ## `PromptBar` Props

    The `PromptBar` accepts the following props. It does not forward remaining React Native `View` or `TextInput` props.

    <ParamField path="onChange" type="(value: string) => void" required>
      Fired on every edit with the next value.
    </ParamField>

    <ParamField path="value" type="string" required>
      Current draft text. Controlled.
    </ParamField>

    <ParamField path="acceptVoiceLabel" type="string" default="Accept voice input">
      Accessible name for the listening-row accept control.
    </ParamField>

    <ParamField path="analyticsId" type="string">
      Opt-in telemetry id. When set under `Anvil2RNTelemetryProvider`, send
      emits a `submit` event with `meta.length` (character count only, never
      the draft text) before `onSend`.
    </ParamField>

    <ParamField path="audioLevel" type="number">
      Input level from 0 to 1 for the listening meter. Clamped. Only read
      while `voiceState` is `"listening"`.
    </ParamField>

    <ParamField path="canSend" type="boolean">
      Override for whether sending is allowed. Defaults to a non-whitespace
      draft.
    </ParamField>

    <ParamField path="cancelVoiceLabel" type="string" default="Cancel voice input">
      Accessible name for the listening-row cancel control.
    </ParamField>

    <ParamField path="disabled" type="boolean">
      Disables the editor and the send action.
    </ParamField>

    <ParamField path="disclaimer" type="string">
      Fine-print sentence below the bar. Omit to hide it.
    </ParamField>

    <ParamField path="isSending" type="boolean">
      Withholds sending while a response is in flight. Pair with `onStop` to
      surface Stop.
    </ParamField>

    <ParamField path="listeningLabel" type="string" default="Recording">
      Polite live-region status while `voiceState` is `"listening"`.
    </ParamField>

    <ParamField path="maxRows" type="number" default="8">
      Rows the editor grows to before it starts scrolling.
    </ParamField>

    <ParamField path="onAcceptVoice" type="() => void">
      Accepts the current voice capture. Surfaces the accept control in the
      listening row.
    </ParamField>

    <ParamField path="onCancelVoice" type="() => void">
      Discards the current voice capture. Surfaces the cancel control in the
      listening row.
    </ParamField>

    <ParamField path="onSend" type="() => void">
      Fired when Send fires. The Send button stays disabled until this is
      wired.
    </ParamField>

    <ParamField path="onStartVoice" type="() => void">
      Fired when the mic action fires. Wiring it surfaces the mic. The host
      owns recording and speech-to-text.
    </ParamField>

    <ParamField path="onStop" type="() => void">
      Fired when Stop fires. Only surfaces while `isSending` is true.
    </ParamField>

    <ParamField path="placeholder" type="string">
      Placeholder for the empty editor. Also the editor's accessible name.
    </ParamField>

    <ParamField path="sendLabel" type="string" default="Send">
      Accessible name for the send action.
    </ParamField>

    <ParamField path="startVoiceLabel" type="string" default="Start voice input">
      Accessible name for the mic button.
    </ParamField>

    <ParamField path="stopLabel" type="string" default="Stop">
      Accessible name for Stop while `isSending` is true.
    </ParamField>

    <ParamField path="testID" type="string">
      Test hook forwarded to the root view.
    </ParamField>

    <ParamField path="transcribingLabel" type="string" default="Transcribing…">
      Fallback copy and accessible name while transcribing before
      `transcript` arrives.
    </ParamField>

    <ParamField path="transcript" type="string">
      Interim transcript while `voiceState` is `"transcribing"`.
    </ParamField>

    <ParamField path="voiceState" type={`"idle" | "listening" | "transcribing"`} default="idle">
      Voice-capture phase owned by the host.
    </ParamField>
  </Tab>
</Tabs>
