{"id":45980857,"url":"https://github.com/dictate-button/dictate-button-react","last_synced_at":"2026-02-28T18:00:32.174Z","repository":{"id":333689040,"uuid":"1138188202","full_name":"dictate-button/dictate-button-react","owner":"dictate-button","description":"React text fields with Dictate Button integrated","archived":false,"fork":false,"pushed_at":"2026-02-28T12:10:36.000Z","size":156,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-28T15:15:26.102Z","etag":null,"topics":["dictate","dictate-button","react","speech-to-text","voice-recognition"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@dictate-button/react","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dictate-button.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-20T10:57:12.000Z","updated_at":"2026-02-28T12:10:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dictate-button/dictate-button-react","commit_stats":null,"previous_names":["dictate-button/dictate-button-react"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dictate-button/dictate-button-react","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dictate-button%2Fdictate-button-react","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dictate-button%2Fdictate-button-react/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dictate-button%2Fdictate-button-react/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dictate-button%2Fdictate-button-react/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dictate-button","download_url":"https://codeload.github.com/dictate-button/dictate-button-react/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dictate-button%2Fdictate-button-react/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29941817,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T13:49:17.081Z","status":"ssl_error","status_checked_at":"2026-02-28T13:48:50.396Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dictate","dictate-button","react","speech-to-text","voice-recognition"],"created_at":"2026-02-28T18:00:24.057Z","updated_at":"2026-02-28T18:00:32.134Z","avatar_url":"https://github.com/dictate-button.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @dictate-button/react\n\n[![NPM Version](https://img.shields.io/npm/v/@dictate-button/react)](https://www.npmjs.com/package/@dictate-button/react)\n[![CI](https://github.com/dictate-button/dictate-button-react/actions/workflows/ci.yml/badge.svg)](https://github.com/dictate-button/dictate-button-react/actions/workflows/ci.yml)\n\nReact text field components with speech-to-text dictation powered by [Dictate Button](https://github.com/dictate-button/dictate-button).\n\nProvides a thin integration layer that avoids DOM scanning and mutation, making it fully compatible with React and any CSS framework.\n\n## Features\n\n- **No DOM Scanning**: Declarative React components instead of inject scripts\n- **No DOM Mutation**: Integrates naturally with React's virtual DOM\n- **Framework Agnostic**: Works with any CSS framework (Tailwind, Bootstrap, etc.)\n- **TypeScript First**: Full type safety and IntelliSense support\n- **React 19 Ready**: Built for modern React\n- **Controlled \u0026 Uncontrolled**: Supports both patterns\n- **Customizable**: Full control over styling and behavior\n\n## Installation\n\n```bash\npnpm add @dictate-button/react\n```\n\n## Registration Required\n\n**You need to register your app on [dictate-button.io](https://dictate-button.io) to use the `@dictate-button/react` components in your app.**\n\nTo do that, visit [dash.dictate-button.io](https://dash.dictate-button.io/auth/register), create a free account and register your site.\nNo API key configuration needed - the service works automatically once your site is registered and verified.\n\n## Quick Start\n\n```tsx\nimport { DictateInput, DictateTextarea, DictateButton } from '@dictate-button/react';\n\nfunction MyForm() {\n  return (\n    \u003cdiv\u003e\n      \u003cDictateInput\n        type=\"text\"\n        placeholder=\"Start typing or click the mic...\"\n        className=\"your-input-class\"\n      /\u003e\n\n      \u003cDictateTextarea\n        rows={5}\n        placeholder=\"Or speak here...\"\n        className=\"your-textarea-class\"\n      /\u003e\n\n      \u003cDictateButton\n        onDictateEnd={(text) =\u003e console.log('Transcribed:', text)}\n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## Why This Integration Layer?\n\nThe [dictate-button](https://github.com/dictate-button/dictate-button) package includes inject scripts that scan the DOM using `querySelectorAll` and mutate it by wrapping elements.\n\nThis integration layer provides:\n\n- ✅ Declarative React components\n- ✅ No DOM scanning or mutation\n- ✅ Works with any CSS framework or styling approach\n- ✅ Full TypeScript support\n- ✅ React refs, controlled components, and hooks\n\n## Components\n\n### `\u003cDictateInput /\u003e`\n\nA text input with integrated speech-to-text button.\n\n```tsx\n\u003cDictateInput\n  type=\"text\"\n  placeholder=\"Type or speak...\"\n  buttonSize={30}\n  onDictateEnd={(text) =\u003e console.log(text)}\n/\u003e\n```\n\n### `\u003cDictateTextarea /\u003e`\n\nA textarea with integrated speech-to-text button.\n\n```tsx\n\u003cDictateTextarea\n  rows={5}\n  placeholder=\"Type or speak...\"\n  buttonSize={30}\n  onDictateEnd={(text) =\u003e console.log(text)}\n/\u003e\n```\n\n### `\u003cDictateButton /\u003e`\n\nA standalone dictate button for custom event-based implementations.\n\n```tsx\n\u003cDictateButton\n  size={30}\n  onDictateStart={() =\u003e console.log('Started')}\n  onDictateText={(text) =\u003e console.log('Interim:', text)}\n  onDictateEnd={(text) =\u003e console.log('Final:', text)}\n  onDictateError={(error) =\u003e console.error(error)}\n/\u003e\n```\n\nUse this when you want to handle dictation events yourself without automatic text field integration.\n\n### `useDictateButtonEventHandlers` Hook\n\nFor building custom text field integrations, use the hook to get text insertion event handlers:\n\n```tsx\nimport { useRef } from 'react';\nimport { DictateButton, useDictateButtonEventHandlers } from '@dictate-button/react';\n\nfunction CustomInput() {\n  const inputRef = useRef\u003cHTMLInputElement\u003e(null);\n  const handlers = useDictateButtonEventHandlers(inputRef);\n\n  return (\n    \u003cdiv style={{ position: 'relative' }}\u003e\n      \u003cinput ref={inputRef} style={{ paddingRight: '40px' }} /\u003e\n      \u003cDictateButton\n        {...handlers}\n        style={{ position: 'absolute', right: '4px', top: '50%', transform: 'translateY(-50%)' }}\n      /\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## Props\n\n### DictateInput \u0026 DictateTextarea Props\n\nAll standard HTML input/textarea props are supported, plus:\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `buttonSize` | `number` | `30` | Size of the dictate button in pixels |\n| `buttonClassName` | `string` | - | CSS class for the button |\n| `apiEndpoint` | `string` | - | Custom API endpoint for transcription |\n| `language` | `string` | `'en'` | Language code (e.g., 'en', 'es', 'fr') |\n| `theme` | `'light' \\| 'dark'` | - | Button theme |\n| `onDictateStart` | `() =\u003e void` | - | Called when dictation starts (overrides text insertion if provided) |\n| `onDictateText` | `(text: string) =\u003e void` | - | Called with interim results (overrides text insertion if provided) |\n| `onDictateEnd` | `(text: string) =\u003e void` | - | Called with final transcription (overrides text insertion if provided) |\n| `onDictateError` | `(error: Error \\| string) =\u003e void` | - | Called on errors (overrides text insertion if provided) |\n\n### DictateButton Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `size` | `number` | `30` | Size of the button in pixels |\n| `className` | `string` | - | CSS class for the button |\n| `style` | `React.CSSProperties` | - | Inline styles for the button |\n| `apiEndpoint` | `string` | - | Custom API endpoint for transcription |\n| `language` | `string` | `'en'` | Language code (e.g., 'en', 'es', 'fr') |\n| `theme` | `'light' \\| 'dark'` | - | Button theme |\n| `onDictateStart` | `() =\u003e void` | - | Called when dictation starts |\n| `onDictateText` | `(text: string) =\u003e void` | - | Called with interim results |\n| `onDictateEnd` | `(text: string) =\u003e void` | - | Called with final transcription |\n| `onDictateError` | `(error: Error \\| string) =\u003e void` | - | Called on errors |\n\n## Styling with Tailwind CSS\n\nThese 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:\n\n```tsx\nimport { DictateInput } from '@dictate-button/react';\nimport { cn } from '@/lib/utils'; // clsx + tailwind-merge utility\n\n\u003cDictateInput\n  className={cn(\n    \"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2\",\n    \"text-sm ring-offset-background\",\n    \"placeholder:text-muted-foreground\",\n    \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n    \"disabled:cursor-not-allowed disabled:opacity-50\"\n  )}\n/\u003e\n```\n\nThe `cn()` utility is commonly used in Tailwind projects to merge class names. It's not specific to any component library.\n\n## Examples\n\nSee [EXAMPLES.md](./EXAMPLES.md) for comprehensive usage examples including:\n\n- Basic usage\n- Tailwind CSS styling\n- Controlled components\n- Custom event handlers\n- React Hook Form integration\n- Advanced hook usage\n\n## TypeScript\n\nAll components and hooks are fully typed. Import types as needed:\n\n```tsx\nimport type {\n  DictateButtonComponentProps,\n  DictateInputProps,\n  DictateTextareaProps,\n  UseDictateButtonEventHandlersReturn,\n} from '@dictate-button/react';\n```\n\n## Development\n\n```bash\n# Build the library\npnpm build\n\n# Run tests\npnpm test\n\n# Type checking\npnpm typecheck\n\n# Lint and format check (Biome)\npnpm check\n\n# Auto-fix formatting\npnpm format\n\n# Lint only\npnpm lint\n\n# Watch mode for development\npnpm dev\n```\n\n## License\n\nApache-2.0\n\n## Credits\n\nBuilt on top of [dictate-button](https://github.com/dictate-button/dictate-button) by the Dictate Button team.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdictate-button%2Fdictate-button-react","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdictate-button%2Fdictate-button-react","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdictate-button%2Fdictate-button-react/lists"}