as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support

Vega Web App Accessibility Guide

For Vega Web Apps, we suggest you follow the guidelines from WCAG (minimum AA), and WAI-ARIA. WCAG covers all the aspects of the accessibility.

The goal of accessibility is to deliver a TV app that supports users with the following types of disabilities:

  • Visual – from color blindness to complete blindness
  • Mobility – from limited dexterity to difficulty performing gestures
  • Speech – from accented speech to being non-verbal (if voice input is used)
  • Cognitive – including learning disabilities, difficulty with complex instructions
  • Hearing – from partial to complete hearing loss

A WebView could be an HTML, ReactJS, or Angular app. An accessible WebView includes 3 layers:

  1. Web apps: It is the developer’s responsibility to write and implement accessible code.
  2. Vega WebView wrapper: This is provided by the Vega team.
  3. OS: All required accessibility support and APIs have been provided at the OS level.

Vega WebView wrapper

To make your HTML/Angular/React app a Vega Web App, wrap it with the Vega WebView wrapper.

The focus should go inside your app: for this it is important to have the following.

  1. Initial focus must enter the app container.
  2. Expose TV-remote events (DPAD, Select) as keyboard events.
  3. Test the app with assistive technologies on the device.

Web apps

This is the layer to focus on making your app accessible. In frameworks like VueJS, ReactJS, React Native, React Native for Vega, and AngularJS, write using JSX or HTML-like templates.

Resources to explore

  1. ReactJS accessibility Guide
  2. Angular Accessibility Guide

Accessibility guidelines

Use the following guidelines to implement accessibility.

Semantic HTML structure

  • Use meaningful HTML tags. For example, use semantic HTML tags like <header>, <footer>, and <nav>. For buttons, use the <button> element instead of <div> or <span>. For links, use <a> instead of non-semantic elements. These semantic tags are recognized by the platform and assistive technologies, such as VoiceView, Screen Magnifier, and TextBanner. Most accessibility is handled automatically when used correctly.
  • Use a hierarchical heading structure: Maintain ordered headings in your app, from <h1> to <h6>. This helps screen readers and other assistive technologies understand the content hierarchy, which improves overall navigation.

Accessible Rich Internet Application (ARIA) tags

  • There may be cases where you need to use non-semantic elements, such as when building custom components like tiles, cards, or carousels. In these cases, use ARIA attributes to communicate the purpose and behavior to assistive technologies.
  • In simple terms, ARIA attributes help provide three key types of information:
    • What the element is. Example: role="button"
    • What it does. Example: aria-pressed, or aria-expanded
    • Additional context or labels. Example: aria-label, or aria-describedby
  • For a list of ARIA tags, properties, and methods you can use, see the ARIA Authoring Practices Guide.
  • Example of ARIA usage:
<section aria-labelledby="features-title">
  <h2 id="features-title">Accessibility Features</h2>
  <p>This section describes how to make your content accessible.</p>
</section>

Alt or image and icon descriptions

VoiceView doesn’t understand images or graphics. Therefore, provide an alt or meaningful description. For example, for a settings icons, use a description like “settings” rather than “an image of a setting icon” or "an icon." VoiceView will add "an image…" or "link image…". Adding text like "an image" or "an icon" is not meaningful.

<img src="" alt="Settings">
  • Decorative Images: Skip the alt tag for purely decorative images with no user value.
  • Repeating Text: Don’t repeat nearby text in the alt tag or aria-label if the image already contains it.

Focus management

  • Focus to an element should be visible and clear. Follow the WACG guidelines.
  • If you are using semantic HTML tags (button, and a), then by default you will see the focus ring or you can customize according to your app’s design and VoiceView will be able to identify and read out aloud.
  • For the initial focus, use the React/Angular autoFocus prop.
  • If you are using a non-semantic tag then write custom JavaScript code to apply focus, and a custom style onFocus.
  • Use tabindex only when
    • You're making a non-focusable element focusable.
    • Customizing focus order carefully. This is for modals or custom components. ```html
    Focusable div using tabindex

    // this is to make an element focuable ```

  • Letter spacing: Keep it consistent and avoid overly tight or loose spacing.
  • Avoid all-caps: Especially for long sentences, as it's harder to read.
  • Line height: Use at least 1.5 (or 150%) to improve legibility as per WCAG.
  • Maintain consistent typography.

Programmatic announcements

There are options for developers who are building software that doesn’t have tags or need to announce information programmatically. This is particularly useful for web apps that use canvas to draw charts, diagrams, interactive navigation, or 3D world elements.

