SlideShare uma empresa Scribd logo
1 de 77
Baixar para ler offline
Accessible Salesforce
Write Visualforce, Lightning and declarative
Salesforce pages that work for everyone!
Hello! We’ll be your presenters today.
Jesse Hausler
Principal Accessibility Specialist, Salesforce
@jessehausler
Shannon Hale
Director of UX, Skuid
(+ former Accessibility Workgroup member @ Salesforce)
@shannonsans
Defining web accessibility
Accessibility enables people with disabilities to perceive, understand,
navigate, interact with and contribute to the Web.
● Vision
● Mobility impairments
● Deafness and hard of hearing
● Cognitive
Assistive Technology
Keyboards and switches
Switches
Switches
Cheek Switch
Switches
Cheek Switch
Scanning with switches
● Cycle through rows
● Activate switch
● Cycle through columns
● Activate switch
● Profit
Making Things Work with
Assistive Technology
Forms
The most common and important
task in a CRM is entering data, so
accessible forms are critical.
Form labels
When labels aren’t programmatically
associated to inputs, assistive technology
users have no information about what to
type in each field.
Form labels
When labels aren’t programmatically
associated to inputs, assistive technology
users have no information about what to
type in each field.
<label/> tags associate inputs with their purpose
All <input/>, <textarea/> and <select/> HTML elements need labels
● Match the for attribute of <label/> tags to the id attribute of the
corresponding input control
● Remove orphaned labels (<label/> without an associated input control)
<label/> tags, great for mouse users too!
Click on a label to:
● Place focus inside of an input field or textarea
● Open a picklist
● Check a checkbox
● Select a radio button
Good Bad
Placeholder attributes are not substitutes for labels
Labels in Visualforce
Salesforce Classic Layout/Styling
● For fields on a Salesforce object, <apex:inputField/> automatically
associates labels and input controls as a child of <apex:
pageBlockSection/>
● For fields not on a Salesforce object, use <apex:outputLabel/> with
<apex:input/>, <apex:inputText/>, etc. inside <apex:
pageBlockSectionItem/> and match the for attribute of <apex:
outputLabel/> with the id attribute of <apex:input*/>
Custom Layout/Styling
● For Bootstrap or other custom layouts, use <apex:outputLabel/> with
<apex:inputField/>, <apex:input/> etc. as above
Visualforce label example: Salesforce Classic styling
Visualforce label example: Salesforce Classic styling
<apex:page docType="html-5.0" standardController="Contact" extensions="ContactAccessibility">
<apex:form >
<apex:pageBlock title="Contact" mode="edit">
<apex:pageBlockButtons >
<apex:commandButton action="{!save}" value="Save"/>
</apex:pageBlockButtons>
<apex:pageBlockSection title="Contact Details" columns="1">
<apex:inputField value="{!contact.lastName}"/>
<apex:pageBlockSectionItem>
<apex:outputLabel for="NumGuests" value="Number of Guests" />
<apex:input type="number" id="NumGuests" value="{!numGuests}"/>
</apex:pageBlockSectionItem>
<apex:pageBlockSectionItem>
<apex:outputPanel layout="none" />
<apex:outputPanel layout="none">
<apex:inputCheckbox id="OkToContact" value="{!contactOK}" />
<apex:outputLabel for="OkToContact" value="Contact with special offers" />
</apex:outputPanel>
</apex:pageBlockSectionItem>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>
Visualforce label example: Bootstrap form
Visualforce label example: Bootstrap form
<div class=”container”>
<apex:form>
<div class="form-group">
<apex:outputLabel for="LastName" value="{!$ObjectType.Contact.fields.LastName.Label}"
styleClass=”control-label” />
<apex:inputField id="LastName" value="{!contact.lastName}" required="true" styleClass="form-
control" />
</div>
<div class="form-group">
<apex:outputLabel for="NumGuests" value="Number of Guests" styleClass=”control-label” />
<apex:input type="number" id="NumGuests" value="{!numGuests}" styleClass="form-control" />
</div>
<div class="form-group">
<div class="checkbox">
<apex:inputCheckbox id="OkToContact" value="{!contactOK}" />
<apex:outputLabel for="OkToContact" value="Contact with special offers" />
</div>
</div>
<div class="form-group">
<apex:commandButton action="{!save}" value="Save" styleClass="btn btn-default" />
</div>
</apex:form>
</div>
But what happened to the ‘required’ indicator?
<div class="form-group">
<apex:outputLabel for="LastName" value="{!$ObjectType.Contact.fields.LastName.Label} *"
styleClass=”control-label” />
<apex:inputField id="LastName" value="{!contact.lastName}" required="true" styleClass="form-
control" />
</div>
We set required=”true” on <apex:
input/> but Bootstrap doesn’t
know what to do with this.
Provide a text indicator such as
an asterisk on the label, so it’s
accessible to assistive tech.
A note about required fields
The Salesforce Classic red bar or other styling on its own is not enough to
indicate a required field.
If you’re rolling your own page markup, make sure to provide some text
indication of field requiredness inside the <label> tags.
What you don’t see here is that Visualforce- and Salesforce
Classic-generated required field labels have an asterisk in the
label that’s visually hidden, but still available to assistive
technology.
<label for="j_id0:j_id1:j_id2:j_id5:j_id6">
<span class="assistiveText">*</span>
Last Name
</label>
Lightning label example
Lightning label example
<form class="slds-form--stacked">
<div class="slds-form-element slds-is-required">
<div class="slds-form-element__control">
<ui:inputText aura:id="lastName" label="Last Name" class="slds-input" labelClass="slds-
form-element__label" value="{!v.newContact.LastName}" required="true" />
</div>
</div>
<div class="slds-form-element">
<div class="slds-form-element__control">
<ui:inputNumber aura:id="numGuests" label="Number of Guests" class="slds-input"
labelClass="slds-form-element__label" value="{!v.newContact.NumberOfGuests}" />
</div>
</div>
<div class="slds-form-element">
<ui:inputCheckbox aura:id="reimbursed" label="Contact with special offers" class="slds-
checkbox" labelClass="slds-form-element__label" value="{!v.newContact.OKToContact}" />
</div>
<div class="slds-form-element">
<ui:button label="Save" class="slds-button slds-button--neutral" press="{!c.createContact}"
/>
</div>
</form>
Labels in other frameworks
In other frameworks (React, Angular, SLDS outside of Lightning, etc.), always use
<label/> with <input/>, <textarea/> and <select/> HTML elements.
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
<label for="name">Last Name *</label>
<input type="text" id="name" ng-model="contact.lastname" required /><br />
<label for="numGuests">Number of Guests</label>
<input type="number" id="numGuests" ng-model="contact.numberOfGuests" /><br />
<input type="checkbox" id="okToContact" ng-model="contact.okToContact"
value="okToContact" />
<label for="okToContact">Contact with special offers</label><br />
<input type="submit" ng-click="update(contact)" value="Save" />
</form>
</div>
Hiding labels (or other content) visually on a page
Sometimes you want to visually hide a label, heading or other content while still
making the label available to assistive technologies.
Don’t use display: none or visibility: hidden in the CSS. Both of
these will hide the content from assistive technologies -- use them only when you
want to hide the content from EVERYONE.
To do it right, add a class to the element you want hidden:
● Lightning Design System: slds-assistive-text
● Bootstrap: sr-only
● Visualforce and other frameworks: create a custom class (see next slide)
Hiding content visually on a page with custom CSS
If you’re using another framework or rolling your own styles in Visualforce,
create a custom class and add it to the content you want to hide:
.assistive-text {
position: absolute;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
z-index: -1000;
}
Lightning accessible hidden label example
<form class="slds-form">
<div class="slds-form-element">
<div class="slds-form-element__control">
<div class="slds-input-has-icon slds-input-has-icon--left">
<c:svgIcon svgPath="/resource/slds0121/assets/icons/utility-sprite/svg/symbols.svg#search"
category="utility" size="x-small" name="search"
class="slds-input__icon slds-icon-text-default" />
<ui:inputText aura:id="q" label="Search" class="slds-input" labelClass="slds-assistive-text" />
</div>
</div>
</div>
</form>
aria-describedby associates
help text and error messages with input controls
While <label> tags are used to associate form fields with their label, aria-
describedby is used to associate information beyond a label to an input
● When a user places focus on an input, both the label and the help or error
text will be available to screen readers
Using aria-describedby in Visualforce
● Visualforce <apex:input*/> tags don’t have native aria-* attribute
● Leverage HTML pass through attributes and add html-aria-describedby
● Use the $Component global merge field to get the generated id of the
related element if it’s an <apex:outputPanel/> or other Visualforce
component
Unfortunately, neither Salesforce Classic or Visualforce set aria-describedby automatically for
errors, so this is a manual exercise. If the user has Accessibility Mode enabled, then labels of fields with
errors prepend “Error -” to the label. Lightning handles this better, as you’ll see.
Visualforce aria-describedby example
Visible inline help text is great for settings like this one in the
Nonprofit Starter Pack, which aren’t edited very frequently and
can be hard to understand from just the label.
Visualforce aria-describedby example
STG_PanelContacts: right now, the help text isn’t semantically associated with the field it describes
<div class="form-group">
<apex:outputLabel value="{!$ObjectType.npe01__Contacts_And_Orgs_Settings__c.Fields.
npe01__Account_Processor__c.Label}" for="slAP" styleClass="col-sm-4 control-label" />
<div class="col-sm-8 form-control-column">
<apex:outputField value="{!stgService.stgCon.npe01__Account_Processor__c}" rendered="{!
isReadOnlyMode}" />
<apex:selectList value="{!stgService.stgCon.npe01__Account_Processor__c}" multiselect="
false" size="1" rendered="{!isEditMode}" id="slAP" styleClass="form-control">
<apex:selectOptions value="{!listSOAccountModels}"/>
</apex:selectList>
</div>
<div class="col-sm-offset-4 col-sm-8 help-block">
<apex:outputText value="{!$Label.stgHelpAccountModel}" />
</div>
</div>
Visualforce aria-describedby example
STG_PanelContacts: now with accessible help text!
<div class="form-group">
<apex:outputLabel value="{!$ObjectType.npe01__Contacts_And_Orgs_Settings__c.Fields.
npe01__Account_Processor__c.Label}" for="slAP" styleClass="col-sm-4 control-label" />
<div class="col-sm-8 form-control-column">
<apex:outputField value="{!stgService.stgCon.npe01__Account_Processor__c}" rendered="{!
isReadOnlyMode}" />
<apex:selectList value="{!stgService.stgCon.npe01__Account_Processor__c}" multiselect="
false" size="1" rendered="{!isEditMode}" id="slAP" html-aria-describedby="{!$Component.
slAPHelp}" styleClass="form-control">
<apex:selectOptions value="{!listSOAccountModels}"/>
</apex:selectList>
</div>
<apex:outputPanel id="slAPHelp" layout="block" styleClass="col-sm-offset-4 col-sm-8 help-
block">
<apex:outputText value="{!$Label.stgHelpAccountModel}" />
</apex:outputPanel>
</div>
Errors and aria-describedby in Lightning
Set errors on a field using the component’s .errors attribute to dynamically
create and insert the error message and aria-describedby tag into the field
DOM:
createExpense : function(component, event, helper) {
var amtField = component.find("amount");
var amt = amtField.get("v.value");
if (isNaN(amt) || amt==''){
amtField.set("v.errors", [{message:"Enter an expense amount."}]);
}
else {
amtField.set("v.errors", null);
var newExpense = component.get("v.newExpense");
helper.createExpense(component, newExpense);
}
}
More on error handling: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_throw_error.htm
Errors and aria-describedby in Lightning
This is what the generated markup looks like from the previous example:
<div class="slds-form-element slds-is-required">
<div class="slds-form-element__control">
<div class="uiInput uiInputNumber uiInput--default uiInput--input has-error">
<label class="slds-form-element__label uiLabel-left form-element__label uiLabel" for="
34:2;a" ><span class="">Amount</span><span class="required">*</span></label>
<input class="slds-input input" max="99999999999999" step="1" type="text" min="
-99999999999999" aria-describedby="112:c" placeholder="" required="" id="34:2;a">
</div>
<ul class="has-error uiInputDefaultError uiInput uiInputNumber uiInput--default uiInput--
input" id="112:c">
<li class="form-element__help">Enter an expense amount.</li>
</ul>
</div>
</div>
Help and aria-describedby in Lightning
<div class="slds-form-element slds-is-required">
<div class="slds-form-element__control">
<ui:inputText aura:id="expname" label="Expense Name" class="slds-input"
labelClass="slds-form-element__label" value="{!v.newExpense.Name}"
required="true" />
</div>
<div class="custom-help-block">
<p>Please use the format: Date - last name - purpose</p>
</div>
</div>
Unfortunately, the ariaDescribedBy attribute hasn’t been surfaced in the Lightning Component
framework on the platform as of Winter ‘16 (more info)
Using aria-describedby in other frameworks
In other frameworks, just use the aria-describedby attribute on the
<input/> element to associate it with the element containing the message. You
can use Element.setAttribute() to set the attribute dynamically via
JavaScript during error handling.
<label for=”myFieldId”>Field Label</label>
<input id=”myFieldId” type=”text” value=”fieldValue” aria-
describedby=”myMessageId” />
<span id=”myMessageId”>More information or an error message
about this field</span>
Group related radio buttons within a <fieldset/>
Consider that a set of radio buttons are an answer to a question.
Group related radio buttons within a <fieldset/>
<label> associates answer choices to their radio buttons.
<input type=”radio” id=”color-blue” name=”color” value=”blue” />
<label for=”color-blue”>Blue</label>
Group related radio buttons within a <fieldset/>
The <legend/> of the <fieldset/> associates the question to the answer
choices.
<fieldset>
<legend>What is your favorite color?</legend>
<!-- blue/red/green/orange radio buttons go here -->
</fieldset>
Other use cases for <fieldset/>
● Group related fields -- consider
Shipping Address vs Billing Address
in compound fields
● Group checkboxes to allow multiple
possible answers (“check all that
apply”)
Using <fieldset/> in Visualforce
● Specify the legendText attribute on <apex:selectCheckboxes/> and
<apex:selectRadio/> to properly group the input controls in a fieldset
with a legend
● If needed, hide the legend from sighted users by setting
legendInvisible=”true” -- this adds class=”assistiveText” to the
<legend/> tag, which keeps to the legend accessible to assistive
technologies but hides it visually
Using <fieldset/> in Visualforce: Classic Styling
<apex:page controller="CheckboxTestControllerVF">
<apex:form>
<apex:selectCheckboxes layout="pageDirection"
legendText="Contacts to invite:"
value="{!contactIds}">
<apex:selectOptions value="{!items}" />
</apex:selectCheckboxes>
</apex:form>
</apex:page>
public List<SelectOption> getItems() {
List<SelectOption> options = new List<SelectOption>();
for (Contact c : [SELECT Id, Name FROM Contact]) {
options.add(new SelectOption(c.Id, c.Name));
}
return options;
}
Using <fieldset/> in Lightning with SLDS
<aura:component implements="force:appHostable" controller="CheckboxTestController">
<aura:attribute name="contacts" type="Contact[]" />
<aura:attribute name="checkedContacts" type="String[]" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<div class="slds-form--stacked">
<fieldset class="slds-form-element">
<span class="slds-form-element__label slds-form-element__label-top">
<legend>Contacts to invite:</legend>
</span>
<div class="slds-form-element__control">
<aura:iteration var="con" items="{!v.contacts}">
<label for="{!'c' + con.Id}" class="slds-checkbox">
<input type="checkbox" id="{!'c' + con.Id}" value="{!con.Id}"
onchange="{!c.updateCheckboxes}" />
<span class="slds-checkbox--faux"></span>
<span class="slds-form-element__label">{!con.Name}</span>
</label>
</aura:iteration>
</div>
</fieldset>
</div>
</aura:component>
Note that we’re not using
<ui:inputCheckbox/>
here: as of Winter ‘16
there’s no way to (1)
position the label on the
right and (2) add the faux
checkbox <span/> for
SLDS styling.
Using <fieldset/> in other frameworks
<fieldset>
<legend>My Legend</legend>
<!-- Form fields and other grouped content go here -->
</fieldset>
If an element behaves like a button, it’s a <button/>
Generally speaking, if an element submits a form, executes some code without
leaving the page, or otherwise has button-like behavior, it should be a
<button/>
Image-only buttons have other
important considerations -- we’ll talk
about this in Images.
Why semantic <button/> use is important
● Buttons have different interaction behaviors than links and are announced
differently by assistive technologies
○ Pressing Space or Enter triggers onclick on button, but only Enter triggers onclick on
links
○ <a/> elements with an empty href attributes won’t receive keyboard focus
● <div/> and <span/> elements don’t receive keyboard focus, so aren’t
accessible from the keyboard*
● Some assistive technology uses shortcut keys to get a list of links or buttons
on the page -- you want the right elements to be returned
Images
Describe non-text content to
assistive technologies
Informational vs decorative images
<img/> requires the presence of the alt attribute
The alt attribute helps assistive technologies describe the purpose of an image
to users who can’t see it
● Images that are purely decorative should have an empty alt attribute:
<img src=”decorative.jpg” alt=”” />
● Informational images should have a useful alt attribute value:
<img src=”exclamation.png” alt=”Warning” />
● “null”, “empty” and “undefined” are not appropriate alt values
● If the alt attribute is missing, the file name will be read instead!
alt attributes in Visualforce
Use the alt attribute on <apex:image/> for accessible images in Visualforce:
<h1 class="h4">Recent Items</h1>
<ol class="list-unstyled recentItems">
<apex:repeat value="{!recentItems}" var="item">
<li>
<apex:outputLink value="/{!item.Id}">
<apex:image value="/s.gif"
styleClass="{!IF(item.type='Account', 'account24', 'contact24')}"
alt="{!IF(item.type='Account', 'Account', 'Contact')}" />
{!item.Name}
</apex:outputLink>
</li>
</apex:repeat>
</ol>
alt attributes in Lightning
<ui:image/> has an imageType attribute with two possible values:
● informational: the alt attribute is also required
● decorative: the alt attribute is not required
However!
<ui:image/> is not available in Lightning components as of Winter ‘16.
Instead, use the HTML <img/> tag and set the alt attribute as for any other
framework (remember to set alt=”” for descriptive images)
alt attributes in Lightning: SLDS Example
If you want to leverage the SVGs in SLDS inside Lightning
Components, you may need the Lightning SVG Icon
Component Helper
alt attributes in Lightning: SLDS example
recentItemsList.cmp
<aura:component implements="force:appHostable" controller="RecentItemsControllerLX">
<ltng:require styles="/resource/slds0121/assets/styles/salesforce-lightning-design-system.min.
css"/>
<aura:attribute name="items" type="RecentlyViewed[]" />
<aura:handler name="init" value="{!this}" action="{!c.doInit}" />
<ol>
<aura:iteration var="item" items="{!v.items}">
<li>
<c:sObjectHyperlink sObjectId="{!item.Id}"
hyperlinkLabel="{!item.Name}"
sObjectType="{!item.Type}" />
</li>
</aura:iteration>
</ol>
</aura:component>
alt attributes in Lightning: SLDS example
sObjectHyperlink.cmp
<aura:component >
<aura:attribute name="sObjectId" type="Id" />
<aura:attribute name="hyperlinkLabel" type="String" />
<aura:attribute name="sObjectType" type="String" />
<a href="javascript:void(0);" onclick="{!c.showObjectInfo}">
<aura:renderIf isTrue="{!v.sObjectType == 'Account'}">
<c:svgIcon svgPath="/resource/slds0121/assets/icons/standard-sprite/svg/symbols.svg#account"
category="standard" size="small" name="account"
containerClass="slds-icon__container slds-icon-standard-account"
assistiveText="Account"/>
</aura:renderIf>
<aura:renderIf isTrue="{!v.sObjectType == 'Contact'}">
<c:svgIcon svgPath="/resource/slds0121/assets/icons/standard-sprite/svg/symbols.svg#contact"
category="standard" size="small" name="contact"
containerClass="slds-icon__container slds-icon-standard-contact"
assistiveText="Contact"/>
</aura:renderIf>
{!v.hyperlinkLabel}
</a>
</aura:component>
Image links and buttons need text content
With icon fonts, this is too common:
<a href="http://www.facebook.com/">
<span class="icon-facebook"></span>
</a>
<a href="http://twitter.com/">
<span class="icon-twitter"></span>
</a>
<a href="http://youtube.com/">
<span class="icon-youtube"></span>
</a>
<a href="http://plus.google.com/">
<span class="icon-googleplus"></span>
</a>
Image links and buttons need text content
How a screen reader announces this:
“Link”
“Link”
“Link”
“Link”
Image links and buttons need text content
How to fix it:
<a href="http://www.facebook.com/">
<span class="icon-facebook"><span class=”assistive-text”>Facebook</span></span>
</a>
<a href="http://twitter.com/">
<span class="icon-twitter"><span class=”assistive-text”>Twitter</span></span>
</a>
<a href="http://youtube.com/">
<span class="icon-youtube"><span class=”assistive-text”>YouTube</span></span>
</a>
<a href="http://plus.google.com/">
<span class="icon-googleplus"><span class=”assistive-text”>Google+</span></span>
</a>
Image links and buttons need text content
Bootstrap image example:
<button class="btn btn-link">
<span class="glyphicon glyphicon-remove delete-icon">
<span class="sr-only">Delete</span>
</span>
</button>
See also: http://salesforce.stackexchange.com/questions/99411/make-an-apeximage-appear-conditionally-with-apex-
code/99418#99418
Interactivity
Make all interactive content
accessible from the keyboard.
Ensure interactive elements are accessible using
keyboard and assistive technology
These components all follow the W3C spec for accessibility
● Menu <ui:menu/>
● Modal dialog <ui:modal/>
● Non-modal panel <ui:panel/>
● Autocomplete typeahead <ui:autocomplete/>
● Tabset <ui:tabset/>
● Tooltip <ui:tooltip/>
Only <ui:menu> is supported in Lightning as of Winter ‘16 -- for a list of supported components, use
https://yourdomain.lightning.force.com/auradocs/reference.app rather than the open source http:
//documentation.auraframework.org/auradocs)
Use hyperlinks and buttons for click targets
Only <a/>, <button/>, and <input/> types should be:
○ Click targets
○ Hover targets
They natively receive and show focus, perform actions, and communicate with
assistive technologies.
Use hyperlinks and buttons for click targets
Don't make <div/>, <span/>
and other non-focusable
elements “clickable”.
Use hyperlinks and buttons for click targets
Navigation options:
● add onclick to a card for a
larger tap/click target, but
include a hyperlink to the
same destination
● wrap the card in an <a/>
Interaction:
● add an explicit <button/>
instead of onclick on a
non-focusable element
Using hover
● Behaviors which occur on mouse hover
must also occur with keyboard focus
● Triggers need to be focusable
In this example, the blue circle with the “i” character should
be an anchor. The tooltip shows when the anchor is in
focus.
Using hover
Don’t use hover to reveal actionable
content, such as buttons or links. Just
show them.
In Lightning Experience, pencils aren’t hidden behind
hover states. Instead, they get darker on hover.
Color Usage
Color is a key part of visual design
-- but not everyone using your page
will see it the same way you do
Text color contrast ratio
must meet the minimum requirement
According to the WCAG,
● Contrast ratio between text and background should be at least 4.5 to 1.
● If font is at least 24 px or 19 px bold, the minimum drops to 3 to 1.
For large text, the lightest gray you can use on white is
#959595
For small text, the lightest gray you can use on white is #767676
Don’t use color as the only means of differentiation
Don’t use color as the only means of differentiation
Other
Considerations
These are other items that test
automation can be used to find.
Other
● Have a descriptive page <title/>
○ This is good not only for assistive tech, but for those of us who like to have 20 tabs open in
our browsers!
● Properly nest your page headings (<h1/><h2/><h3/>)
○ Use heading tags for headings! <div class=”my-heading-style”>...</div> does
not communicate that the content is a heading to assistive technologies.
● Consider whether lists are ordered or unordered
● Data table cells must be associated with data table headers
● Have a descriptive title attribute for frame and iframe elements
● Avoid repetitive hyperlink text (Edit, View All, etc)
○ Provide disambiguation for assistive technologies by hiding the content visually
Testing and
Debugging
How can you tell if you’re doing the
right thing?
Testing and Debugging
● Unplug your mouse
● Test with users with disabilities
● Chrome Accessibility Developer Tools
● Mac OS X
○ VoiceOver - free screen reader software (System Preferences > Accessibility > VoiceOver)
○ Full Keyboard Access: All Controls (System Preferences > Keyboard > Shortcuts)
○ Safari accessibility: tab to links (Preferences > Advanced >Press Tab to highlight each item on
a webpage)
● Windows
○ NVDA - free screen reader software
○ Most screen reader users use JAWS on Windows
Questions?
Resources
How to Meet WCAG 2.0
7 Things Every Designer Needs to Know about Accessibility
Colorsafe.co
Microsoft Inclusive Design Toolkit

