Modernization Hub

Modernization and Improvement
Empathy-Driven Development – Marcy Sutton – JSConf EU 2018

Empathy-Driven Development – Marcy Sutton – JSConf EU 2018


Hello, JSConf. I’m super excited to be back here. It’s been a few years since I’ve been to JSConf
EU. I wish I could say that accessibility has
gotten better in that time, but we still need to be reminded that people with disabilities
are left behind quite often. To tell you about accessibility today, I’m
going to do something a little bit different. I don’t have any slides. Instead, we’re going to 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’re 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 the repo a my GitHub. With that, we’re going to dive right into
code. If I go to the browser, I can show you the
basing component library I’ve built. It’s got three components – a login form,
a card flip, and a menu. It’s worth reiterating we can’t cover all
of it in 25 minutes. I will show you keyboard mechanics, screen
reader support, and things that are chronically forgotten. 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 screenreader user to use a web page, and I wish we could move on from this, but
I see this so often. 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 DevTools in Chrome, I
can go and inspect this HTML and see what’s going on. A quicker way to do this is to use a tool
like the X Chrome extension. There are other tools. I like this one. I happy to work on it. It is built with React and JavaScript. I can analyse any web page and see what’s
going on with this, and, sure enough, those placeholder attributes are not enough for
a screenreader user in all browsers. That’s something that we could fix. There is also an error here about content
not being contained in a landmark region. 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 to be
screenreader users. Let’s go back over to my text editor, poke
around, and fix some of this stuff. In my app.js file, this is where everything
comes together, my components. I can see that there is a header element here,
so that acts and one landmark. If we scroll down, there is a main detective
that has a class name. Guess what? That’s not very semantic. Let’s fix that. I’m going to change the divs to a main element
which has an implicit role of main, but if you’re supporting Internet Explorer 11, which
a lot of people with disabilities rely on, we need to bolt on a role. I’m going to bolt on main. It is redundant. If you’re supporting IE11 or below, you need
to add that to expose the semantics. Similarly, on the header element, we can add
a roll of banner and will expose the fact that this is a global header, not to be confused
with a header inside an article tag. That way, assistive technology, they can use
these landmarks as navigation points in our application, of like they might navigate by
headings, you can also navigate by landmarks. We uncovered those few problems in the X Chrome
extension. I am also going to show you the login form. The login form demo in JavaScript, this example
uses an array with the three field names. They get past the login form and we can create
a dynamic login form based on this array. If I look at the login form component, it
takes that array of fields, maps them to a set of inputs. Each input we iterate over its name. This is where those labels are missing. So I’m going to add a label. We’ve got something redundant here with the
placeholder. This is 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
area label? I’m going to opt for the visible label. 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 go back
out and back, I would advocate for the visible label. If it was something like a telephone number,
and it had a specific pattern, then that would be a good place for a placeholder. Additionally, we can use HTML better here
by adding a field set element around our form fields. I’m going to wrap in in a field set, and then
this H2 heading I will wrap in a legend tag. Leveraging HTML’s capabilities to make a more
semantic and accessible 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 web driver. I have a script in my package JSON file called
integration, so I’m going to run mpm run integration. It’s going to use mocha. It has found that there are no violations
in this. If we look at this test, no pressure doing
is live! Login, this is the fun part, right, watching
me type! So I have a test here. It’s actually using the just library the same
extension we were using in the browser extension, and we can leverage the accessibility API
so we don’t have to know the nitty-gritty details of accessible names, and colour contrasts,
and a lot of common accessibility problems. So I’m using Selenium here because that’s
a lot like what a real user can experience. I can fire up a browser. In this case, I was using Chrome. It hits that localhost URL for the login form,
and then I have a single test in here. It uses X build er. That will return to me an object with accessibility
violations that I can use to assert accessibility problems. It’s worth pointing out this will only catch
the low-hanging fruit, so those basics we forget. It is nice to have a tool pointing out you’ve
forgotten it and you can move on to use human power for more complex problems. We fixed our first few problems and 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 field set, it did add a border around it. You can style it however you want, but under
the hood, we’ve added great semantics to this form. So, on to our next component. The card flip. Now, I’m going – I’m not going to name where
this came from, but it came from a real website out of respect for the innocent! It’s a little profile. In this case, I’m using a picture of my dog,
Mr Ranier McChetterton, but, when I hover over this, it reveals back side on the card
flip. If I’m using a keyboard only, if I tab through
this web page, I don’t ever reach the card flip because it just works with the mouse. So, for a keyboard-only user, someone using
a screenreader, by the end of the workweek when my programmer elbow problem flares up,
this is super useful. We need to be able to focus and flip it back
and forth. I’m going to make a design decision here to
make it work on click rather than hover. I can tell you from experience that the reality
of maintaining hover animations and keyboard support, you don’t want to make this move
on keyboard focus, so that one-to-one interaction isn’t the same any more. I’m going to change it to work a little bit
differently. 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 is a series of detectives. It does — it is a series of divs. I’ve got some content. The back side of this card, we want to make
it revealed when we interact it for everybody, not just for mouse users. With that, let’s go back to our card flip. The card flip demo is where we instantiate
the component. It may be useful, they all have this card
flip interaction. Isle passing it some data. It instantiates this card flip component. It needs to manage state. Is it active or not in we need to add markup
to this to reach it. It’s sad how I find user interface components
who have completely forgotten the keyboard. We are going to fix this right now. So, our card flip, it is in a slightly better
state. So, I’m going to 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 adult. The text inside it is the team member’s name,
and a subtitle. It is a short amount of title so okay for
a button name. I’m working on the click event for the button
which works for everybody. You can use it from the mouse, you can use
it from the keyboard. This is way more accessible. So that button is then going to trigger the
card flip, and that is going expose the back side of this card content inside of a dialogue
element. I’m using a role of dialogue. It is similar to our landmarks earlier. If you’re useful the landmark element, you
need to bolt on the role of dialogue in order to support its semantics in older browsers. This is a good start. Now we need to look at how we are going to
handle this interaction. So, when I land on that button, I’m going
to fire that click event, and it’s in React style, I’m going to change the state. That’s why I’m going to flip between the front
and back. There is something you should know about this
type of interaction is that we need to handle the user’s focus so they’re not getting left
behind in the background layer. We will send focus into it. In React, the great tool for that is the ref
API. They’ve added a better handle for it, so,
with each element 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. Let’s check this out in the browser. Now, when I hover over it, that’s the old
version, so, now, it’s not hover interaction any more. I’ve indicated that it’s interactive by changing
the text to have some other indication which, in this case, is an underline. 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. If I’m using the keyboard, instead of passing
by this component, I can use the enter key and this is sent into the component. This is a simple card flip, but these keyboard
mechanics, you can use for other things, modal dialogues, menus – which we will look at in
a second. We want to make make sure that we’re not leaving
the keyboard user behind completely by not making things focusable and not handling their
focus. In JavaScript applications with be we want
to be mindful of the user’s focus and sending them in and out of interactive layer. This is a lot better. There is a Twitter link in here that also
needs a little bit of help. 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 add a tool called “what
input”. I can download it from MPM, gives you a hook
in your – to input the user modality. If you’re using a mouse, they can style one
way, a keyboard another way, and so on. There is a standards-based condition coming
been it’s not ready for prime-time yet, so I’m still a what-input fan, but we need one
more piece to this. I’m going to cheat a little bit. I’m going to check out the solution. If we add what-input, if we go to our CSS,
instead of lining the outside line for everyone, which, if you have outlined none for everything,
nuke it from orbit. Get rid of it. Put it to focus visible to be more selective
about how you apply focus. With this what-intent input, whatever that
matches, then we can hide the outline. I will show you what effect that has. Now, when we click on this component with
the mouse, we don’t get that outline. 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, which is super important if you can’t use a mouse, or attraction pad,
even. Users who rely on that can’t magically grow
the ability to see where they are on the screen. This is super helpful and makes it easy to
support all users. 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 are like for this card flip. So, I’ve written some unit tests for this. It’s debatable whether you want your tests
to live in unit tests or integrate 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 you’re testing APIs, like,
if you have a focus manager throughout your whole application, you can test with unit
tests for that been in this case, I could have done either. I’m testing where the focus has been handled. I’m testing the state of this component, so
I’m using Jest for this component. I’m first testing the active state, and check
– or setting the state in the test to true. This is 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,
that it is handling that appropriately. For the keyboard mechanics, I want to do the
same thing, I want to see the side effect of the DOM being manipulated but I want to
simulate it with a keydown event. With Enzyme in React land, you can simulate
events. The catch is that your event handling has
to be in React. You can’t use Enzyme to simulate a native
implement event, so a little bit of a gotcha there, but since I did use React for this,
I can simulate that event and check that my logic and component is doing what I expect. In this case, I’m simulating a key down with
an enter key on that burnt that I created. I suspect it will also add that touch of class. Gotcha number two is that sometimes, your
DOM may not be ready when you go to test it. The element might not be visible yet, and
you need a way to tick. Is sucks. I wish we didn’t have to do that. If you’re testing for accessibility, you might
have to become friends with the sett function. We just tell – the setTimeout function. We tell the element with the focusable thing
is actually visible and ready. Then to take this one step further, I’ve got
the same API that we used earlier, and the AX web driver JS utility, using the underlying
JavaScript core library. If you’ve used lighthouse in Google Chrome,
it is the same accessibility there. The idea is that it’s the same API to get
accessibility basics into your tests automation. That way, if a team-mate 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 into production. Because I’m using Jest here, which uses JS
DOM, I’ve disabled two rules in AX: colour contrast and text block, because JS DOM doesn’t
have some of the necessary APIs for that, but then you would want to go back either
to a browser extension and run those colour-contrast tests again because that’s actually the number-one
accessibility problem on the web. In this case, my app didn’t really in have
any colour contrast problems. I’m instantiating my component, passing it
dummy data and then using x.run and making similar assertions as I did in my test. I’m going to do mpm test. That’s going to fire up jest. I can hit “all”, and we will see what is going
on. 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, that test would then fail. It is 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. I love that way of working, especially with
test-driven development when you can write a failing test, go at the feature, and then
make the test pass. So that’s a card flip. Let’s look at our last component, which is
a December top-style menu. Now, if you’re building something like a text
editor built with web technologies, or actually you 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 consent into lines, this menu that I have here is very – it looks like
something you would pinned in a text editor. When I more over each of these selections,
it opens that little sub menu. So, if I go in and inspect this, let’s see
what is 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 is some hover going on here but no handle for a keyboard user to get to. The sub content is a sibling unordered list. There is no programmatic association between
these two, no hooks for keyboards, no screenreader support. I just found this component in any event on
the internet. You might find stuff like this. Without a second thought, you’re shipping
something that you naught was saving you time but opens you up for some accessibility risk,
and leaving your users behind. So I thought this had potential, and let’s
go and look at how I actually fixed this. Let’s go back to our text editor. I will open up our menu component. It’s using this React menu AIM component. It is actually creating a React mix-in under
the hood, and then the tell me mow that I pulled in gave me the opportunity to make
changes to it. So the default state of this is all this good
stuff that is sadly not accessible, so, let’s go and fix it. I’m going to get out of Jest, and I’m going
to check out the fixed solution for this. We will go and make sure that our solution
is showing. I guess the first thing I had to do was add
assist focusable. I added a few different items to this to the
role of menu, to insist on the fact that this is a desktop-style menu, and, inside 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 role of menu item, so kind
of overloading the default semantics of that element, but I’m getting the focusability
for free. This pattern is not something I made up. It’s from the authoring practices guide. I’m using their recommended attributes of
RE has pop-up of true, using REX expanded, I can change that attribute to be true or
false, and this is where the magic happens, the on-key-down function. It uses a ref so I can handle focus management
between here. To finish out our our tour, I have the child
list. Instead of being siblings, I moved it so it
is inside of that list item. That way, we don’t have to use something like
the controls, which, if you’ve read – so I opted to use HTML’s own hierarchy to
make that association. Then the child items for this stage one, I
just did the top level. When I handled the key events, I can hit handle
up or 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 add focus to the item.. if I go to this menu
now, it looks slightly different but you can play around with the style. The idea of the desktop menu, it’s not actual
links. It is is one-tab stop. I can arrow around, and now I can real reach
everything for this stage one. For stage 2, let’s check that out real quick. Let’s make sure we don’t have any changes. For stage 2, it got a little more complex,
because now I have to manage the state of two levels, so, for my first pass at this,
I had to add hooks for the number of item in both levels, I had to refresh this, and
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 tease top-level items and I can get to the lower level of items. With a little bit of refactoring I was able
to make this way more accessible than it was before. This is something I will probably contribute
back to the component, because, when you’re using components, you can really help other
people out by filing issues for sensibility, and, if you have the solution, contribute
it or suggest it in the issue before we have managed to make make some things way more
accessible than they were before. I don’t have slides. If you want to review what we worked on today,
you can check out my GitHub. I’ve tagged all the fixes in git tags. There are resources here. If you’re new to accessibility, need help,
get your team members on here, got some resources here. I want to, you don’t need to reinvent the
wheel with a lot of these interactions and components. You can check what is out there already and
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 relies on you to know how to make the components
in your app more successful with tips like I have in this repo but then test with peel
people – people with disabilities. See how they use your application. You might be surprise they stumble and hit
barriers. I hope I’ve given you tools and techniques
you can use to make your apps so much more successful. Thanks very much for having me. [Applause].

3 comments on “Empathy-Driven Development – Marcy Sutton – JSConf EU 2018

  1. Stoked to see a11y mentioned at more conferences 🙂 And the fact about IE11 being the most used browser by screen reader users is mind blowing! Definitely didn't expect that

Leave a Reply

Your email address will not be published. Required fields are marked *