Skip to content

dictate-button/dictate-button-react

Repository files navigation

@dictate-button/react

Tests

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.

Features

  • 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

Installation

pnpm add @dictate-button/react

Registration Required

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.

Quick Start

import { DictateInput, DictateTextarea, DictateButton } from '@dictate-button/react';

function MyForm() {
  return (
    <div>
      <DictateInput
        type="text"
        placeholder="Start typing or click the mic..."
        className="your-input-class"
      />

      <DictateTextarea
        rows={5}
        placeholder="Or speak here..."
        className="your-textarea-class"
      />

      <DictateButton
        onDictateEnd={(text) => console.log('Transcribed:', text)}
      />
    </div>
  );
}

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

<DictateInput />

A text input with integrated speech-to-text button.

<DictateInput
  type="text"
  placeholder="Type or speak..."
  buttonSize={30}
  onDictateEnd={(text) => console.log(text)}
/>

<DictateTextarea />

A textarea with integrated speech-to-text button.

<DictateTextarea
  rows={5}
  placeholder="Type or speak..."
  buttonSize={30}
  onDictateEnd={(text) => console.log(text)}
/>

<DictateButton />

A standalone dictate button for custom event-based implementations.

<DictateButton
  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.

useDictateButtonEventHandlers Hook

For building custom text field integrations, use the hook to get text insertion event handlers:

import { useRef } from 'react';
import { DictateButton, useDictateButtonEventHandlers } from '@dictate-button/react';

function CustomInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  const handlers = useDictateButtonEventHandlers(inputRef);

  return (
    <div style={{ position: 'relative' }}>
      <input ref={inputRef} style={{ paddingRight: '40px' }} />
      <DictateButton
        {...handlers}
        style={{ position: 'absolute', right: '4px', top: '50%', transform: 'translateY(-50%)' }}
      />
    </div>
  );
}

Props

DictateInput & DictateTextarea Props

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)

DictateButton Props

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:

import { DictateInput } from '@dictate-button/react';
import { cn } from '@/lib/utils'; // clsx + tailwind-merge utility

<DictateInput
  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:

import type {
  DictateButtonComponentProps,
  DictateInputProps,
  DictateTextareaProps,
  UseDictateButtonEventHandlersReturn,
} from '@dictate-button/react';

Development

# Build the library
pnpm build

# Run tests
pnpm test

# Type checking
pnpm typecheck

# Watch mode for development
pnpm dev

License

Apache-2.0

Credits

Built on top of dictate-button by the Dictate Button team.