Mais conteúdo relacionado

Semelhante a Accessible Salesforce

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...OPITZ CONSULTING Deutschland
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysqlKnoldus Inc.
 
AngularJS and SharePoint
AngularJS and SharePointAngularJS and SharePoint
AngularJS and SharePointdanielsmon
 
CSS3 Takes on the World
CSS3 Takes on the WorldCSS3 Takes on the World
CSS3 Takes on the WorldJonathan Snook
 
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)Maximilian Lenkeit
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular UJoonas Lehtinen
 
CSS3 and jQuery
CSS3 and jQueryCSS3 and jQuery
CSS3 and jQuerypsophy
 
Building iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" DominoBuilding iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" DominoRob Bontekoe
 
FamilySearch Reference Client
FamilySearch Reference ClientFamilySearch Reference Client
FamilySearch Reference ClientDallan Quass
 
Rails, Postgres, Angular, and Bootstrap: The Power Stack
Rails, Postgres, Angular, and Bootstrap: The Power StackRails, Postgres, Angular, and Bootstrap: The Power Stack
Rails, Postgres, Angular, and Bootstrap: The Power StackDavid Copeland
 
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8netmind
 
QCon 2015 - Thinking in components: A new paradigm for Web UI
QCon 2015 - Thinking in components: A new paradigm for Web UIQCon 2015 - Thinking in components: A new paradigm for Web UI
QCon 2015 - Thinking in components: A new paradigm for Web UIOliver Häger
 
