The voice utility manages the user's preferred speech-synthesis voice across the site. It mirrors the theme utility — persisting to localStorage, syncing across tabs via the storage event, and exposing a pub/sub API. Pair it with <k-voice-selector> for a settings UI; <k-text-to-speech> automatically uses the saved preference when no voice attribute is set.
import voice from './utils/voice.js';
// Get current preferred voice (empty string = use browser default)
const current = voice.get();
// Set a preferred voice
voice.set('Google US English');
// Subscribe to changes
const unsubscribe = voice.subscribe((name) => {
console.log('Voice preference changed to:', name);
});
// Enumerate available voices (may need to wait — the list loads async)
const voices = await voice.waitForVoices();
voice.get()Returns the user's saved voice name. An empty string means "no preference — use the browser default for the language".
stringvoice.set(name)Sets the saved voice and persists it to localStorage. Pass an empty string (or a falsy value) to clear the preference.
name: stringThe voice name as reported by speechSynthesis.getVoices(), or a comma-separated fallback chain ("Samantha, Google US English").
voice.subscribe(callback)Subscribes to preference changes. Fires once immediately with the current value, then on every change (including changes from other tabs).
FunctionAn unsubscribe function.
voice.getAvailable()Synchronous shortcut for window.speechSynthesis.getVoices(). May return [] if the browser hasn't populated the list yet.
SpeechSynthesisVoice[]voice.waitForVoices(timeoutMs?)Returns a promise that resolves with the list of available voices, waiting for the browser's voiceschanged event if the list is initially empty.
timeoutMs: number — default 2000How long to wait before giving up and resolving with whatever the browser has.
Promise<SpeechSynthesisVoice[]>voice.subscribeAvailable(callback)Subscribes to changes in the available voice list (fires on the voiceschanged event). Useful when populating a settings UI.
FunctionAn unsubscribe function.
import voice from './utils/voice.js';
const $select = document.getElementById('voice-picker');
voice.subscribeAvailable((voices) => {
$select.innerHTML = '<option value="">Browser default</option>';
for(const v of voices){
const opt = document.createElement('option');
opt.value = v.name;
opt.textContent = `${v.name} (${v.lang})`;
$select.appendChild(opt);
}
$select.value = voice.get();
});
$select.addEventListener('change', () => voice.set($select.value));
import voice from './utils/voice.js';
const preferred = voice.get();
if(preferred){
console.log(`User picked: ${preferred}`);
} else {
console.log('No preference set — using browser default');
}