Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement accessibility defaults #150

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Implement accessibility defaults #150

wants to merge 8 commits into from

Conversation

erxclau
Copy link

@erxclau erxclau commented Aug 2, 2022

What's this PR do?

Essentially, this adds screen reader support for ai2html graphics and D3 graphics that use createBase.

  1. Adds an alttext parameter to the createBase function. If this argument is not provided, a warning will appear in the console. If it is provided, alttext will be set as the text read aloud by a screen reader via an aria-describedby attribute. The SVG will also be set to have an image role.
  2. Adds a nunjucks filter called addA11yAttributes that takes in html (string) and alttext (string). The HTML string is expected to be ai2html output. The filter adds an aria-describedby attribute to the ai2html wrapper and a role attribute set to img. The two artboards inside the wrapper are set to aria-hidden to prevent anything in the artboards (like axis labels) from being read.
    • Note that I previously used aria-description instead of aria-describedby but realized it was not working on iOS (i.e. no alt text was read aloud).
  3. If graphicTitle exists, then the title of the graphic document is set to graphicTitle. Otherwise, the title of the document is set to The Texas Tribune. In all practical cases, graphicTitle should probably be set.

Why are we doing this? How does it help us?

Currently, screen readers do not read our graphics in a helpful way. This PR tries to fix that. We did have an alt text variable but it just wasn't used anywhere.

The main objective of this PR is to make sure that graphics generated with createBase or ai2html have only the headline, chatter, alt text, notes, source, and credit read aloud. Textual elements such as axis numbers or bar labels should not be read aloud in this implementation. There may be cases when we want those textual elements to be read out. In such cases, the kit user should make exceptions to these defaults by implementing some custom solution.

How should this be manually tested?

There is a large matrix to test because I think operating systems and browsers in those operating systems all have slightly different screen reader behavior. MacOS (Chrome, Safari, Firefox), Windows (Chrome, Edge, Firefox), iOS, different Androids, etc.

Getting set up

  1. To use this branch, run npx github:texastribune/data-visuals-create#a11y graphic test-graphic.
  2. Download this zip file. You'll need it to test ai2html output and iframe behavior.
    • It contains an index.html file which has an iframe, and a test.html file which is ai2html output. It also contains two image files.
  3. Start the development server by running npm run start and navigate to http://localhost:3000.

Activating your screen reader

  • On a Mac, this is done by pressing CMD + F5.
  • On a Windows, this is done by pressing Windows + Ctrl + Enter.
  • On an iPhone, this is done by going to Settings, selecting the Accessibility section, and turning on VoiceOver. You'll need to use the network URL. If you feel stuck, you can tell Siri to turn VoiceOver on or off. Here is a list of gestures from Apple.
  • I don't have an Android phone but these instructions could help.

Testing createBase

  1. Open app/templates/graphic.html. Copy the contents of that file and paste it into app/index.html.
  2. Open app/scripts/packs/graphic.js. Replace renderGraphic with the following:
    export default function renderGraphic() {
      // pass the recalculated frameWidth to parts of your chart (like an axis) that change with resize!
      clearContainer();
      const frameWidth = getFrameWidth();
    
      const { drawAxis } = createBase({
        container,
        width: frameWidth,
        height: 500,
        margin: { left: 30 },
        // alttext: 'This is some alttext',
      });
    
      drawAxis();
    }
  3. Note the behavior of the screen reader. It is probably reading the header tag, and then reading all of the numbers in the axes. This is not desirable. Perhaps we should prevent this behavior too if there is no alt text provided.
  4. Uncomment the alttext argument. Note that the numbers in the axes are no longer read aloud.

Testing ai2html output

  1. Open app/templates/graphic-static.html. Copy the contents of that file and paste it into app/index.html.
  2. Open app/templates and create a folder called ai2html-ouput. Inside this folder, place the test.html file from the zip file.
  3. Open app/assets and create a folder called images. Inside this folder, place the two image files from the zip file.
  4. Replace {% set graphicAltText = context.alttext %} (on line 19) with {% set graphicAltText = 'This is some alt text' %}.
  5. On lines 38 and 39, uncomment the nunjucks expressions by replacing the hashtags with percent signs.
  6. On line 38, replace {% set ai2html = "" %} with {% set ai2html = "test" %}.
  7. Note the behavior of the screen reader. The text inside the graphic is read aloud.
  8. On lines 37 and 40, uncomment the nunjucks expression.
  9. Note the behavior of the screen reader. The text inside the graphic is not read aloud. The alt text is read in place.

Testing inside an iframe

Graphics on our website are embedded with an iframe so it's important that the screen reader still works when the document is inside an iframe.

  1. Place the index.html file from the zip file in the root of the repository. If you have VSCode open, you can use the Live Server extension to serve this file. Otherwise, you can use Python by running python3 -m http.server.
  2. If you are testing on a phone, you'll have to replace the src attribute with the network URL.

Note: it doesn't look like iOS Safari, iOS Chrome, or Windows reads the iframe title or embedded document title if they are set.

How should this change be communicated to end users?

N/A

Are there any smells or added technical debt to note?

The ai2html nunjucks filter is pretty brittle — it relies on there only ever being two artboards with pixel sizes 664 and 360. It won't break anything if those sizes change, but we'll have to change the filter to get the properties to show up.

Are we using the right tags and attributes?

What are the relevant tickets?

N/A

Have you done the following, if applicable:

(optional: add explanation between parentheses)

  • Added automated tests? ( )
  • Tested manually on mobile? (On an iPhone)
  • Checked for performance implications? ( )
  • Checked accessibility? (Yes!)
  • Checked for security implications? (There are no security implications)
  • Updated the documentation/wiki? ( )

TODOs / next steps:

  • Update version
  • Update CHANGELOG
  • Publish to npm

@erxclau erxclau marked this pull request as ready for review August 4, 2022 21:27
Copy link
Member

@ashley-hebler ashley-hebler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such a great a11y improvement! All test steps work and make sense to me.

You are correct in that the context.altext values weren't really being surfaced anywhere, but glad to see those values in the sheet and that we'll be making use of those finally. Some background there is that we were hoping to one day use that for places where we'd have to fallback to static images of the whole graphic page where iframes aren't supported like Apple News or even Twitter/IG. We're obviously not doing that yet and this is a more direct and impactful use that alt text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants