React text fields with Dictate Button integrated
npm install @dictate-button/react
React text field components with speech-to-text dictation powered by Dictate Button.
Provides a thin integration layer that avoids DOM scanning and mutation, making it fully compatible with React and any CSS framework.
- No DOM Scanning: Declarative React components instead of inject scripts
- No DOM Mutation: Integrates naturally with React's virtual DOM
- Framework Agnostic: Works with any CSS framework (Tailwind, Bootstrap, etc.)
- TypeScript First: Full type safety and IntelliSense support
- React 19 Ready: Built for modern React
- Controlled & Uncontrolled: Supports both patterns
- Customizable: Full control over styling and behavior
``bash`
pnpm add @dictate-button/react
You need to register your app on dictate-button.io to use the @dictate-button/react components in your app.
To do that, visit dash.dictate-button.io, create a free account and register your site.
No API key configuration needed - the service works automatically once your site is registered and verified.
`tsx
import { DictateInput, DictateTextarea, DictateButton } from '@dictate-button/react';
function MyForm() {
return (
placeholder="Or speak here..."
className="your-textarea-class"
/>
/>
Why This Integration Layer?
The dictate-button package includes inject scripts that scan the DOM using
querySelectorAll and mutate it by wrapping elements.This integration layer provides:
- ✅ Declarative React components
- ✅ No DOM scanning or mutation
- ✅ Works with any CSS framework or styling approach
- ✅ Full TypeScript support
- ✅ React refs, controlled components, and hooks
Components
$3
A text input with integrated speech-to-text button.
`tsx
type="text"
placeholder="Type or speak..."
buttonSize={30}
onDictateEnd={(text) => console.log(text)}
/>
`$3
A textarea with integrated speech-to-text button.
`tsx
rows={5}
placeholder="Type or speak..."
buttonSize={30}
onDictateEnd={(text) => console.log(text)}
/>
`$3
A standalone dictate button for custom event-based implementations.
`tsx
size={30}
onDictateStart={() => console.log('Started')}
onDictateText={(text) => console.log('Interim:', text)}
onDictateEnd={(text) => console.log('Final:', text)}
onDictateError={(error) => console.error(error)}
/>
`Use this when you want to handle dictation events yourself without automatic text field integration.
$3
For building custom text field integrations, use the hook to get text insertion event handlers:
`tsx
import { useRef } from 'react';
import { DictateButton, useDictateButtonEventHandlers } from '@dictate-button/react';function CustomInput() {
const inputRef = useRef(null);
const handlers = useDictateButtonEventHandlers(inputRef);
return (
{...handlers}
style={{ position: 'absolute', right: '4px', top: '50%', transform: 'translateY(-50%)' }}
/>
);
}
`Props
$3
All standard HTML input/textarea props are supported, plus:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
buttonSize | number | 30 | Size of the dictate button in pixels |
| buttonClassName | string | - | CSS class for the button |
| apiEndpoint | string | - | Custom API endpoint for transcription |
| language | string | 'en' | Language code (e.g., 'en', 'es', 'fr') |
| theme | 'light' \| 'dark' | - | Button theme |
| onDictateStart | () => void | - | Called when dictation starts (overrides text insertion if provided) |
| onDictateText | (text: string) => void | - | Called with interim results (overrides text insertion if provided) |
| onDictateEnd | (text: string) => void | - | Called with final transcription (overrides text insertion if provided) |
| onDictateError | (error: Error \| string) => void | - | Called on errors (overrides text insertion if provided) |$3
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
size | number | 30 | Size of the button in pixels |
| className | string | - | CSS class for the button |
| style | React.CSSProperties | - | Inline styles for the button |
| apiEndpoint | string | - | Custom API endpoint for transcription |
| language | string | 'en' | Language code (e.g., 'en', 'es', 'fr') |
| theme | 'light' \| 'dark' | - | Button theme |
| onDictateStart | () => void | - | Called when dictation starts |
| onDictateText | (text: string) => void | - | Called with interim results |
| onDictateEnd | (text: string) => void | - | Called with final transcription |
| onDictateError | (error: Error \| string) => void | - | Called on errors |Styling with Tailwind CSS
These components accept standard
className props and work with any CSS framework. Here's an example using Tailwind CSS with the popular cn() utility for conditional classes:`tsx
import { DictateInput } from '@dictate-button/react';
import { cn } from '@/lib/utils'; // clsx + tailwind-merge utility className={cn(
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2",
"text-sm ring-offset-background",
"placeholder:text-muted-foreground",
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
"disabled:cursor-not-allowed disabled:opacity-50"
)}
/>
`The
cn() utility is commonly used in Tailwind projects to merge class names. It's not specific to any component library.Examples
See EXAMPLES.md for comprehensive usage examples including:
- Basic usage
- Tailwind CSS styling
- Controlled components
- Custom event handlers
- React Hook Form integration
- Advanced hook usage
TypeScript
All components and hooks are fully typed. Import types as needed:
`tsx
import type {
DictateButtonComponentProps,
DictateInputProps,
DictateTextareaProps,
UseDictateButtonEventHandlersReturn,
} from '@dictate-button/react';
`Development
`bash
Build the library
pnpm buildRun tests
pnpm testType checking
pnpm typecheckWatch mode for development
pnpm dev
``Apache-2.0
Built on top of dictate-button by the Dictate Button team.