AngularJS Mobile Warsaw 20-10-2014
AngularJS Mobile Warsaw 20-10-2014AngularJS Mobile Warsaw 20-10-2014
AngularJS Mobile Warsaw 20-10-2014Dariusz Kalbarczyk
 
Pengenalan AngularJS
Pengenalan AngularJSPengenalan AngularJS
Pengenalan AngularJSEdi Santoso
 

Semelhante a Accessible Salesforce (20)

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...
Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ ...
 
Form demoinplaywithmysql
Form demoinplaywithmysqlForm demoinplaywithmysql
Form demoinplaywithmysql
 
AngularJS and SharePoint
AngularJS and SharePointAngularJS and SharePoint
AngularJS and SharePoint
 
CSS3 Takes on the World
CSS3 Takes on the WorldCSS3 Takes on the World
CSS3 Takes on the World
 
CSS3 vs jQuery
CSS3 vs jQueryCSS3 vs jQuery
CSS3 vs jQuery
 
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)
Building Custom Controls to Visualize Data (UI5Con 2016 Frankfurt)
 
Schoology tutorial[1]
Schoology tutorial[1]Schoology tutorial[1]
Schoology tutorial[1]
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular U
 
CSS3 and jQuery
CSS3 and jQueryCSS3 and jQuery
CSS3 and jQuery
 
