Skip to content

Accessibility

Announcer Library

The Announcer library allows for relevant information to be voiced along the focus path of the application. The Announcer traverses the focusPath of the app collecting strings or promises of strings to announce to the user. The array of information is passed to a SpeechEngine which is responsible for converting the text to speech. By default we use the speechSynthesis API, but you can replace this by overwriting Announcer._textToSpeech.

Note: The speechSynth api has some known problems:
https://stackoverflow.com/questions/39391502/js-speechsynthesis-problems-with-the-cancel-method
https://stackoverflow.com/questions/23483990/speechsynthesis-api-onend-callback-not-working

This class does its best to work around these issues, but speech synth api can randomly fail.

Usage

jsx
import { useFocusManager, useAnnouncer } from '@lightningjs/solid-primitives';
const App = (props) => {
  // Create a toggle to enable / disable announcer
  useFocusManager({
    Announcer: 'a',
  });
  const Announcer = useAnnouncer();

  Announcer.debug = false;
  Announcer.enabled = false;

   <View
      ref={window.APP}
      onAnnouncer={() => Announcer.enabled = !Announcer.enabled}
      ...
    </View>
import { useFocusManager, useAnnouncer } from '@lightningjs/solid-primitives';
const App = (props) => {
  // Create a toggle to enable / disable announcer
  useFocusManager({
    Announcer: 'a',
  });
  const Announcer = useAnnouncer();

  Announcer.debug = false;
  Announcer.enabled = false;

   <View
      ref={window.APP}
      onAnnouncer={() => Announcer.enabled = !Announcer.enabled}
      ...
    </View>

Set Announcer.debug = true to see console tables of the output as shown below.

IndexComponentPropertyValue
0BrowsePage-1TitleFree to Me
1GridTitle
2RowsTitle
3RowTitlePopular Movies - Free to Me
4ItemsTitle
5TileItemTitleTeenage Mutant Ninja Turtles: Out of the Shadows
6MetadataAnnouncePromise
7MetadataNo Context
8TileItemContext1 of 5
9ItemsNo Context
10RowNo Context
11RowsNo Context
12GridNo Context
13BrowsePage-1ContextPAUSE-2 Press LEFT or RIGHT to

The Announcer will travel through the focusPath looking for component.announce then component.title properties. After collecting those properties it reverses the focusPath looking for component.announceContext.

SpeechType

All of the properties may return values compatible with the following recursive type definition:

SpeechType = string | Array<SpeechType> | Promise<SpeechType> | () => SpeechType
SpeechType = string | Array<SpeechType> | Promise<SpeechType> | () => SpeechType

At its simplest, you may return a string or an array of strings. Promises and functions that return SpeechType values may be used as necessary for advanced/asyncronous use cases.

Examples

jsx
  <View
    announce={[
      'Despicable Me',
      Promise.resolve([
        ['2020', 'Rated PG'],
        Promise.resolve('Steve Carell, Miranda Cosgrove, Kristen Wiig, Pierre Coffin'),
        () => 'A description of the movie'
      ])
    ]}
    announceContext={'Press LEFT or RIGHT to review items'}
  <View
    announce={[
      'Despicable Me',
      Promise.resolve([
        ['2020', 'Rated PG'],
        Promise.resolve('Steve Carell, Miranda Cosgrove, Kristen Wiig, Pierre Coffin'),
        () => 'A description of the movie'
      ])
    ]}
    announceContext={'Press LEFT or RIGHT to review items'}

Inserting a pause

You may also use PAUSE-# to pause speech for # seconds before saying the next string.

js
['PAUSE-2.5', 'Hello there!'];
['PAUSE-2.5', 'Hello there!'];

API

Properties

nametypereadonlydescription
enabledbooleanfalsedefault true - flag to turn on or off Announcer
announcerTimeoutnumberfalseBy default the announcer only gets information about what changed between focus paths. The announcerTimeout resets the cache to announce the full focus path when the user has been inactive a certain amount of time. Default value is 5 minutes.

Methods

nameargsdescription
speakPerforms a manual announce
 announcementSee SpeechType above
 optionsObject containing one or more boolean flags:
  • append - Appends announcement to the currently announcing series.
  • notification - Speaks out notification and then performs $announcerRefresh.
clearPrevFocusdepthClears the last known focusPath - depth can trim known focusPath
cancelnoneCancels current speaking
setupTimersoptionsObject containing:
  • focusDebounce - default amount of time to wait after last input before focus change announcing will occur.
  • focusChangeTimeout - Amount of time with no input before full announce will occur on next focusChange