Option 1: Use a div specifically for announcements and update the text that should be used for announcements.

Copied to clipboard.

<!-- index.html -->
<div id="announcer" aria-live="assertive" aria-atomic="true"></div>

<script>
  const announcerDiv = document.getElementById("announcer");

  // Simulate an update
  setTimeout(() => {
    announcerDiv.textContent = "New Announcement!";
  }, 5000);
</script>

Option 2: Use postMessage to send a message to the Vega WebView container and then handle this message using onMessage. In onMessage, invoke AccessibilityInfo.announceForAccessibility();. This takes a little more setup but will end up operating similarly to how SpeechSynthesis works.

In this example, a type-value messaging pattern is used much like JSON API or socket data industry standards. This way, when messages are sent or received, it is easier to serialize and deserialize different data types. The top script is the web app while the bottom is the Vega Web App code.

Copied to clipboard.

<!-- index.html -->
<script>
  const message = JSON.Stringify({
    type: "announcement",
    value: "New Announcement!"
  });
  
  // use postMessage to send data to Vega Web App.
  window.ReactNativeWebView.postMessage(message);
</script>

Copied to clipboard.

// App.tsx
import { AccessibilityInfo } from "@amzn/react-native-kepler";

export const App = () => {

  // implement to return value if type is "announcement"  
  const getAnnouncement = (message: string) => {};

  return (
    <WebView
      source={{ uri: 'https://amazon.com' }}
      
      // use onMessage to receive data from postMessage
      onMessage={(event: WebViewMessageEvent) => {
        const announcement = getAnnouncement(event.nativeEvent.data);
        
        // announce
        AccessibilityInfo.announceForAccessibility(announcement);
    }}
    </WebView>
  );
};

Typography and color

  1. Font sizes must meet readability criteria.
  2. Use a color contrast ratio ≥ 4.5:1 for normal text and ≥ 3:1 for large text. As per WCAG Check https://webaim.org/resources/contrastchecker/
  3. Visual focus should be have the color which should not merge with the background
  4. Font family should be easy to understand. Avoid using too cursive or light
  5. Have line height which makes the content easy to read

and many more.

VoiceView

Test with VoiceView to avoid redundant announcements, maintain a correct reading order, and enable live updates (aria-live). Check the FAQ for common issues.

Test Playback, Alexa , and other Audio behavior.

To hide non-interactive content from the accessibility API, use aria-hidden="true". Check the MDN docs for details. This content could be:

  • Purely decorative content, such as icons or images
  • Duplicated content, such as repeated text
  • Offscreen or collapsed content, such as menus

Accessibility features in Vega WebView

  1. TV Remote (DPAD, Back, Select)
  2. VoiceView (screen reader)
  3. Magnifier (screen zoom)
  4. Captions/Subtitles

Accessibility options in the Fire TV menu

Enabling accessibility elements in WebView

Enable VoiceView

  1. Navigate to Accessibility Settings
  2. Toggle VoiceView ON

Turning on VoiceView in the Fire TV menu

Hide elements for VoiceView

To hide VoiceView elements, use the following.

Copied to clipboard.

aria-hidden="true"

How to notify VoiceView of an element when the default accessible name is missing

Use the following so that VoiceView knows about the element.

Copied to clipboard.

<button aria-label="Close dialog">X</button>

Announcing dynamic values

HTML, ReactJS, Angular uses aria-live. For more details, see ARIA: aria-live attribute. Use the following to announce dynamic values.

Copied to clipboard.

<div aria-live="polite" id="status"> <!— Text inserted here will be announced --></div>

Test cases

Below are suggested minimum test cases. You may use them for your app’s accessibility testing.

VoiceView

Enable and disable VoiceView

  1. Navigate to Accessibility Settings
  2. Toggle VoiceView ON/OFF

Use app with VoiceView enabled

  1. Enable VoiceView
  2. Navigate through the app using your remote
  3. Verify voice prompts for each UI element

Verify new screen spoken text

On a new screen, the header, description, usage hints, orientation text, and currently focused item are spoken

  1. Navigate to different app sections (Home, Settings, Content, etc.)
  2. Confirm VoiceView output

Verify navigation and spoken elements

Make sure a user can navigate (using directional pad/select/quick select actions on buttons) to all actionable elements, that the focused element is spoken in full, and that static text related to the element is spoken in Normal Mode

Verify the spoken focused element after a pause

You should hear spoken Usage Hints, Orientation Text, Described By, and Static Text after a short pause (~0.5 seconds)

