How a Card Matching game is compliant with international accessibility standards
Guy Barker
Exploring how to make apps more accessible to more people, and sharing all I learn.
This article describes how an exploratory card matching game complies with some of the accessibility standards included in the European Standards EN 301 549, and encourages all app-builders to respect those standards as part of the process of building great experiences for all customers.
Introduction
How many of you have been Person A in the following conversation?
Person A: “It looks like your sample app isn’t accessible. Is there anything I can do to help with that?”
Person B: “It doesn’t have to be accessible. It’s not an accessibility sample.”
A few weeks ago, I downloaded a sample app from the web. I don’t remember what the app was demonstrating, but it came in the form of a matching pair game, where pairs of pictures were to be found in a set of pictures. As I considered the app, it became apparent that it wasn’t accessible. It seemed to be the classic situation where the app had been designed for use by sighted players who can use touch or the mouse at their device. The game wasn’t keyboard accessible, had an unusable programmatic interface, relied on a fast timer, provided no control to players on colours shown in the app, and so on. This got me thinking. If I was to build a matching pair game, how could I build it in a way to support all players?
This article describes my subsequent exploration. While some technical details mentioned are specific to the type of UI technology I used to build the app, (I used the same technology as that used by the sample app I mentioned earlier), the principles apply to any UI.
In addition, I’ll mention specific EN 301 549 standards which relate to some of the app’s features. While the size of the set of standards included in EN 301 549 V3.2.1 may seem daunting to people who’ve not reviewed it before, you’ll find that if your product is designed to provide a great experience for all customers, many of the standards will automatically be met. For example, by designing for people who only use the keyboard as their input device, your app will support many of the keyboard-specific standards included in EN 301 549.
At European Standards EN 301 549, Microsoft states: “Microsoft's consideration of EN 301 549 in the development of products and services points to its commitment to accessibility for all customers.”
For anyone interested in the source code for my new game, it’s freely available at WinFormsMatchingGame at GitHub.
The Accessibility Insights for Windows tool used to verify the programmatic interface of the game during development, is available at Accessibility Insights for Windows.
Now, before discussing technical details and standards, first I’ll describe how to play the game.
?
To Play the Game
The game is feely available at the Microsoft Store, at Accessible Matching Game.
The game uses free software from Microsoft when it runs, called .NET 5, (pronounced “dot net five”). If that software isn’t already installed on your computer when the game is run, a message pops up saying that .NET 5 needs to be installed, with a link to a page where the software is available. That linked-to Download .NET 5.0 page is very technical and it’s not particularly clear as to what should be done when at the page, so I’ll include the specific .NET 5 download link here, x64 .NET Desktop Runtime. (The game only runs on 64-bit Windows computers, but that’s most Windows computers these days.)
When the game runs, it shows a grid of four-by-four blank squares. The squares can be considered to be face-down cards. When a card is clicked, the card is turned up revealing a picture. The goal is to turn up pairs of cards, such that the pictures revealed by the two face-up cards are the same. If the pictures on the two turned-up cards are not the same, the player turns those cards back down, and the search for two matching pictures continues. If a pair of matching pictures is found, those cards remain face-up for the remainder of the game, and other face-down cards are turned up. Once the eight pairs of pictures have been revealed, the game is over and the count of attempts to find the pairs of pictures is shown.
Game-specific instructions for keyboard use are shown in the main window in the app.
To click one of the cards shown in the app using speech input, say "Click Card" followed by the number of the card. The cards are numbered from 1 to 16, reading left to right then top to bottom. For example, to click the first card on the bottom row, say "Click card 13".
Figure 1: The main window in the Card Matching app, showing the 8 pairs of default pictures.
Any set of 8 pictures can be shown in the game, and those pictures’ accessible names are supplied by the player. Optionally, accessible descriptions of the pictures can also be provided. These details are provided through the game’s Settings window.
By supporting player-supplied pictures, the game can become more personal, (for example, by showing pictures of family members and friends), or educational, (for example, by showing pictures relating to subjects about which the player wishes to become more familiar).
Figure 2: The Settings window in the Card Matching app, listing picture files and accessible names relating to recent recipients of the Nobel Peace Prize.
Figure 3: Accessibility Insights for Windows reporting the UIA hierarchy and names of a set of player-supplied pictures associated with recent recipients of the Nobel Peace Prize.
?
Accessibility standards compliance in the game
By default, when building Windows games for everyone to play, it's best to leverage standard controls which come with the UI framework being used to build the app. Typically standard controls for Windows have built-in support for some level of accessibility, and so they provide a great head start when building an accessible app. So the first question is, what would be the most appropriate control to use for the grid of cards?
Given that the game is basically a grid of cards, one option that seemed attractive was to use a WinForms DataGridView control, as that control supports many of the EN 301 549 standards automatically. Below I’ll list some of those standards and comment on how they relate to the game’s UI overall or to the grid specifically.
Please note that the set of EN 301 549 standards mentioned below is not a comprehensive list of all the standards that relate to the game’s UI, and are only a subset that I chose to include here.
Also, some links have been provided below relating to the Success Criterion associated with specific standards.
11.1.1.1 Non-text content
The game’s UI supports the Windows UI Automation (UIA) API, meaning that assistive technologies such as screen readers can access textual information associated with the pictures shown in the game.
11.1.3.2 Meaningful sequence
The programmatically accessible hierarchy of elements in the UI matches its logical sequence. This means players who navigate through the UI using screen readers that follow that programmatically accessible hierarchy, are provided with an intuitive experience.
The following image shows Accessibility Insights for Windows reporting a UIA Table representing the card grid, with four child elements representing the rows in the grid, with each of those four child elements containing four UIA Buttons representing the cards in each row.
Figure 4: Accessibility Insights for Windows reporting the UIA hierarchy and names of a set of player-supplied pictures associated with actors from the film Oceans 8.
Figure 5: Accessibility Insights for Windows reporting the UIA hierarchy and names of a set of player-supplied pictures associated with subatomic particles.
Important: Whenever I added, removed, or rearranged controls in a window while building the app, I ran Accessibility Insights for Windows to verify that the order of the elements in the programmatically accessible UIA hierarchy matches the logical order of the UI. If the UIA order is not as expected, I reordered the calls to Add() in the window's Designer file as necessary, to create the required UIA order for the elements within the window. While editing the Designer file, I also manually removed all setting of the TabIndex property. The TabIndex will be added back as required later by Visual Studio. By taking this action, the game UI provides both the programmatic order and the tab order required by players.
11.1.4.13 Content on hover or focus
The game is compliant with this standard because it never presents additional content based on pointer hover or keyboard focus moving.
Note that it was very deliberate that the game should not present additional content based on pointer hover or keyboard focus moving. Rather, the goal was that all important information presented to players would be included in labels shown in the UI, so players can carefully review the information whenever they want to. As part of achieving this end-result, the DataGridView’s ShowCellToolTips was set False.
11.2.1.1 Keyboard
Due to the use of standard controls in the app, all functionality provided by the game is accessible through the keyboard.
The WinForms platform also provides support for further custom behaviours in response to keyboard input, and this was leveraged in order to support having an Enter key press turn unmatched face-up cards over. Note that care was taken while adding custom key input handling, to not unintentionally break the DataGridView’s built-in support for keyboard use. For example, the DataGridView supports a press of the F3 key to change the sort order of the grid when keyboard focus is in the grid.
Further details relating to keyboard input at the grid are at Default keyboard and mouse handling in the Windows Forms DataGridView control.
领英推荐
Note: I’m not aware of a way to change the width of the DataGridView’s columns using only the keyboard.
In the interests of input efficiency, all focusable controls in the app have unique keyboard shortcuts.
11.2.2.1 Timing adjustable
The game is compliant with this standard because no action is triggered in the app based on a time limit. That is, all action occurring in the game is triggered through explicit input from the player.
11.2.4.3 Focus order
The order of keyboard focus in the game follows a logical sequence. A press of Tab or Shift+Tab moves keyboard focus to the next or previous control in the UI respectively.
The DataGridView control’s StandardTab property was intentionally set True in order to have Tab key presses not move keyboard focus between adjacent cells inside the grid. Rather, a Tab press moves keyboard focus into the grid, then Arrow keys are used to move around the grid, and a subsequent press of Tab moves keyboard focus out of the grid.
11.2.4.7 Focus visible
Technically, the UI does show where keyboard focus is in the game, but personally I do think it’d be helpful if there was a trivial way for an app-builder to support having the focus visuals much more prominent for players who would prefer that.
Note: As I understand things, the DataGridView doesn't support a property like the WinForms ListView’s HideSelection property. This means the visuals shown on the currently selected cell in the grid look almost identical when the grid has keyboard focus and when it doesn't.
11.3.2.1 On focus
As keyboard focus moves around the app, there’s no change of context.
11.3.3.1 Error identification
If information that’s required to be supplied by the player is missing when attempting to save details of a custom set of pictures, a message is shown in the app stating what details are required. When the message is dismissed, keyboard focus moves to the input field relating to the missing details.
11.3.3.2 Labels or instructions
The app shows text labels providing instructions on what details are expected to be supplied by the player in the input fields in the app. Those labels are shown close to the input fields to which they relate.
The labels provide identification of which fields require information, and do not rely on players assuming the meaning of fields which are marked with an asterisk.
11.4.1.2 Name, role, value
Note: This is where I would be very interested in feedback from players on the best app experience.
By default, I would say that the names of cards in the game should never change. For example, a card might have a name of "Card 1" or "Card 8", and its name would not change based on whether it’s currently face-up or face-down. Any current state data associated with the card would be programmatically exposed through other properties, such as its value. However, conveying the image shown on the card is essential when playing the game, and a card's value might not be announced due to a screen reader's current settings. As such, the image data is currently incorporated into the card's name.
Note: The Role property of the cards has been left with the default value of Button. While WinForms provides a way to customize the role of a cell in a DataGridView, that customization does not always impact the experience provided through the Windows UI Automation API. For example, if an WinForms AccessibleRole of Graphic is set on the cell, it still gets exposed through UIA as a Button.
Note: I’m not aware of a way to customize the UIA LocalizedControlType property for the elements representing the rows in the grid, and so those elements are left with a ControlType of Custom, and no LocalizedControlType property at all.
By default, the accessible names of the TextBox and DataGridView controls shown in the app are taken from the labels that precede those controls. Consideration was made as to whether those exact labels were the best match for the accessible names of the controls, and where necessary, more appropriate accessible names were explicitly set instead.
11.5.2.5 Object information
The game supports player-supplied descriptions of the pictures shown in the DataGridView. Those descriptions are exposed programmatically through the UIA HelpText property.
Note: The Description property of a class derived from DataGridViewButtonCellAccessibleObject does not get exposed through UIA as UIA clients would expect it to, so that property is not overridden in the app. Rather, the Help property is used to describe the image shown on a card, and that gets exposed through the UIA HelpText property.
Note: I’m not aware of a way to programmatically expose a DataGridView cell as having a UIA IsRequiredForForm property of True.
11.5.2.6 Row, column, and headers
The row and column indices of the cards in the grid are exposed through the UIA GridItem pattern. The grid does not present headers.
Note: For coding convenience, the grid uses a hidden column to store the full file path for the player's picture files. While that column data is not exposed through UIA, the column indices for all the columns after that column are increased by 1. This may cause some confusion for players using screen readers, as it gives the impression that there's a column somewhere in the grid which is inaccessible to them.
11.5.2.15 Change notification
Note: This is where I would be very interested in feedback from players on the best app experience.
In response to specific actions occurring in the game, the app notifies screen readers of those actions. In the current version of the game, the following three notifications are made.
The goal in announcing these notifications is to provide as efficient a player experience as possible.
11.6.2 No disruption of accessibility features
If the player has selected specific Windows accessibility features, the app does not interfere with those features. For example, if the player is using a specific Windows high contrast theme, all controls’ UI in the app will respect those theme colours. This particular behaviour was straightforward to achieve by not adding use of any custom colours to the app.
Figure 6: The Settings window showing only colours from the “High Contrast Black” theme.
A few other notes
I did wonder about showing a thumbnail preview of player-provided pictures in the ListView in the Settings window. I decided against that given that unless the list rows were relatively tall, the picture previews would be too small to be useful to many players.
I’m very keen that players don’t unintentionally lose the changes they’ve made in the Settings window. For example, a player could go to a lot of effort to add helpful accessible names and descriptions, and they’d not want all this work to be lost due to an unintentional press of the Escape key. To account for this, the app presents a confirmation dialog before changes are lost.
Traditionally some desktop apps struggle with low resolution support. The apps may claim to support a very low resolution because their main window adapts its layout as the screen resolution changes. But then they also have fixed sized dialogs which don't fit at the same low resolution that's supported by the main window. My card matching game currently supports a minimum resolution of 1024x768.
Note: Due to the use of standard controls in the app, the app supports the Windows Magnifier feature. As such, players can use a combination of a low screen resolution and magnification if they prefer such a combination.
A standard included in the current version of EN 301 549 which is not met by the game is 11.1.4.10 Reflow. The UI framework on which the game is built does not make it practical for the game’s UI to be compliant with this standard. I do not consider this to be a concern for players in practice given that the nature of the game’s UI is quite different from that of the type of UI associated with the original WCAG standard on which 11.1.4.10 Reflow is based.
A few technical resources
The following resources show code snippets relating to customizing the accessibility of the cells in a WinForms DataGridView control.
For other technical accessibility resources relating to WinForms and other Windows UI Frameworks, please visit Common approaches for enhancing the programmatic accessibility of your Win32, WinForms and WPF apps.
Summary
Historically many sample apps have been inaccessible. This means that many people cannot learn from the samples, and sample code which leads to inaccessible UI gets copied and pasted around into shipping products. By designing all apps to be accessible, including sample apps, these problems can be avoided. And typically on Windows, leveraging standard controls that come with the UI framework being used to build the app is a very important part of the process of delivering a great experience for all your customers.
So please do design for accessibility, and verify that your product complies with the accessibility standards in EN 301 549. While the end goal here is to build great experiences for all, rather than specifically to meet a set of standards, the standards can help to achieve that end goal.
Finally, if you would like me to update my card matching game in some way such that it can be more helpful or fun for you or someone you know, please let me know. I’ll do my best to make those updates.
All the best,
Guy
Director of Accessibility Program and Innovation | Sustainable accessibility through skills | Program Manager, Designer, and Strategist | Ex-Microsoft
3 年I'm so glad you're still contributing your expertise to the industry. And you make it look easy. I hope you're doing well.
Quality Assurance Engineer - Alexa Music at Amazon
3 年Very nice Guy. You are an inspiration to others.??
Assistive Technologies Engineer
3 年Nice work Guy. Just wrote a similar app as part of teaching myself how to write in SwiftUI (see https://cs193p.sites.stanford.edu/). Would be interesting to see your compare and contrast notes if you ever decided to take a look.
Senior Product Manager, Document Cloud Accessibility, Adobe
3 年Still rocking it in a11y I see.
Principal Technical Program Manager (Accessibility)
3 年Nice!!