Building iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" DominoBuilding iPhone Web Apps using "classic" Domino
Building iPhone Web Apps using "classic" Domino
 
FamilySearch Reference Client
FamilySearch Reference ClientFamilySearch Reference Client
FamilySearch Reference Client
 
Rails, Postgres, Angular, and Bootstrap: The Power Stack
Rails, Postgres, Angular, and Bootstrap: The Power StackRails, Postgres, Angular, and Bootstrap: The Power Stack
Rails, Postgres, Angular, and Bootstrap: The Power Stack
 
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
netmind - Primer Contacto con el Desarrollo de Aplicaciones para Windows 8
 
QCon 2015 - Thinking in components: A new paradigm for Web UI
QCon 2015 - Thinking in components: A new paradigm for Web UIQCon 2015 - Thinking in components: A new paradigm for Web UI
QCon 2015 - Thinking in components: A new paradigm for Web UI
 
AngularJS Mobile Warsaw 20-10-2014
AngularJS Mobile Warsaw 20-10-2014AngularJS Mobile Warsaw 20-10-2014
AngularJS Mobile Warsaw 20-10-2014
 
Introduccion a HTML5
Introduccion a HTML5Introduccion a HTML5
Introduccion a HTML5
 
html5
html5html5
html5
 
Pengenalan AngularJS
Pengenalan AngularJSPengenalan AngularJS
Pengenalan AngularJS
 
