Voice Input on a Form Field
Add nds-voice-input to any action button inside a form container to activate speech-to-text. The button toggles listening on and off, and the transcript is written directly into the input.
<div class="nds-form-container nds-search">
<div class="nds-form-control-wrapper">
<div class="nds-form-control">
<i class="nds-icon nds-hgi-search-01 nds-form-leading-icon" aria-hidden="true"></i>
<input type="text" id="search-input-1" class="nds-search-input" name="search"
placeholder="Search services...">
<div class="nds-form-action">
<button class="nds-btn nds-subtle nds-clear" type="button" aria-label="Clear search" hidden>
<i class="nds-icon nds-hgi-cancel-01" aria-hidden="true"></i>
</button>
<button class="nds-btn nds-subtle nds-voice-input" type="button" aria-label="Start voice input">
<i class="nds-icon nds-hgi-mic-01" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="nds-form-footer" data-feedback-target hidden></div>
</div>
</div>
Built-in Features
Any button with nds-voice-input is wired automatically when the NDS.VoiceInput module loads: it installs a single document-level click handler, so buttons present now or added later all work with no per-button setup. No extra JS required.
Reads the page language at recognition start and sets ar-SA for Arabic pages or en-US for English, with no manual configuration needed.
Partial results appear in the field as you speak, styled in italic to distinguish them from committed text. The final transcript replaces them when speech ends.
A short tone plays when the microphone opens (high pitch), closes (low pitch), or encounters an error (very low pitch), giving clear non-visual feedback during dictation.
Listening automatically stops after 30 seconds of inactivity and shows a localized timeout message in the input placeholder, preventing the microphone from staying open indefinitely.
Call NDS.VoiceInput.isSupported() to check whether the browser provides the Web Speech API, so you can hide or omit the microphone button on browsers that cannot use it.
Usage Guidelines
Best Practices
- Use voice input on search fields and long free-text inputs where typing is burdensome. Short, constrained fields like phone numbers, postcodes, or PIN codes are not good candidates.
- Use the search input variant (
nds-search-input) for search fields. It includes the microphone button slot alongside the clear button by design. - Do not add voice input to password fields, OTP fields, or other security-sensitive inputs where dictation could expose credentials to bystanders or screen-recording software.
- Do not add voice input to
<select>or read-only inputs. The plugin targets the primary textinputortextareainside the form control and sets.valuedirectly. - Always provide a visible microphone icon in the button so users can identify it without reading the
aria-label. Use thends-hgi-mic-01UI icon for consistency with the rest of NDS. - On browsers without the Web Speech API the button is left in place: a click shows a localized "not supported" message in the field and the input keeps working as a normal text field. To omit the button entirely on those browsers, gate it with
NDS.VoiceInput.isSupported(). - The plugin requires microphone permission from the browser. Pair it with a visible permission explanation or tooltip when the feature is prominent in a service flow, so users understand why they are being prompted.
- In Arabic layouts the plugin sets
lang="ar-SA"on the recognition instance automatically. You do not need to setdirorlangon the input itself. - The button links to its input automatically when it sits inside an
nds-form-control. To place the button elsewhere on the page, point it at the field withdata-voice-targetset to the input'sidorname.
Error Messages
When recognition fails, the plugin sets a localized message as the input placeholder for 3 seconds. These messages are bilingual and chosen automatically by page language.
| Error Code | English Message | Arabic Message |
|---|---|---|
no-speech | No speech detected | لم يتم اكتشاف صوت |
not-allowed | Microphone permission required | مطلوب إذن الميكروفون |
audio-capture | Microphone access denied | تم رفض الوصول للميكروفون |
network | Network error | خطأ في الشبكة |
aborted | Voice input cancelled | تم إلغاء إدخال الصوت |
language-not-supported | Language not supported | اللغة غير مدعومة |
timeout | Voice input timed out | انتهت مهلة إدخال الصوت |
unsupported | Voice input is not supported in this browser | إدخال الصوت غير مدعوم في هذا المتصفح |
Listening State
When recording starts, the module adds listening to the data-state of the enclosing nds-form-container. The CSS uses that token to animate the microphone icon with a colour-cycling pulse, giving a visible recording indicator.
| Selector | Effect |
|---|---|
[data-state~="listening"] on .nds-form-container | Applied by JS when the mic opens; removed when the mic closes. Triggers the colour-cycle animation on the .nds-voice-input > i icon. |
Data Attributes
The button finds its input automatically when it sits inside an nds-form-control. Use a data attribute to link a button that lives elsewhere on the page.
| Attribute | Description |
|---|---|
data-voice-target="field-id" | Set on the button to point it at a specific input by id or name. Lets the button sit anywhere on the page, not just inside the form control. |
data-target="field-id" | The shared NDS targeting convention, accepted as a fallback when data-voice-target is absent. |
data-name="field-name" | Last-resort lookup on the input itself: if neither id nor name match the target value, the module queries for an element with a matching data-name attribute. |
JavaScript API
Voice input wires itself up: when the NDS.VoiceInput module loads it installs a single document-level click handler, so every nds-voice-input button (present now or added later) works with no per-button setup. The public surface is intentionally small.
// ── Install the delegated click handler (idempotent) ──
// Called automatically on load; only call it yourself after
// injecting markup before the module has initialized.
NDS.VoiceInput.init();
NDS.VoiceInput.reinit(); // alias for init(), safe to call again
// ── Browser support check ─────────────────────────────
// true when the Web Speech API is available. Use it to gate
// your own UI: hide or omit the mic button when unsupported.
if (!NDS.VoiceInput.isSupported()) {
// e.g. don't render the voice-input button at all
}