Empathy-Driven Development

Marcy Sutton

Recorded at JSConf EU 2018


Get notified about Marcy Sutton

Sign up to a email when Marcy Sutton publishes a new video

hello jeaious comm I'm super excited to
be back here it's been a few years since
I've been at J's confi you I wish I
could say that accessibility has gotten
a lot better and that time but we still
need to be reminded that people with
disabilities are left behind quite often
so to tell you about accessibility today
I'm gonna do something a little bit
different I don't have any slides
instead we're gonna take a live
debugging tour of a react application
that I've built with a few components
the goal of which is to teach you how to
debug components for accessibility
because you are all capable of doing it
you just need a little bit of knowledge
and a little bit of empathy for your
user you can find this repo with these
components on my github it's Marci
Sutton's slash empathy - driven -
development and with that we're just
gonna dive right into some code so if we
go over to the browser it can show you
this basic component library that I've
built it's got three components in it a
login form a card flip and a menu and
it's worth reiterating that we can't
cover all of it in 25 minutes but I'm
gonna show you some keyboard mechanics
some screen reader support and some
things that are chronically forgotten
and it really ends up impacting users so
to get started let's look at our login
form it has three fields in it those
fields have placeholders unfortunately a
placeholder is not enough for a screen
reader user to use a web page and I
really wish that we could move on from
this but I see this so often so let's
check out how we can fix this if I were
debugging this on a real page I would
open the developer tools so if I open up
my dev tools in Chrome I can't go and
inspect this HTML and see what's going
on a quicker way to do this is to use a
tool like the excrement ention there are
other tools I like this one I happen to
work on it it's built with react and
JavaScript I can analyze any webpage and
see what's going on with this and sure
enough those placeholder attributes are
not enough for a screen reader user in
all browsers so that's something we
could fix there's also
an error here about content not being
contained in a landmark region so our
main content is just sitting there in
the dom and it's not wrapped in a
landmark so we're not taking advantage
of HTML for screen reader users so let's
go back over to my text editor and start
poking around and fix some of this stuff
so in my app JS file it's written in
react this is where everything comes
together all of my components I can see
that there is a header element here so
scroll down there is a main div that
just has a class name and guess what
that's not very semantic so let's go fix
that I'm gonna change this div to a main
element which has an implicit role of
main but if you're supporting Internet
Explorer 11 which a lot of users with
disabilities still rely on we actually
need to bolt on a role so I'm going to
bolt on main it is a little redundant
but if you're actually supporting ie 11
or below you need to add that to expose
the semantics similarly on the header
element we can add a role of banner and
that will expose the fact that this is a
global header not to be confused with a
header inside of an article tag so that
way assistive technology they can use
these these landmarks as navigation
points in our application much like they
might navigate by headings you can also
navigate by landmarks so we uncovered
those first few problems in the axe
Chrome extension I'm also going to show
you the login form since we looked at
that the login form demo in JavaScript
this example uses an array with the
three field names those fields end up
getting passed to our login form and
then we can create a dynamic dynamic
login form based on this array so if I
go look at the login form component it
takes that array of fields Maps them to
a set of inputs so each input we iterate
over its name this is where those labels
are missing so I'm gonna go here and add
a label and I'm going to use the key
from this the array value to add a name
now we've got something a little
here with the placeholder this is sort
of a design decision that you might need
to make with your design team do you
have a visible label or do you use
something like Aria label I'm actually
gonna opt for the visible label because
I don't know about you but when I type
in a form field that only has a
placeholder and I forget what I'm typing
in and I feel like back out and go back
so I would really advocate for the
visible label if it was something like a
telephone number and I had a specific
pattern then that would be a good case
for a placeholder and additionally we
can do use HTML a little bit better here
by adding a fieldset element around our
form fields so I'm going to wrap this in
a field set and then this h2 heading I'm
gonna wrap in a legend tag so leveraging
htmls capabilities to make a more
semantic inaccessible form no matter how
you're delivering your HTML this happens
to be in JSX using react so to test this
in the spirit of test-driven development
I'm going to apply selenium webdriver I
have a script in my package JSON file
called an integration so I'm gonna run
NPM run integration it's gonna use mocha
fire up the app in the browser and it
has found that there are no violations
in this if we go look at this test test
log in no pressure doing it live login
this is the fun part right watching me
type so I have a test here it's actually
using the axe webdriver jus library
which is the same accessibility API we
were using in the browser extension but
we can pull this in our integration
tests and leverage that accessibility
API so we don't have to know the
nitty-gritty details of accessible names
and color contrast and a lot of the
common accessibility problems so I'm
using selenium here because that's a lot
like what a real user would experience I
can fire up a browser in this case I was
using Chrome it goes and hits that
localhost URL for the login form and
then I have a single test in here it
uses ax builder analyze
what that will return to me is an object
with accessibility violations that I can
use to assert accessibility problems now
it's it's also worth pointing out that
this will only catch the low-hanging
fruit
so those basics that we commonly forget
it's nice to have a tool point out to
you that you've forgotten it and then
for more complex problems but this is a
really great way to start so we fixed
our first few problems in our login form
let's go back to the browser and look at
our next component I guess one thing to
point out about this login form when I
added the fieldset it did add a border
around it but that's an easy fix to make
with CSS so you can style it however you
want but under the hood we've added some
really great semantics to this form so
on to our next component the card flip
now I'm gonna I'm not going to name
where this came from but it came from a
real web site out of respect for the
innocent it's a little profile so in
this case I'm using a picture of my dog
mr. Rainier maquette orton so i just i
can't get enough of his cute face but
when i hover over this it reveals
content on the back side of this card
flip now if i'm using a keyboard only
say if I tab through this web page
I don't ever reach this card flip
because it just works with the mouse so
for a keyboard only user someone with a
disability someone using a screen reader
or even me by the end of the work day or
the work week when my programmer elbow
really flares up and I can't use a mouse
anymore this is super unusable so it
needs something to make it focusable and
we need to be able to flip it back and
forth I'm actually gonna make a design
decision here to make this work on click
instead of on hover because I can tell
you from experience that the reality of
maintaining hover animations and
keyboard support like you probably don't
want to make this move on keyboard focus
so that one-to-one interaction is not
the same anymore so I'm gonna make a
judgment call here and change it to work
a little bit differently and just to
give you a little more info before we go
and make our changes to this we can go
inspect what this markup under the hood
is looking like
it's a series of divs it does have an
image for the picture of rainier I've
got some content the the backside of
this card we want to make it revealed
when we interact with it for everybody
not just for Mouse users so with that
let's go back to our card flip so the
card flip demo is a it's where we
instantiate this component it could be
reusable you could have multiple team
member components on a page and they all
have this card flip interaction so I'm
passing it some data it instantiates
this card flip component now this card
flip needs to manage some state is it
active or not we need to add some markup
to this to actually be able to reach it
and it's sad how common I find user
interface components that have
completely forgotten the keyboard so
we're gonna fix this right now I'm going
to go and check out the fixed state of
this moustache what I've got here okay
so our card flip is in a slightly better
state so I'm gonna give you a little
tour of what I fixed here our card flip
component if we scroll down and look at
this markup now instead of just a series
of divs that we hover on we actually
have a button the button is focusable by
default the text inside of it is the
team members name and the little
subtitle it's pretty short amount of
content so it's OK for a button name I'm
using the click event on a button which
works for everybody you can use it with
the mouse you can use it from the
keyboard so this is way more accessible
so that button is then going to trigger
the card flip and that is going to
expose the back side of this card
content inside of a dialog element I'm
using a roll of dialog it's similar to
our landmarks earlier if you're using
the actual dialog element you still need
to bolt on this roll of dialog to expose
its semantics in older browsers so this
is a good start what we need to look at
now is how we're actually going to
handle this interaction so when I land
on that button I'm gonna fire that click
event and
in react style I'm going to change the
state and that's why I'm going to flip
between the front and the back now
there's something you should know about
this type of interaction is that we need
to handle the users focus so they're not
getting left behind in the background
layer so when it opens we're gonna send
focus into it and react a really great
tool for that is the ref the ref API
they've just added a even better handle
for it with react duck create ref so for
each element that you're going to send
focus to you can create a ref it gives
you a handle or a hook to add focus
management so we have one for the toggle
which is where it starts and then we
have a close button now because we've
made this open on click we need a way to
get back so let's go check this out in
the browser now when I hover over it
that's the old version so now it's not a
hover interaction anymore I've indicated
that it's interactive by changing the
text to have some other indication which
in this case is an underline so when we
look at it we can tell it's more
interactive than just text on the screen
so when I click on it now I can actually
fire this interaction and my focus is
sent into it
and so if I'm actually using the
keyboard instead of skipping right past
this component I can now land on it I
can hit the enter key and my focus is
sent into this component this is a
pretty simple little card flip but these
keyboard mechanics you can use for other
things like modal dialogs menus which
we'll look at in a second but we want to
make sure we're not just leaving the
keyboard user behind completely both by
not making things focusable and then not
handling their focus so in JavaScript
heavy applications we want to make sure
we're mindful of managing the users
focus and sending them in and out of
interactive layers so this is a lot
better there's a little Twitter link in
here that also needs a little bit of
help and one thing I want to fix now is
if you're seeing this blue focus ring
you might be going wait a minute I need
to turn that off I hate that blue
outline I've been there so I have a
solution for you let's go back to our
text editor I'm actually going to
a tool called what input all I have to
do is include what input I could
download it from NPM that gives you a
hook in your CSS to actually style based
on the users input modality we call it
so if they're using a mouse you can
style one way if they're using the
keyboard you can style another way and
so on with touch so what input we just
include it in our JavaScript there's a
similar standards-based solution coming
called focus visible that'll be a CSS
for selector it's not quite ready for
primetime yet so I am still a what input
fan but we need one more piece to this
and I'm actually going to cheat a little
bit and check out the solution so if we
add what input then when we go to our
CSS instead of hiding the outline for
everyone which if you have outlined none
for everything go to nuke it from orbit
get rid of it use a tool like what input
or focus visible to be more selective
about how you apply focus so with this
data - what intent attribute that what
input is applying to our HTML whenever
that matches then we can hide the
outline and I'll show you what effect
that has now when we click on this
component with the mouse we don't get
that outline so it keeps Mouse users
happy but if I use the keyboard as an
input modality I still get that visible
outline so I can see where I am on the
screen super important if you can't use
a mouse or a trackpad even users that
rely on that can't just magically grow
the ability to see where they are on the
screen so this is super helpful and it
makes it easier to support all users so
that's a card flip animation how we can
support everybody by doing it I guess
before we move on I want to show you
what the tests look like for this card
flip so I've written some unit tests for
this it's debatable whether you want
your test to live in unit tests or
integration tests I think you can do
both it depends on what exactly you're
testing but for focus management unit
tests make a lot of sense if your
testing AP is like if you have a focus
manager throughout your whole
application you can test with unit tests
for that in this case I could have done
either I'm testing you know where the
focus is being handled I'm testing the
state of this component so I'm using
just for this component I'm first
testing the active state and checking
whether it's or I'm actually setting the
state in the test to true this is sort
of the mouse user case and just using
pure state so the side effect of
changing the state of this component is
that it adds a CSS class of active I can
go and check if I modify the state if it
is handling that appropriately for the
keyboard mechanics I want to do that
same thing I want to see that side
effect of the Dom being manipulated but
I'm gonna simulate it using a keydown
event so with just an enzyme in react
land you can simulate events the catch
with this is that your event handling
has to be in react you can't use enzyme
to simulate a native JavaScript event so
a little bit of a gotcha there but since
I did use react for this I can go and
simulate that event and check that my
logic and my component is doing what I
expect so in this case I'm simulating a
key down with an inter key directly on
that button that I created and then I
expect that it will also add that active
class so gotcha
number two for focus management testing
is that sometimes your Dom might not be
ready when you go to test it the test
executes so fast the element that might
not be visible yet and you need to wait
a tick it sucks I wish we didn't have to
do that but if you're actually testing
for accessibility you might have to
become friends with the set timeout
function so set timeout we just told the
event loop to wait a tick and then our
element with the focus of all thing is
actually visible and ready and then to
take this one step further I've got the
same API that we used earlier in the axe
webdriver jeaious utility I'm using the
underlying JavaScript axe core library
if you've ever used lighthouse in Google
Chrome it is the same accessibility API
use there so XCore it is my favorite
tool but there are a few others and the
idea is that it is the same API to get
some accessibility basics into your test
automation that way if a teammate breaks
something for accessibility or you come
back a few weeks later and break your
own thing you can prevent those problems
from making it to production so because
I'm using just here which uses Jas Tom
I've disabled two rules in ax I've
disabled color contrast and Lincoln text
block because J s Tom does not have some
of the necessary api's for that but then
you'd want to go back either in a
browser extension or an integration test
and run those color contrast tests again
because color contrast is actually the
number one accessibility problem on the
web in this case my app didn't really
have any color contrast problems but we
want to test for anything else that it
might find so I'm going to use I'm
instantiating my component I'm passing
it some dummy data and then I'm using
axe dart run to return that violations
array to me and then I can make similar
assertions as I did in my integration
test so that's pretty cool
let's run that so I'm going to do n PM
test that's gonna fire up just I can hit
all and we'll see what's going on so our
tests are passing which is amazing I've
got that card flip it's checking the
keyboard mechanics so if I broke it like
maybe somebody didn't know what the
button was for and they change it back
to a div that test would then fail and
it's not just accessibility testing off
to the side it's baked into our tests so
it's a holistic approach and it really
makes it embedded and mainstream so I
love that way of working
especially with test-driven development
when you can write a failing test go add
the feature and then make the test pass
so that's a card flip let's look at our
last component which is a desktop style
menu now if you're building something
like a text editor built with web
technologies or maybe you actually have
a complex web application that
your menu doesn't necessarily navigate
the user to places but you can do things
like find something or split content
into lines this this menu that I have
here is very it looks like something you
would find in a text editor
and when I hover over each of these
selections it opens that little submenu
so if I go and inspect this let's go see
what's going on with this markup so the
menu is an unordered list it has a set
of list items that are not interactive
so there's some hover going on here but
there's no handle for a keyboard user to
get to and the sub content is just a
sibling unordered list
there's no programmatic association
between these two there's no hooks for
keyboards there's no screen reader
support I just found this component on
the internet so when you're out there
looking for components you might find
stuff like this and without a second
thought you're all of a sudden you're
shipping something that you thought was
saving you time but opens you up for
some accessibility risk and leaving your
users behind so I thought this had
potential and so let's go look at how I
actually fix this let's go back to our
text editor I'm gonna open up our menu
component it is using this react menu
aim component it's actually creating a
react mixin under the hood and then the
the demo that I pulled in gave me the
opportunity to make changes to it so the
default state of this is just these this
unordered list all this good stuff that
is sadly not accessible so let's go fix
it I'm gonna get out of jest and I'm
gonna check out the fixed solution for
this and we'll go and make sure that our
solution is showing so I guess the first
thing that I had to do was add something
focusable I added a few different items
to this including a roll of menu to
indicate to assistive technology that
this is in fact a desktop style menu and
then inside of the the top-level list
items I opted to create a button for
each
item so that it would be focusable by
default I'm giving that a roll of menu
item so kind of overloading the default
semantics of that element but I'm
getting the focus ability for free and
this pattern is not something I made up
it's actually from the Aria authoring
practices guide which I'll have a link
for in a minute but I'm using their
recommended attributes of Aria has pop
up of true I'm using Aria expanded
depending on the state of it I can
change that attribute to be true or
false and then this is the where the
magic happens the onkeydown function it
also uses a ref so I can handle focus
management between here to finish out
our tour I have the the child list
instead of being siblings I moved it so
that it's now inside of that list item
like Aria controls which if you've read
from Hayden Pickering Aria controls is
poop so we're really not supported that
well so I opted to use html's I own
hierarchy to make that Association and
then the child items for this stage one
I just did the top level when I handle
the key events I can hit handle up
handle down and those will check where
we are in the menu and change the state
accordingly so the state is really just
setting the state of what the active
index is and then if I've used the
keyboard which I know because I've used
the keyboard to get there I can send
focus to that item so if I go to this
menu now it looks slightly different but
you can always play around with the
style but the idea of this desktop style
menu it's not a list of links it's
actual menu for an application is it
acts as one tab stop and I can arrow
around and now I can actually reach
everything for this stage one so for
Stage two let's go check that out real
quick make sure we don't have any
changes so for Stage two it got a little
more complex because now I have to
manage the state of two levels and so
for my first pass at this I had to add
hooks for the number of items in both
levels I had to need to refresh this
I have to maintain the sub menu items
and all kinds of stuff so you can check
this out on github to see the full
solution if we go look at it in the
browser now I can go through these
top-level items and I can get to the
lower level of items so with a little
bit of refactoring I was able to make
this way more accessible than it was
before this is something I'll probably
contribute back to the component because
when you're using components you can
really help other people out by filing
issues for accessibility and if you have
the solution contribute it or suggest it
in the issue so we've managed to make
some things way more accessible than
they were before I didn't have any
slides so if you want to review what
we've worked on today you can check out
my github I've tagged all of the fixes
in git tags and there's some resources
here if you're new to accessibility if
you need to help get your team members
on board I've got some resources here
the one I really want to point out is
don't need to reinvent the wheel with a
lot of these interactions and components
so you can go check what's out there
already and you can go learn more about
accessibility my last caveat is that
automated testing and this type of work
will only get to the low-hanging fruit
so you also want to test with real users
because automated tooling can't catch
everything it can't make your app
accessible it relies on you to know how
to make the components in your app more
accessible with tips like I have in this
in this repo but then also test with
real people people with disabilities see
how they use your application you might
be surprised that they stumble and
they've hit barriers so I hope that I've
given you some tools and techniques you
can use to make your apps more
accessible thanks so much for having me
[Music]