Fcr 2
Fcr 2Fcr 2
Fcr 2
 

Último

Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...confluent
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxRTS corp
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingShane Coughlan
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profileakrivarotava
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecturerahul_net
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonApplitools
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencessuser9e7c64
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogueitservices996
 

Último (20)

Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
Catch the Wave: SAP Event-Driven and Data Streaming for the Intelligence Ente...
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full RecordingOpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
SoftTeco - Software Development Company Profile
SoftTeco - Software Development Company ProfileSoftTeco - Software Development Company Profile
SoftTeco - Software Development Company Profile
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Understanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM ArchitectureUnderstanding Flamingo - DeepMind's VLM Architecture
Understanding Flamingo - DeepMind's VLM Architecture
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + KobitonLeveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
Leveraging AI for Mobile App Testing on Real Devices | Applitools + Kobiton
 
Patterns for automating API delivery. API conference
Patterns for automating API delivery. API conferencePatterns for automating API delivery. API conference
Patterns for automating API delivery. API conference
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
Ronisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited CatalogueRonisha Informatics Private Limited Catalogue
Ronisha Informatics Private Limited Catalogue
 

Accessible Salesforce

  • 1. Accessible Salesforce Write Visualforce, Lightning and declarative Salesforce pages that work for everyone!
  • 2. Hello! We’ll be your presenters today. Jesse Hausler Principal Accessibility Specialist, Salesforce @jessehausler Shannon Hale Director of UX, Skuid (+ former Accessibility Workgroup member @ Salesforce) @shannonsans
  • 3. Defining web accessibility Accessibility enables people with disabilities to perceive, understand, navigate, interact with and contribute to the Web. ● Vision ● Mobility impairments ● Deafness and hard of hearing ● Cognitive
  • 9. Scanning with switches ● Cycle through rows ● Activate switch ● Cycle through columns ● Activate switch ● Profit
  • 10. Making Things Work with Assistive Technology
  • 11. Forms The most common and important task in a CRM is entering data, so accessible forms are critical.
  • 12. Form labels When labels aren’t programmatically associated to inputs, assistive technology users have no information about what to type in each field.
  • 13. Form labels When labels aren’t programmatically associated to inputs, assistive technology users have no information about what to type in each field.
  • 14. <label/> tags associate inputs with their purpose All <input/>, <textarea/> and <select/> HTML elements need labels ● Match the for attribute of <label/> tags to the id attribute of the corresponding input control ● Remove orphaned labels (<label/> without an associated input control)
  • 15. <label/> tags, great for mouse users too! Click on a label to: ● Place focus inside of an input field or textarea ● Open a picklist ● Check a checkbox ● Select a radio button
  • 16. Good Bad Placeholder attributes are not substitutes for labels
  • 17. Labels in Visualforce Salesforce Classic Layout/Styling ● For fields on a Salesforce object, <apex:inputField/> automatically associates labels and input controls as a child of <apex: pageBlockSection/> ● For fields not on a Salesforce object, use <apex:outputLabel/> with <apex:input/>, <apex:inputText/>, etc. inside <apex: pageBlockSectionItem/> and match the for attribute of <apex: outputLabel/> with the id attribute of <apex:input*/> Custom Layout/Styling ● For Bootstrap or other custom layouts, use <apex:outputLabel/> with <apex:inputField/>, <apex:input/> etc. as above
  • 18. Visualforce label example: Salesforce Classic styling
  • 19. Visualforce label example: Salesforce Classic styling <apex:page docType="html-5.0" standardController="Contact" extensions="ContactAccessibility"> <apex:form > <apex:pageBlock title="Contact" mode="edit"> <apex:pageBlockButtons > <apex:commandButton action="{!save}" value="Save"/> </apex:pageBlockButtons> <apex:pageBlockSection title="Contact Details" columns="1"> <apex:inputField value="{!contact.lastName}"/> <apex:pageBlockSectionItem> <apex:outputLabel for="NumGuests" value="Number of Guests" /> <apex:input type="number" id="NumGuests" value="{!numGuests}"/> </apex:pageBlockSectionItem> <apex:pageBlockSectionItem> <apex:outputPanel layout="none" /> <apex:outputPanel layout="none"> <apex:inputCheckbox id="OkToContact" value="{!contactOK}" /> <apex:outputLabel for="OkToContact" value="Contact with special offers" /> </apex:outputPanel> </apex:pageBlockSectionItem> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>
  • 20. Visualforce label example: Bootstrap form
  • 21. Visualforce label example: Bootstrap form <div class=”container”> <apex:form> <div class="form-group"> <apex:outputLabel for="LastName" value="{!$ObjectType.Contact.fields.LastName.Label}" styleClass=”control-label” /> <apex:inputField id="LastName" value="{!contact.lastName}" required="true" styleClass="form- control" /> </div> <div class="form-group"> <apex:outputLabel for="NumGuests" value="Number of Guests" styleClass=”control-label” /> <apex:input type="number" id="NumGuests" value="{!numGuests}" styleClass="form-control" /> </div> <div class="form-group"> <div class="checkbox"> <apex:inputCheckbox id="OkToContact" value="{!contactOK}" /> <apex:outputLabel for="OkToContact" value="Contact with special offers" /> </div> </div> <div class="form-group"> <apex:commandButton action="{!save}" value="Save" styleClass="btn btn-default" /> </div> </apex:form> </div>
  • 22. But what happened to the ‘required’ indicator? <div class="form-group"> <apex:outputLabel for="LastName" value="{!$ObjectType.Contact.fields.LastName.Label} *" styleClass=”control-label” /> <apex:inputField id="LastName" value="{!contact.lastName}" required="true" styleClass="form- control" /> </div> We set required=”true” on <apex: input/> but Bootstrap doesn’t know what to do with this. Provide a text indicator such as an asterisk on the label, so it’s accessible to assistive tech.
  • 23. A note about required fields The Salesforce Classic red bar or other styling on its own is not enough to indicate a required field. If you’re rolling your own page markup, make sure to provide some text indication of field requiredness inside the <label> tags. What you don’t see here is that Visualforce- and Salesforce Classic-generated required field labels have an asterisk in the label that’s visually hidden, but still available to assistive technology. <label for="j_id0:j_id1:j_id2:j_id5:j_id6"> <span class="assistiveText">*</span> Last Name </label>
  • 25. Lightning label example <form class="slds-form--stacked"> <div class="slds-form-element slds-is-required"> <div class="slds-form-element__control"> <ui:inputText aura:id="lastName" label="Last Name" class="slds-input" labelClass="slds- form-element__label" value="{!v.newContact.LastName}" required="true" /> </div> </div> <div class="slds-form-element"> <div class="slds-form-element__control"> <ui:inputNumber aura:id="numGuests" label="Number of Guests" class="slds-input" labelClass="slds-form-element__label" value="{!v.newContact.NumberOfGuests}" /> </div> </div> <div class="slds-form-element"> <ui:inputCheckbox aura:id="reimbursed" label="Contact with special offers" class="slds- checkbox" labelClass="slds-form-element__label" value="{!v.newContact.OKToContact}" /> </div> <div class="slds-form-element"> <ui:button label="Save" class="slds-button slds-button--neutral" press="{!c.createContact}" /> </div> </form>
  • 26. Labels in other frameworks In other frameworks (React, Angular, SLDS outside of Lightning, etc.), always use <label/> with <input/>, <textarea/> and <select/> HTML elements. <div ng-controller="ExampleController"> <form novalidate class="simple-form"> <label for="name">Last Name *</label> <input type="text" id="name" ng-model="contact.lastname" required /><br /> <label for="numGuests">Number of Guests</label> <input type="number" id="numGuests" ng-model="contact.numberOfGuests" /><br /> <input type="checkbox" id="okToContact" ng-model="contact.okToContact" value="okToContact" /> <label for="okToContact">Contact with special offers</label><br /> <input type="submit" ng-click="update(contact)" value="Save" /> </form> </div>
  • 27. Hiding labels (or other content) visually on a page Sometimes you want to visually hide a label, heading or other content while still making the label available to assistive technologies. Don’t use display: none or visibility: hidden in the CSS. Both of these will hide the content from assistive technologies -- use them only when you want to hide the content from EVERYONE. To do it right, add a class to the element you want hidden: ● Lightning Design System: slds-assistive-text ● Bootstrap: sr-only ● Visualforce and other frameworks: create a custom class (see next slide)
  • 28. Hiding content visually on a page with custom CSS If you’re using another framework or rolling your own styles in Visualforce, create a custom class and add it to the content you want to hide: .assistive-text { position: absolute; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); padding: 0; border: 0; height: 1px; width: 1px; overflow: hidden; z-index: -1000; }
  • 29. Lightning accessible hidden label example <form class="slds-form"> <div class="slds-form-element"> <div class="slds-form-element__control"> <div class="slds-input-has-icon slds-input-has-icon--left"> <c:svgIcon svgPath="/resource/slds0121/assets/icons/utility-sprite/svg/symbols.svg#search" category="utility" size="x-small" name="search" class="slds-input__icon slds-icon-text-default" /> <ui:inputText aura:id="q" label="Search" class="slds-input" labelClass="slds-assistive-text" /> </div> </div> </div> </form>
  • 30. aria-describedby associates help text and error messages with input controls While <label> tags are used to associate form fields with their label, aria- describedby is used to associate information beyond a label to an input ● When a user places focus on an input, both the label and the help or error text will be available to screen readers
  • 31. Using aria-describedby in Visualforce ● Visualforce <apex:input*/> tags don’t have native aria-* attribute ● Leverage HTML pass through attributes and add html-aria-describedby ● Use the $Component global merge field to get the generated id of the related element if it’s an <apex:outputPanel/> or other Visualforce component Unfortunately, neither Salesforce Classic or Visualforce set aria-describedby automatically for errors, so this is a manual exercise. If the user has Accessibility Mode enabled, then labels of fields with errors prepend “Error -” to the label. Lightning handles this better, as you’ll see.
  • 32. Visualforce aria-describedby example Visible inline help text is great for settings like this one in the Nonprofit Starter Pack, which aren’t edited very frequently and can be hard to understand from just the label.
  • 33. Visualforce aria-describedby example STG_PanelContacts: right now, the help text isn’t semantically associated with the field it describes <div class="form-group"> <apex:outputLabel value="{!$ObjectType.npe01__Contacts_And_Orgs_Settings__c.Fields. npe01__Account_Processor__c.Label}" for="slAP" styleClass="col-sm-4 control-label" /> <div class="col-sm-8 form-control-column"> <apex:outputField value="{!stgService.stgCon.npe01__Account_Processor__c}" rendered="{! isReadOnlyMode}" /> <apex:selectList value="{!stgService.stgCon.npe01__Account_Processor__c}" multiselect=" false" size="1" rendered="{!isEditMode}" id="slAP" styleClass="form-control"> <apex:selectOptions value="{!listSOAccountModels}"/> </apex:selectList> </div> <div class="col-sm-offset-4 col-sm-8 help-block"> <apex:outputText value="{!$Label.stgHelpAccountModel}" /> </div> </div>
  • 34. Visualforce aria-describedby example STG_PanelContacts: now with accessible help text! <div class="form-group"> <apex:outputLabel value="{!$ObjectType.npe01__Contacts_And_Orgs_Settings__c.Fields. npe01__Account_Processor__c.Label}" for="slAP" styleClass="col-sm-4 control-label" /> <div class="col-sm-8 form-control-column"> <apex:outputField value="{!stgService.stgCon.npe01__Account_Processor__c}" rendered="{! isReadOnlyMode}" /> <apex:selectList value="{!stgService.stgCon.npe01__Account_Processor__c}" multiselect=" false" size="1" rendered="{!isEditMode}" id="slAP" html-aria-describedby="{!$Component. slAPHelp}" styleClass="form-control"> <apex:selectOptions value="{!listSOAccountModels}"/> </apex:selectList> </div> <apex:outputPanel id="slAPHelp" layout="block" styleClass="col-sm-offset-4 col-sm-8 help- block"> <apex:outputText value="{!$Label.stgHelpAccountModel}" /> </apex:outputPanel> </div>
  • 35. Errors and aria-describedby in Lightning Set errors on a field using the component’s .errors attribute to dynamically create and insert the error message and aria-describedby tag into the field DOM: createExpense : function(component, event, helper) { var amtField = component.find("amount"); var amt = amtField.get("v.value"); if (isNaN(amt) || amt==''){ amtField.set("v.errors", [{message:"Enter an expense amount."}]); } else { amtField.set("v.errors", null); var newExpense = component.get("v.newExpense"); helper.createExpense(component, newExpense); } } More on error handling: https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_throw_error.htm
  • 36. Errors and aria-describedby in Lightning This is what the generated markup looks like from the previous example: <div class="slds-form-element slds-is-required"> <div class="slds-form-element__control"> <div class="uiInput uiInputNumber uiInput--default uiInput--input has-error"> <label class="slds-form-element__label uiLabel-left form-element__label uiLabel" for=" 34:2;a" ><span class="">Amount</span><span class="required">*</span></label> <input class="slds-input input" max="99999999999999" step="1" type="text" min=" -99999999999999" aria-describedby="112:c" placeholder="" required="" id="34:2;a"> </div> <ul class="has-error uiInputDefaultError uiInput uiInputNumber uiInput--default uiInput-- input" id="112:c"> <li class="form-element__help">Enter an expense amount.</li> </ul> </div> </div>
  • 37. Help and aria-describedby in Lightning <div class="slds-form-element slds-is-required"> <div class="slds-form-element__control"> <ui:inputText aura:id="expname" label="Expense Name" class="slds-input" labelClass="slds-form-element__label" value="{!v.newExpense.Name}" required="true" /> </div> <div class="custom-help-block"> <p>Please use the format: Date - last name - purpose</p> </div> </div> Unfortunately, the ariaDescribedBy attribute hasn’t been surfaced in the Lightning Component framework on the platform as of Winter ‘16 (more info)
  • 38. Using aria-describedby in other frameworks In other frameworks, just use the aria-describedby attribute on the <input/> element to associate it with the element containing the message. You can use Element.setAttribute() to set the attribute dynamically via JavaScript during error handling. <label for=”myFieldId”>Field Label</label> <input id=”myFieldId” type=”text” value=”fieldValue” aria- describedby=”myMessageId” /> <span id=”myMessageId”>More information or an error message about this field</span>
  • 39. Group related radio buttons within a <fieldset/> Consider that a set of radio buttons are an answer to a question.
  • 40. Group related radio buttons within a <fieldset/> <label> associates answer choices to their radio buttons. <input type=”radio” id=”color-blue” name=”color” value=”blue” /> <label for=”color-blue”>Blue</label>
  • 41. Group related radio buttons within a <fieldset/> The <legend/> of the <fieldset/> associates the question to the answer choices. <fieldset> <legend>What is your favorite color?</legend> <!-- blue/red/green/orange radio buttons go here --> </fieldset>
  • 42. Other use cases for <fieldset/> ● Group related fields -- consider Shipping Address vs Billing Address in compound fields ● Group checkboxes to allow multiple possible answers (“check all that apply”)
  • 43. Using <fieldset/> in Visualforce ● Specify the legendText attribute on <apex:selectCheckboxes/> and <apex:selectRadio/> to properly group the input controls in a fieldset with a legend ● If needed, hide the legend from sighted users by setting legendInvisible=”true” -- this adds class=”assistiveText” to the <legend/> tag, which keeps to the legend accessible to assistive technologies but hides it visually
  • 44. Using <fieldset/> in Visualforce: Classic Styling <apex:page controller="CheckboxTestControllerVF"> <apex:form> <apex:selectCheckboxes layout="pageDirection" legendText="Contacts to invite:" value="{!contactIds}"> <apex:selectOptions value="{!items}" /> </apex:selectCheckboxes> </apex:form> </apex:page> public List<SelectOption> getItems() { List<SelectOption> options = new List<SelectOption>(); for (Contact c : [SELECT Id, Name FROM Contact]) { options.add(new SelectOption(c.Id, c.Name)); } return options; }
  • 45. Using <fieldset/> in Lightning with SLDS <aura:component implements="force:appHostable" controller="CheckboxTestController"> <aura:attribute name="contacts" type="Contact[]" /> <aura:attribute name="checkedContacts" type="String[]" /> <aura:handler name="init" value="{!this}" action="{!c.doInit}" /> <div class="slds-form--stacked"> <fieldset class="slds-form-element"> <span class="slds-form-element__label slds-form-element__label-top"> <legend>Contacts to invite:</legend> </span> <div class="slds-form-element__control"> <aura:iteration var="con" items="{!v.contacts}"> <label for="{!'c' + con.Id}" class="slds-checkbox"> <input type="checkbox" id="{!'c' + con.Id}" value="{!con.Id}" onchange="{!c.updateCheckboxes}" /> <span class="slds-checkbox--faux"></span> <span class="slds-form-element__label">{!con.Name}</span> </label> </aura:iteration> </div> </fieldset> </div> </aura:component> Note that we’re not using <ui:inputCheckbox/> here: as of Winter ‘16 there’s no way to (1) position the label on the right and (2) add the faux checkbox <span/> for SLDS styling.
  • 46. Using <fieldset/> in other frameworks <fieldset> <legend>My Legend</legend> <!-- Form fields and other grouped content go here --> </fieldset>
  • 47. If an element behaves like a button, it’s a <button/> Generally speaking, if an element submits a form, executes some code without leaving the page, or otherwise has button-like behavior, it should be a <button/> Image-only buttons have other important considerations -- we’ll talk about this in Images.
  • 48. Why semantic <button/> use is important ● Buttons have different interaction behaviors than links and are announced differently by assistive technologies ○ Pressing Space or Enter triggers onclick on button, but only Enter triggers onclick on links ○ <a/> elements with an empty href attributes won’t receive keyboard focus ● <div/> and <span/> elements don’t receive keyboard focus, so aren’t accessible from the keyboard* ● Some assistive technology uses shortcut keys to get a list of links or buttons on the page -- you want the right elements to be returned
  • 49. Images Describe non-text content to assistive technologies
  • 51. <img/> requires the presence of the alt attribute The alt attribute helps assistive technologies describe the purpose of an image to users who can’t see it ● Images that are purely decorative should have an empty alt attribute: <img src=”decorative.jpg” alt=”” /> ● Informational images should have a useful alt attribute value: <img src=”exclamation.png” alt=”Warning” /> ● “null”, “empty” and “undefined” are not appropriate alt values ● If the alt attribute is missing, the file name will be read instead!
  • 52. alt attributes in Visualforce Use the alt attribute on <apex:image/> for accessible images in Visualforce: <h1 class="h4">Recent Items</h1> <ol class="list-unstyled recentItems"> <apex:repeat value="{!recentItems}" var="item"> <li> <apex:outputLink value="/{!item.Id}"> <apex:image value="/s.gif" styleClass="{!IF(item.type='Account', 'account24', 'contact24')}" alt="{!IF(item.type='Account', 'Account', 'Contact')}" /> {!item.Name} </apex:outputLink> </li> </apex:repeat> </ol>
  • 53. alt attributes in Lightning <ui:image/> has an imageType attribute with two possible values: ● informational: the alt attribute is also required ● decorative: the alt attribute is not required However! <ui:image/> is not available in Lightning components as of Winter ‘16. Instead, use the HTML <img/> tag and set the alt attribute as for any other framework (remember to set alt=”” for descriptive images)
  • 54. alt attributes in Lightning: SLDS Example If you want to leverage the SVGs in SLDS inside Lightning Components, you may need the Lightning SVG Icon Component Helper
  • 55. alt attributes in Lightning: SLDS example recentItemsList.cmp <aura:component implements="force:appHostable" controller="RecentItemsControllerLX"> <ltng:require styles="/resource/slds0121/assets/styles/salesforce-lightning-design-system.min. css"/> <aura:attribute name="items" type="RecentlyViewed[]" /> <aura:handler name="init" value="{!this}" action="{!c.doInit}" /> <ol> <aura:iteration var="item" items="{!v.items}"> <li> <c:sObjectHyperlink sObjectId="{!item.Id}" hyperlinkLabel="{!item.Name}" sObjectType="{!item.Type}" /> </li> </aura:iteration> </ol> </aura:component>
  • 56. alt attributes in Lightning: SLDS example sObjectHyperlink.cmp <aura:component > <aura:attribute name="sObjectId" type="Id" /> <aura:attribute name="hyperlinkLabel" type="String" /> <aura:attribute name="sObjectType" type="String" /> <a href="javascript:void(0);" onclick="{!c.showObjectInfo}"> <aura:renderIf isTrue="{!v.sObjectType == 'Account'}"> <c:svgIcon svgPath="/resource/slds0121/assets/icons/standard-sprite/svg/symbols.svg#account" category="standard" size="small" name="account" containerClass="slds-icon__container slds-icon-standard-account" assistiveText="Account"/> </aura:renderIf> <aura:renderIf isTrue="{!v.sObjectType == 'Contact'}"> <c:svgIcon svgPath="/resource/slds0121/assets/icons/standard-sprite/svg/symbols.svg#contact" category="standard" size="small" name="contact" containerClass="slds-icon__container slds-icon-standard-contact" assistiveText="Contact"/> </aura:renderIf> {!v.hyperlinkLabel} </a> </aura:component>
  • 57. Image links and buttons need text content With icon fonts, this is too common: <a href="http://www.facebook.com/"> <span class="icon-facebook"></span> </a> <a href="http://twitter.com/"> <span class="icon-twitter"></span> </a> <a href="http://youtube.com/"> <span class="icon-youtube"></span> </a> <a href="http://plus.google.com/"> <span class="icon-googleplus"></span> </a>
  • 58. Image links and buttons need text content How a screen reader announces this: “Link” “Link” “Link” “Link”
  • 59. Image links and buttons need text content How to fix it: <a href="http://www.facebook.com/"> <span class="icon-facebook"><span class=”assistive-text”>Facebook</span></span> </a> <a href="http://twitter.com/"> <span class="icon-twitter"><span class=”assistive-text”>Twitter</span></span> </a> <a href="http://youtube.com/"> <span class="icon-youtube"><span class=”assistive-text”>YouTube</span></span> </a> <a href="http://plus.google.com/"> <span class="icon-googleplus"><span class=”assistive-text”>Google+</span></span> </a>
  • 60. Image links and buttons need text content Bootstrap image example: <button class="btn btn-link"> <span class="glyphicon glyphicon-remove delete-icon"> <span class="sr-only">Delete</span> </span> </button> See also: http://salesforce.stackexchange.com/questions/99411/make-an-apeximage-appear-conditionally-with-apex- code/99418#99418
  • 61. Interactivity Make all interactive content accessible from the keyboard.
  • 62. Ensure interactive elements are accessible using keyboard and assistive technology These components all follow the W3C spec for accessibility ● Menu <ui:menu/> ● Modal dialog <ui:modal/> ● Non-modal panel <ui:panel/> ● Autocomplete typeahead <ui:autocomplete/> ● Tabset <ui:tabset/> ● Tooltip <ui:tooltip/> Only <ui:menu> is supported in Lightning as of Winter ‘16 -- for a list of supported components, use https://yourdomain.lightning.force.com/auradocs/reference.app rather than the open source http: //documentation.auraframework.org/auradocs)
  • 63. Use hyperlinks and buttons for click targets Only <a/>, <button/>, and <input/> types should be: ○ Click targets ○ Hover targets They natively receive and show focus, perform actions, and communicate with assistive technologies.
  • 64. Use hyperlinks and buttons for click targets Don't make <div/>, <span/> and other non-focusable elements “clickable”.
  • 65. Use hyperlinks and buttons for click targets Navigation options: ● add onclick to a card for a larger tap/click target, but include a hyperlink to the same destination ● wrap the card in an <a/> Interaction: ● add an explicit <button/> instead of onclick on a non-focusable element
  • 66. Using hover ● Behaviors which occur on mouse hover must also occur with keyboard focus ● Triggers need to be focusable In this example, the blue circle with the “i” character should be an anchor. The tooltip shows when the anchor is in focus.
  • 67. Using hover Don’t use hover to reveal actionable content, such as buttons or links. Just show them. In Lightning Experience, pencils aren’t hidden behind hover states. Instead, they get darker on hover.
  • 68. Color Usage Color is a key part of visual design -- but not everyone using your page will see it the same way you do
  • 69. Text color contrast ratio must meet the minimum requirement According to the WCAG, ● Contrast ratio between text and background should be at least 4.5 to 1. ● If font is at least 24 px or 19 px bold, the minimum drops to 3 to 1. For large text, the lightest gray you can use on white is #959595 For small text, the lightest gray you can use on white is #767676
  • 70. Don’t use color as the only means of differentiation
  • 71. Don’t use color as the only means of differentiation
  • 72. Other Considerations These are other items that test automation can be used to find.
  • 73. Other ● Have a descriptive page <title/> ○ This is good not only for assistive tech, but for those of us who like to have 20 tabs open in our browsers! ● Properly nest your page headings (<h1/><h2/><h3/>) ○ Use heading tags for headings! <div class=”my-heading-style”>...</div> does not communicate that the content is a heading to assistive technologies. ● Consider whether lists are ordered or unordered ● Data table cells must be associated with data table headers ● Have a descriptive title attribute for frame and iframe elements ● Avoid repetitive hyperlink text (Edit, View All, etc) ○ Provide disambiguation for assistive technologies by hiding the content visually
  • 74. Testing and Debugging How can you tell if you’re doing the right thing?
  • 75. Testing and Debugging ● Unplug your mouse ● Test with users with disabilities ● Chrome Accessibility Developer Tools ● Mac OS X ○ VoiceOver - free screen reader software (System Preferences > Accessibility > VoiceOver) ○ Full Keyboard Access: All Controls (System Preferences > Keyboard > Shortcuts) ○ Safari accessibility: tab to links (Preferences > Advanced >Press Tab to highlight each item on a webpage) ● Windows ○ NVDA - free screen reader software ○ Most screen reader users use JAWS on Windows
  • 77. Resources How to Meet WCAG 2.0 7 Things Every Designer Needs to Know about Accessibility Colorsafe.co Microsoft Inclusive Design Toolkit