screen reader grid and readout shortcuts
This commit is contained in:
@@ -4,6 +4,7 @@ export interface NarratorSettings {
|
||||
pitch: number
|
||||
voice: string
|
||||
verbosity: 'brief' | 'normal' | 'verbose'
|
||||
mode: 'voice' | 'screenreader' | 'both'
|
||||
sounds: boolean
|
||||
}
|
||||
|
||||
@@ -13,6 +14,7 @@ export const defaultNarratorSettings: NarratorSettings = {
|
||||
pitch: 1.0,
|
||||
voice: '',
|
||||
verbosity: 'normal',
|
||||
mode: 'voice',
|
||||
sounds: true,
|
||||
}
|
||||
|
||||
@@ -36,8 +38,42 @@ export function cancel() {
|
||||
window.speechSynthesis.cancel()
|
||||
}
|
||||
|
||||
// a polite live region that screen readers announce from, created on demand
|
||||
let srRegion: HTMLElement | null = null
|
||||
|
||||
function getSrRegion(): HTMLElement {
|
||||
if (!srRegion) {
|
||||
srRegion = document.createElement('div')
|
||||
srRegion.setAttribute('aria-live', 'polite')
|
||||
srRegion.setAttribute('role', 'status')
|
||||
srRegion.className = 'visually-hidden'
|
||||
document.body.appendChild(srRegion)
|
||||
}
|
||||
return srRegion
|
||||
}
|
||||
|
||||
function announceToScreenReader(text: string) {
|
||||
const region = getSrRegion()
|
||||
const msg = document.createElement('span')
|
||||
msg.textContent = `${text} `
|
||||
region.appendChild(msg)
|
||||
while (region.children.length > 6) {
|
||||
const first = region.firstChild
|
||||
if (first) region.removeChild(first)
|
||||
}
|
||||
setTimeout(() => msg.remove(), 15000)
|
||||
}
|
||||
|
||||
export function speak(text: string, interrupt = true) {
|
||||
if (!isSupported() || !settings.enabled) return
|
||||
if (!settings.enabled) return
|
||||
|
||||
const mode = settings.mode
|
||||
const wantsVoice = (mode === 'voice' || mode === 'both') && isSupported()
|
||||
const wantsSr = mode === 'screenreader' || mode === 'both' || !isSupported()
|
||||
|
||||
if (wantsSr) announceToScreenReader(text)
|
||||
if (!wantsVoice) return
|
||||
|
||||
if (interrupt) cancel()
|
||||
|
||||
const utterance = new SpeechSynthesisUtterance(text)
|
||||
@@ -57,9 +93,6 @@ export function speak(text: string, interrupt = true) {
|
||||
export function preloadVoices() {
|
||||
if (!isSupported()) return
|
||||
getVoices()
|
||||
if (window.speechSynthesis.onvoiceschanged !== undefined) {
|
||||
window.speechSynthesis.onvoiceschanged = () => {}
|
||||
}
|
||||
}
|
||||
|
||||
preloadVoices()
|
||||
preloadVoices()
|
||||
Reference in New Issue
Block a user