Web Accessibility To-Do List for MODx Manager
Evaluation by Paul Bohman using automated tools such as FireEyes/WorldSpace by Deque, Wave by WebAIM, but mostly this is a manual evaluation comparing the actions of the web site against the Web Content Accessibility Guidelines 2.0 and web accessibility best practices.
Table of Contents
Executive Summary
Accessibility to people with disabilities is critical not only for the individuals with disabilities themselves — who currently cannot use the MODx manager — but also for companies hoping to use MODx. Government entities, in particular, would be legally at risk if they decided to use MODx because of the non-compliance of the manager interface with web accessibility guidelines.
This evaluation is still incomplete, but some trends have emerged:
- Keyboard accessibility:
- There are many, many places in the MODx manager where a mouse is required. This makes it impossible for blind screen reader users to use, because the mouse is not useful to someone who can't see where to click it. It also makes it impossible for sighted keyboard users who can't use a mouse, perhaps because they have tremors in their hands, or have no hands and user a mouth stick, or they have another similar condition. Many of the dynamic widgets (tablists, multi-select lists, etc.) need to be enhanced with ARIA attributes and ARIA-style keyboard patterns to enable effective screen reader interaction.
- Keyboard focus management:
- The keyboard focus needs to follow the action of dynamic scripts (modal windows, form validation, etc.).
- Labels and text alternatives:
- Every active element (links, buttons, etc.) and every important image-like element (graphics and font icons) needs a text label or a text alternative. Without a label or text alternative, screen readers have nothing to read, so users don't know what the elements are.
There are other issues too, but the above issues are pervasive and need to be addressed broadly across the MODx manager.
Background Information About Web Accessibility
- Visual Disabilities:
- Blind screen reader users need:
- alt text for images, icons, etc.
- labels on form elements
- full keyboard accessibility of all functionality, including drop-down menus, tool-tips, tab lists, modals, etc.
- focus management with dynamic content such as error/feedback messages, dynamically-loaded AJAX content, etc.
- logical tab order
- valid link and button text
- good document structure (headings, table headers, lists, landmark regions)
- Low vision users need:
- good color contrast
- easily visible :focus styles, and preferably :hover styles too
- Color blind users need:
- information presented in a way that does not depend on color
- Deaf users need:
- Transcripts and captions for audio/visual content (not an issue with MODx manager)
- Users with motor disabilities need:
- full keyboard functionality (see above under blind users)
- easily visible :focus styles (some people cannot use a mouse at all, so they need to know where the keyboard focus is at all times)
- Users with cognitive disabilities (including common reading disorders, ADD, and others) need:
- simplicity in the visual design, organization, processes, etc.
- clear instructions
- good error prevention mechanisms
- good, intuitive error recovery mechanisms
Styles
- Keyboard visual focus indicator:
- The visual focus indicator on keyboard focus is either non-existent in some places or too hard to see. This can be added to manager/templates/default/css/index.css:
body *:focus {outline:2px solid #00948e !important;}
body #modx-header *:focus {outline:2px solid #fbf5be !important;}
This will solve the problem nearly everywhere, but additional styling and/or JavaScript will need to be added to make sure there is a visible outline around the custom checkboxes. I realize that this impacts the design somewhat, but having an easily-visible keyboard focus indicator is a requirement for accessibility, and has a huge positive impact on people who can't use a mouse. The impact on mouse users is minimal. They will see it on form fields, but that's probably a good thing. They won't see it with mouse hover (though you could certainly add the same styles for :hover, which would also be good for accessibility, though not as much of a requirement.)
[NOTE: I just noticed that the above styles only partially work in Safari and Chrome, presumably due to some conflicts with other webkit-specific styles in the style sheet somewhere, so additional work is needed to make the visual keyboard focus indicator functional in webkit browsers.]
- Color contrast:
- The color contrast ratio of the light-colored text in many places does not pass the WCAG standard of 4.5 to 1 for normal text of 3 to 1 for large text. The color contrast can be analyzed using automated tools such as FireEyes and Wave.
Login Screen
- Labels:
- The "username or email" field needs a <label> tag. Placeholder text is not considered a valid label.
- Required fields:
- Use aria-required="true" on all required <input> elements. Screen readers will say "required" when reading to users.
- Keyboard tab order:
- The tab order is mostly right, but the language selector in the bottom left corner is out of order. It should be moved in the source code so that it is the last thing on the page in the tab order, both when the login screen is in its default state and when the "forgot your login" feature is activated. I noticed that tabindex is used on some of the links and fields. It's best to not use tabindex with any positive numbers because it overrides the default browser tab behavior in ways that are often undesirable to keyboard users (tabindex="0" is acceptable to put something in the normal tab flow, and tabindex="-1" is acceptable to make something focusable via JavaScript, but tabindex="1" or more is not best practice). One problem with tabindex of positive numbers is that if you forget to add a tabindex value to a link or form field -- such as the "forgot your login" link and on the "username or email" field and the "send activation email" button -- you run the risk of putting things out proper order, and that is what has happened here. The recommendation is to simply put things in the correct tab order in the DOM to begin with and not alter the tab order with tabindex of positive numbers.
- Keyboard focus management:
- When users click on "forgot your login?" the keyboard focus needs to move to the "username or email" form field.
- Error/feedback messages:
- The feedback messages ("User not found...", "The username or password you entered is incorrect...") need to be read by screen readers when the page refreshes.
- Option 1: One way to accomplish this is to force the keyboard focus onto the error message when the page reloads. The error message would need to have tabindex="-1" to effectively be able to receive the focus via JavaScript. <div id="alert-message" tabindex="-1">User not found...</div>. The message should precede the first relevant form field. If the username/password is incorrect, the message should appear above the username field. If the error occurs on the "Username or Email" field (after selecting "forgot password?" then the error message should appear directly above the "username or email" field, so that users hit tab once to go into that field.
- Option 2: put the error message in the label of the relevant field, either by putting it in the <label> tag, or by using aria-label to refer to the message, e.g. refer to both the regular label and the message:
<div id="alert-message">User not found...</div>
<label for="username" id="username-label">Username</label>
<input aria-label="alert-message username-label" ...>
Note that you would want to link the error message for the "username or email" field
to that field directly, not to the "username" field. You would also want to make sure that keyboard focus goes to the "username or email" field and NOT to the top "username" field on page reload. In other words, make sure you're sending the keyboard focus to the correct field to match the error, and make sure the error message is associated with the appropriate field.
- Also: Set aria-invalid="true" on the <input> element after the form has been submitted on all incorrect fields. Screen readers will say "invalid" to let users know they need to fix the field.
- Color contrast:
- The contrast ratio between the blue link text and the grey background is too low for some users with low vision. The blue text is also too light even against the white background for accessibility contrast ratio standards. A possible value is #206e99
- The contrast is too low on the grey text of the "Language" label in the bottom left and the "remember me" label. A possible value for "remember me" would be #757575. A possible value for "Language" is #575757.
- The contrast is too low on the teal background color of the buttons compared to the white text on top. A possible value would be #007571.
Overall Manager Page Structure
There are no landmark regions or roles specified. Landmark regions help screen reader users navigate quickly to regions without having to read through the whole page. Here are the regions I would suggest for the main manager layout:
<header role="banner">
<div role="search"></div>
<nav role="navigation" aria-label="manager menu"> <!--(for the menu on the left)--> </nav>
<nav role="navigation" aria-label="user and system menu"> <!--(for the menu on the right)--> </nav>
</header>
<ul role="tablist" aria-label="Tree view tablist"> <!--(or come up with a better label for this)-->
<li role="tab">Resources<li><li role="tab">Elements</li><li role="Files">
</ul>
<div role="tabpanel">
<nav role="navigation" aria-label="Resource Tree"> <ul>...</ul></nav>
<nav role="navigation" aria-label="Element Tree"> <ul>...</ul></nav>
<nav role="navigation" aria-label="File Tree"> <ul>...</ul></nav>
</div>
<main role="main">
All of the main content goes here (page edits, snippet edits, dashboard content, etc.)
</main>
<footer role="contentinfo">
(Right now MODx manager does not have a footer, but this is how you would mark it up)
</footer>
Note: You could also achieve the same functional result using only <div> tags with role attributes instead of the HTML 5 tags plus the role attributes, but the latter solution is more forward-thinking.
Main Top Menu (the überbar)
- Tab order:
- The order of objects in the DOM differs from the visual order. The way the links are laid out visually, I would expect the order to be:
- MODx/home logo
- search
- content/media/extras/manage
- user menu
- gear/system menu
- help icon
- The actual order starts with user and goes to the right and then goes back to the MODx home and across the left menu, which is not intuitive.
- Keyboard accessibility:
- The main drop down menus are not accessible by keyboard. This is a big problem -- it's a deal-breaker, really -- that affects blind users and sighted keyboard users, neither of which can use a mouse effectively. The menu is 100% inaccessible to these groups. The ideal would be to use an aria-based menu that allows users to tab into the group (the whole nav/menu group) and then tab past it without tabbing into the menu items at all, and use the arrow keys to navigate within the menu system itself. See the keyboard patterns outlined here:
- Alt text for images and icons:
- The gravatar image has no alt text
- The gear icon and help icon need text. Options include:
- Use visually hidden text that only screen readers can access (use CSS clip or offscreen text) and hide the icon itself in case the screen reader tries to read it (it will almost surely read it incorrectly):
- <span class="icon-gear icon icon-large" aria-hidden="true"></span><span class="visually-hidden">System Menu</span>
- Or use role="image" and aria-label:
- <span class="icon-gear icon icon-large" role="image" aria-label="System Menu"></span>
- Form label:
- The search field needs a <label> tag, preferably one that is visible (the placeholder is not considered an accessible label because it disappears as soon as the keyboard focus enters the field), but you could also implement a hidden label in this particular case, because the magnifying glass conveys the idea of search (as long as the magnifying glass is turned into an actual submit button and as long as it has text that says "search").
- Submit button is missing:
- Ideally, the form would have an actual submit button so that blind users know they can submit the form. Blind users don't see the magnifying glass icon. In fact, the magnifying glass icon could be turned into a submit button, and you could maintain the same basic look as the exiting interface.
The Side Tree Panel
- Keyboard accessibility of tablist/tab panels:
- The tab panel is not keyboard accessible at all. The main tabs need to have tabindex="0" on the active tab and tabindex="-1" on the inactive tabs, and the JavaScript needs to toggle that value as users select different tabs. You also need to toggle aria-expanded="true" and aria-controls="the-id-of-the-tabpanel". See https://dequeuniversity.com/assets/js/aria/saveform/form2.html for an example.
- Icon alternative text:
- All of the icons (New document, New symlink, etc. and Trash) need alt text so screen readers know what to say. See "alt text for images and icons" in the uberbar above for possible techniques.
- Button role for icons:
- The icons (New document, New symlink, etc. and Trash) should be given role="button" or they should be enclosed in actual <button> tags because they are perform application-type features, and a button is the appropriate semantic role to convey to screen reader users.
- Keyboard-accessible tooltips for icon/buttons:
- The tooltip should popup when the icons/buttons receive keyboard focus, and not just with mouseover events.
- Keyboard accessibility of the button to collapse side bar:
- The handle to collapse the entire side bar to the left needs to be keyboard accessible, and it needs to be a <button> or have role="button" and it must have a label ("collapse sidebar" for example) to convey to users its purpose.
- Keyboard accessibility of tree view:
- Users need to be able to access all items and functionality (refresh, add new __ here, etc.) in the tree view with the keyboard. It would be best to implement an ARIA tree menu that allows navigation with the arrow key. You would tab into the tree object and then use the arrow keys to navigate within it, including expanding and collapsing nodes in the tree. Using the tab key would take you out of the tree, not navigate within it. Tree views are kind of complicated, but they can be made accessible. You would need to add ARIA attributes and toggle between various states such as aria-expanded="true". You would also need to make sure that the functionality of the expand/collapse icon/triangle is clear, and that it is separate from the functionality of the page title itself, which opens the page. See
- Keyboard accessibility of right-click menu in the tree view:
- The functionality of the right-click menu needs to be available to keyboard users. All of the features are available other places, so this requirement is sort of satisfied already, but it would be best to make the right-click menu directly available to keyboard users, rather than make them go through the less efficient routes to the same features. You could implement a keyboard shortcut such as alt+enter on links in the menu to activate the right-click menu. To be effective, though, you would need to tell users that this keyboard shortcut exists, so you could add a tooltip to each link saying "Use alt + enter for contextual menu". You would need to ensure that screen readers also read this text. Particularly important is the ability to add new items (resources, elements, files) as children of the item that currently has the focus, since this is a very common task.
- Keyboard focus management:
- When you select a page to edit it, the focus initially goes to the pagetitle field, which seems logical. I like that. The problem is that the menu tree loads and refreshes, and as it does so, it eventually steals the keyboard focus away from that field and puts the focus on the current page in the tree view. This breaks the keyboard flow, and if you can't use a mouse, you have to tab, tab, tab, tab, tab, a lot of times to get back to where you were. Ensure that the tree view doesn't steal the focus.
Modal Dialogs
- Keyboard focus management:
- Send focus to modal
- Ensure that the focus goes to the modal when it is activated. If it's a simple ok/cancel modal, then the focus should go on the ok button. MODx seems to do this well in the places I've looked.
- Restrict keyboard access to the modal while it is active:
- Ensure users can't tab to links underneath the modal or use a screen reader to access other elements beneath the modal. One technique to accomplish the latter is to set everything underneath the modal to aria-hidden="true". This will not hide it from visual users, but it will make the content unavailable to screen reader users, which is what you want in this case. Use JavaScript to control focus so that keyboard users can't tab forward or backward (shift+tab) out of the modal.
- Completely hide inactive modals (and other similar dynamic content):
- Ensure the modal is completely hidden from all users, including from screen reader users by using display:none on the element if it is in the DOM already. Be sure to revert it back to display:none at the appropriate time too, after the user or script is done with it. So far I haven't encountered any problems with modals in MODx being read by screen readers when they're inactive, but it's something to watch out for.
Add/Edit Resource
- Labels for form fields, buttons, and button-like (scripted) elements:
- The "Content" main field needs a real <label> tag associated with it.
- The show/hide widget above the right of the Content textarea and to the right of the tabs (Document, Settings, Template Variables...) needs a label. Give it a label like "hide Content field" (for the bottom one) or "Hide page properties" (for the top one), which should toggle to "show Content field" after it has been activated. This should probably be a button, so it could be coded like this:
<button aria-label="Hide Content field"> </button>
In some ways it would be preferable to have real text in the button:
<button><span class="visually-hidden">Hide Content field</span></button>
This text could be visually hidden using CSS clip or offscreen techniques (don't use display:none, because that hides it from screen readers too!).
- In the "Template Variables" pane, when a template variable has a property like @INHERIT, the text that currently shows up to the right of the field (e.g. "Value Inherited") needs to be inside the <label>. You can still style it to be over on the right side, but don't put it outside the label.
- Required fields:
- Use aria-required="true" on all required <input> elements. Screen readers will say "required" when reading to users.
- Keyboard accessibility:
- The tab interface is not keyboard-accessible. Users need to be able to navigate to the tab list with the tab key, then use the arrow keys to navigate the tabs themselves. See https://dequeuniversity.com/assets/js/aria/saveform/form2.html for an example of an accessible tablist and tabpanel.
- The "Uses template" selector:
- Ensure this widget is fully keyboard accessible so that people using only the keyboard can switch templates.
- The Content show/hide widget:
- Ensure keyboard users can tab this control
- The scripted read-only inputs under the "Settings" tab:
- The button (and it should be a button) to the right of the "Parent Resource" field needs to be keyboard-accessible, and/or users need to be able to type an integer directly into the field.
- The button to the right of the "Resource Type" field needs to be keyboard accessible, and keyboard users need to be able to select a resource type without a mouse.
- The button to the right of "Content Type" needs to be keyboard-accessible and users need to be able to select a content type without a mouse.
- The button to the right of "Content Disposition" needs to be keyboard-accessible and users need to be able to select a content disposition without a mouse.
- The "Template Variables" panel:
- The tablist on the side must be keyboard accessible. See https://dequeuniversity.com/assets/js/aria/saveform/form2.html for an example of an accessible tablist and tabpanel.
- The "Set to default" feature is not keyboard-accessible. Users should be able to tab to it and use it without a mouse. NOTE: Be sure to give each of these a distinct name, so they don't all say just "Set to default". You want it to say something like "Set Course ID to default", where "Course ID" is the name/caption for the template variable. Otherwise users won't know for sure which button refers to which field, because there may be several TVs and the placement of the "Set to default" button could be ambiguous (does it refer to the previous TV or the next TV?).
- The resource group panel:
- This seems to be unavailable by keyboard, but if you cheat and click with your mouse in the list of resource groups, keyboard access to the pane is possible, even though access to the checkboxes is not.
- checkboxes:
- The resource group checkboxes are available only with a mouse. They need to be keyboard-focusable and keyboard-functional (with enter or space bar).
- Keyboard tab order:
- For the most part the tab order is good (for the things that can be tabbed to), but the "Freeze URI" checkbox is out of order. It looks like it should be next after "Rich Text" but it is not.
- Error messages:
- When a field is invalid (required field is empty, for example) onblur, add aria-invalid="true" so that screen reader user will hear this when they navigate back to the field.
- When the user attempts to submit the page when there are invalid fields, move the keyboard focus to the invalid field (even if that field is in a different tab panel than the current focus), so that users can find the error and fix it. Make sure the error message is associated with the field by either being in the <label> itself or being referred to by aria-labelledby. Here is a suggestion:
<label>Title*<br>
<input aria-invalid="true" aria-required="true" ...>
<span class="error-message">This field is required</span>
</label>
When both the label and the error message are wrapped in the label tag along with the input itself, the title and error message with both be read when users focus on the input. This is a very convenient way of ensuring that error messages will be read by screen readers. (Note that aria-invalid="true" applies only after the field is truly invalid; not on page load.)