Verify images and icons include descriptive text

If images provide instructions, all instructions must also be described in alt-text for VoiceView to speak

Verify VoiceView in Review Mode

Hold menu for 2 seconds with VoiceView on. The user should be able to navigate (Left/Right on directional pad) to all text and controls, with change in granularity (Up/Down on directional pad). User needs to be able to read non-actionable text and items in Review Mode

Verify accessibility gestures

For instance, double click to activate an item, or perhaps long press

Magnify (screen zoom)

Enable and disable magnification

  1. Go to Accessibility
  2. Enable Magnifier
  3. Verify it zooms in/out

Zoom functionality across UI

  1. Try zooming text, buttons, images
  2. Confirm proper scaling and visibility

Zoom preserves readability and doesn’t clip content

  1. Zoom in/out on all screens
  2. Verify that the layout is preserved and scroll works

1.5x zoom for 1st time

  • Go to setting
  • Make sure zoom is off
  • Activate zoom
  • Observe zoom and app behavior

Zoom preserves as per user's preference after 1st visit

  • Go to setting
  • Make sure zoom is off
  • Activate zoom
  • Observe zoom and app behavior
  • Close the app
  • Reopen the app or power on the device again
  • Verify the zoom level is preserved from before

Verify magnifier on focus

Make sure the user can navigate (using directional pad/select) to actionable controls and that the magnifier follows the focus

Verify user can explore (using menu+directional pad to Pan) all text and controls

Subtitles / captions

Enable and disable subtitles

  1. Play video
  2. Toggle subtitles in player/settings
  3. Confirm visibility

Verify user can set styles for Close Captioning

Use CC Settings in your Local player while on the Global setting

  1. Change subtitle settings
  2. Verify UI updates accordingly

Subtitles persist across sessions (if applicable)

  1. Enable
  2. Exit app
  3. Reopen
  4. Check if setting persists

Subtitle accuracy and sync with audio

  1. Play content
  2. Confirm subtitles are in sync and accurate

Verify the user gets accurate Close Captions

Captions should be limited in delay and follow content

Font / text size

Increase and decrease text size

  1. Access font settings
  2. Adjust size
  3. Verify text scales correctly across UI

Font changes are retained across app

  1. Change font size
  2. Navigate to different screens
  3. Confirm consistency

No layout breaking with a large font

  1. Set maximum font size
  2. Verify no UI clipping or overlap

Focus / visual indicator

Every actionable element has a visible focus ring

  1. Use remote to navigate through all UI
  2. Check focus ring on each element

Consistent focus order (logical navigation flow)

  1. Navigate using the remote
  2. Confirm intuitive focus order (top-to-bottom, left-to-right)

Optional: Audio feedback on focus change

  1. Enable audio cues
  2. Navigate
  3. Confirm audible indication on focus change

Focus not lost after user action, such as on modal close

  1. Open and close modals or dialogs
  2. The focus returns to the expected element
  1. Use D-pad, Back, Select buttons
  2. Verify all areas are accessible without touch input

Keyboard navigation support (if supported)

  1. Test with external keyboard or accessibility input device
  2. Verify all interactive areas

No trap zones (can navigate away from all areas)

  1. Try entering/exiting modals, menus, and carousels
  2. Verify there are no dead ends

Latency

Verify accessibility metadata loads as part of standard payload package

Verify user is informed that the content is loading on screen (Visual and audible)

Verify user is not blocked if connection times out

This also applies if they are offline.

Accessibility by design

Verify images and icons are marked up with descriptive text

If images provide instructions, all must be described in alt-text for VoiceView to speak.

Verify status is communicated through multiple means

Some of those communication means might be text, color, and sound.

Verify all icons have text description

Even commonly used icons need text descriptions.

Troubleshooting

If no items are spoken in the app when VoiceView is enabled

Check the accessibility markup.

If a UI element reads as a button

This is because UI elements don't have accessibility labels or descriptions, but they have accessibility roles set as button.

If UI elements are different from what's visually displayed

This could be because the app didn’t properly set the focused element for accessibility.

If the Title or UI element is spoken more than once

This could be due to duplicate A11Y announcements. Remove all duplicate A11Y announcements.

If there is continuous reading during video playback

This could be an incorrect use of label so that the focus is on content details instead of the video player component, which has no text inside it. The app must not focus on the element/node when it isn’t visually focused on the screen during video playback

Audio ducking is not working

If VoiceView starts to speak during video playback, VoiceView speech gets priority, and the video playback audio should duck.


Last updated: Sep 30, 2025