 I officially hit 12 o'clock. Can everyone hear me, although in the back too? Yay, awesome. Thank you all for joining. I hope you're having a lovely time in Montreal. I'm super excited to be here. Today's talk will be covering scaling accessibility in the age of components. Who here knows what accessibility already means? Awesome. By the end of this, hopefully everyone will be able to raise their hand. So I'm Aisha. I currently work as a senior UX engineer at Optimizely, which is an experimentation software company. Some of you might use it. Some of you might be familiar with it. Before that, I was working on the Lightning Design System at Salesforce. Most importantly, I am dog mom to Pepper. There's a picture at the end if you can stick it out. And I'm also a proud musical theater geek. I spend a lot of time on stage singing and dancing. And I joke that this is my new way of getting on stage, even though I work in tech. So my job as a UX engineer at Optimizely generally covers four main areas. The first one is our component library. It's called OUI. It stands for Optimizely UI. If you're French, it just looks like wee. We also have a design system. The component library is obviously part of that. It also includes lots of documentation on how to use the different components and when to use something over another. It also includes accessibility guidelines and our color tokens. So I spend part of my job working on that design system. I also do a lot of prototyping. So I partner with our PMs and our designers. Whenever they have something either new or updated that they want to test with customers, I work with them to create a prototyping code, typically HTML, CSS, React, that they can use and put in front of customers before we start building. I also every now and then get my hands dirty in the front end code base. So I'll make some UI UX updates, especially if there are updates that need to be made because a component was updated. But throughout all this work, the underlying part is really the component library. So I use this day to day. A lot of our engineers also use it day to day. Our hope is that everyone is using it. But the other key part is also accessibility. So together with the components and the accessibility work, I try to integrate this even into something like prototypes because a lot of times prototyping code ends up being copy and pasted into our production code or it's a good starting point for our engineers. And so I try to ensure that even our prototypes are accessible so that we start thinking about it at a very early on stage and our engineers are starting to think about the accessibility requirements that they're going to need to bake in later. So given that my world revolves around components and accessibility, I probably understand the title of this talk. Today we'll be going over three different components and the accessibility win you can get by making a few tweaks to the underlying code. So we'll look at button icon and how this can improve the visuals of your application especially contrast. We'll look at inputs and what this means for screen readers. We'll get into a little bit more later. We'll hand a select dropdown, a custom select dropdown and how you need to do work for the keyboard navigation part of that. But before we get started, for those of you who didn't raise your hand, I just wanna make sure we're all on the same page about what accessibility entails. So the way I like to describe it is that I ensure everyone no matter their ability can perceive, understand, navigate, contribute to and interact with an application. Basically anything one person can do, another person can do. Doesn't matter their ability. It's also commonly referred to as A11Y because accessibility is kind of a hard word to spell, I appreciate that abbreviation. It's A11Y because there are 11 letters between the A and the Y. Now who benefits from accessible and assistive technology? A lot of times I think when we first think about this, we just think of the permanent column. People who are deaf or blind trying to use an application. However, the Microsoft team, they have amazing accessibility team and they've created these inclusive design personas that I think do a great job in basically giving an idea of, this applies to all of us, right? At any moment, any given moment, any one of us could benefit from assistive technology. You might be a new parent and you have a baby in one arm and you're trying to navigate an entire application with just one hand. Or you might be a bartender and you benefit from having captions on on the TV because there's no way you're going to hear the TV. One of my favorite examples of this is this detailed version from Margaret about vision, right? You may be blind from birth, in which case you might use a screen reader to interact with technology. Or you might have had eye surgery and suddenly you only have one eye at the moment. You won the other ones covered by an eye patch. You might also benefit from assistive technology. Ideally, you probably benefit from at least good contrast so that even with your one eye and it's compensating you can still perceive everything on an application. Or it might be situational. Has anyone here ever tried to work outside in the sun? And if a certain page has pretty low contrast ratios it can be really hard to see some of the items on the page. Or on the projector, right? Has everyone ever done the projector test where it looks fine on your computer and you put it up on the projector and suddenly everything's washed out? By improving contrast ratios we can make sure everyone gets to benefit. Secondly, component libraries. They are an amazing tool because every change you make to a component as long as your developers are using those components that change gets permeated throughout the entire ecosystem. Right, you can make one change, I can make one accessibility fix and suddenly everyone consuming that component also gets that fix. Super handy, it's an ideal world to live in. But it also means that every change gets permeated throughout the entire ecosystem. So you can also introduce a bug and suddenly everyone consuming that component gets that bug. Bugs typically get caught with tests. What might not get caught is an accessibility bug or an accessibility issue, right? If I make a change in a component that deters the accessibility, the unfortunate part of component libraries is that everyone else consuming that component is suddenly inaccessible as well. But with great power comes great responsibility and an endless opportunity to make the web a more accessible place. So if you have any influence over a component library you have a chance to scale the accessibility throughout your application just by making a few changes to the underlying components. So that's what we'll dive into today. To start with we'll look at the visual side of things. Is the interface visually legible and understandable for all users? For button icons in particular there tend to be three key problem areas. Focus and hover states, the contrast especially color contrast and titles. So who is familiar with this beautiful fuzzy blue outline that the browsers have introduced? All buttons and links, right? Browser default has some kind of focus ring. A lot of people call it. It's not the prettiest. Sometimes it's a little bit overwhelming or obnoxious. It's also always a certain color so it might not fit your brand. So how many people are familiar with this bit of code? Yeah, I've done this. I've done the button reset to outline none. I'm sure plenty of people in this room have also done it. It's no ill intent, right? It's just that we want to have a better solution. The problem is if we remove this we need to add something back, right? We can't just take this away and say, all right, we're great, all good. We don't have the ugly blue outlines anymore because now we've introduced a huge accessibility problem. Funny thing is that this was baked in, right? This was done for us in the browsers and now we're overriding it. So when we look at our button icons these are directly from OUI when they first joined. You might be wondering why I put the same button four times. The fun secret is that this is not the same button four times. This is actually a button in four different states, very different states. The neutral, the hover state, focused and focused and hovered. Now, I don't know about you. I can't tell a difference between any of these. I had a really hard time keeping the screenshots apart when I was trying to do this slide. I had to remember which order I had done the screenshots in because they don't look any different. There is technically a color change for the hovers but it's practically missing. Now, with a few fixes, I've darkened the difference between neutral and hover so the hover token is now using a shade, a couple of shades darker from our design tokens and instead of the outline, I've added a box shadow for the focus state. Now, these at least are starting to look a little bit different. We could go further, but this is a good starting point. If I'm looking at this, I can definitely see the difference between neutral and focus. This is a huge improvement and there's a discernible difference between when I'm hovering and when I'm not. Easy fix. Just a reminder, if you take off the outline, you need to put something back in in its place. Otherwise, people trying to use the application with keyboard navigation will lose track of where their focus is if they don't have a clear way to know exactly which element is currently being focused. So, the next bit, this was our button icon component. It's pretty straightforward. You pass in an icon name. We automatically filled it with one of our dark purple color tokens but we got a request for some more customizability and so we added a prop called icon fill. Its initial start was just a string prop type. You could pass in any hex value it would update the fill of the SVG used in this button icon. This is great. Gives people a lot of chance for customization. People are very happy, right? They can put any color they want. The problem is, they can put any color they want and there's no way to know that a certain developer has done the due diligence to make sure that this color would pass a contrast ratio against white. You can see my favorite go-to, ABC, ABC, does not by any means pass a contrast ratio against a white background. So, how do we improve this? How do we prevent the onus being on developers to know exactly which color would be a good choice? We created a little utility that looks at all of our color tokens that we export. We behind the scenes do the test to make sure that each of these color tokens passes the contrast ratio against a white background and now our updated prop type no longer takes any arbitrary string. It points to this map and it says you have to pick one of these colors. We also change the token names a little bit to be a little bit more human friendly so you don't have to remember base or blue dark. We just say default, aqua, green, orange. So now as a developer, you have to pick between one of these nine choices. Might seem a little limiting, but in reality this is actually a benefit for the designers as well and the aesthetic of the entire application because now we know all of our colors are actually being pulled from our official brand tokens, right? Now our application is going to look a lot more consistent throughout all of our button icons. So every time we have a green one it's going to be the same green instead of going across 15 different greens from every developer's favorite shade. And then for the accessibility side we can ensure that this icon is always going to pass contrast against the white. Lastly titles. I use these a lot, especially in something like the S code that has a lot of button icons and you're trying to figure out what all those different icons do. You hover over it and the little tool tip pops up and tells you ideally what this button does. Now this title is also used for screen readers. So if someone is navigating something with a screen reader this title is used to tell them what the button they're currently on is going to do. The code underneath might look something like this. If the person passes in a props.title we'll set that title attribute on the button itself. Now the key here is not making this optional. We're using the is required attribute of the prop types to ensure that everyone who is using a button icon is adding this title. That way that's at least one small sandy check we can make to ensure that everyone's got a title on their button icons. Quality of the title is up to the developer. That's where design system docs come in handy, right? You can say, okay, this shouldn't describe the icon. Like it shouldn't be paperclip. It should be attach a file, something like that. But that's where a component library in a design system work hand in hand. Now button icons are surprisingly quite tricky. Unfortunately screen readers don't have a standard way of handling the title attribute. You can't guarantee that that's going to work on a screen reader. So there are a lot of different options. I like using aria label. So that might look something like this. I don't want to require users to pass yet another prop. Plus if I had a separate prop for aria label and title they might get out of sync. They might be different. I don't need that. I can just use the same title prop for the aria label and the same way it'll be passed on to the component. Sarah has an amazing article on I think six different ways you can make button icons accessible. So I highly recommend checking out that article. They're surprisingly more complicated than you might think. All right, screen readers. Can users easily interact with the content on the screen without seeing it? Who here has tried out a screen reader before? A good set of hands, nice. If you don't, or if you haven't already known, all Macs come with voiceover. It's very easy to turn on. There's also JAWS. There are a couple different options, depending on what OS you're using, what computer you're using. But I highly recommend everyone here test it out at least once. It's a very eye-opening experience and gives you a very good sense of what it's like to try to navigate something without being able to see it. So looking at inputs, this is a screenshot from our storybook. These are the exported components we have for OUI. And when I first started, I thought this was a little odd. I thought it was a little surprising that we export both an input component and the label component. Now, the reason this is weird is because people start doing something like this. So here, API call is most likely a header for a section of information, right? But people are using a label component because in their mind, it's labeling this section, right? That's a natural conclusion to come to. The problem is this label component underneath is using the semantic label HTML element, which is always supposed to be used with an input. It doesn't semantically make sense to have a label without any associated input. So here, label is being used for its style and not for its semantic meaning, which is a really big accessibility issue. We wanna make sure that the components we're using, the underlying HTML elements especially, are used appropriately, and they apply in an appropriate situation versus this where they're being used just for stylistic differences. So how can we fix this? The result of having a separate label input, a separate label component was that our input component was very bare bones. The only required property was actually just type. What that means is if I turn on a screen reader and I go to this input, it's just going to read edit text blank. If I'm a screen reader user and I can't see this, I have no idea what input I've suddenly found myself in. It could be a phone number, it could be a password. There's no clue to me as a user to know what I'm supposed to be typing here. If we look at the underlying code behind this issue, we start to see the problem. This code was relying on developers passing in a label property in order to properly apply an actual label element. But if they didn't pass in this label, all we got was an input. There was no associated label for this input. A few quick changes for our input component. We require an ID and we require a label now. What this means is that in our code, we no longer have an if statement, right? We know a label has been passed and we say, okay, use the label component, this is the input's ID, this is the label's text, and render the input. What that looks like further down is that the label is properly using a for attribute that points to the input's ID and the input has that same ID. So this match, this for and the ID attribute, those two matching and having the exact same string, it is case sensitive, means that now my label's properly associated with my input. So if I were using a screen reader, it would say something like edit name. Now, a fun way to test this without going all the way into a screen reader yet, you still have to do that part. But if you wanna do a quick sandy check, you actually click on the label of any input and it should automatically focus you in the input. If it doesn't, that means the two are not properly connected. This also works for check boxes and radio buttons. If you ever click on the actual text, like the read terms and conditions, if you click on that, it should be checking the checkbox. And they do that because a checkbox is a very small tap target, right? If you maybe are not the best mouse user for whatever reason, it can be very hard to be very particular about where you're clicking. By making the label an access point for that checkbox, you make it a lot easier for users. This is just a quick way to ensure that those two attributes have been connected properly. The last change we made was actually removing our exported label component, right? We no longer want people using this willy-nilly. We know it's associated with inputs, so it's going to be used underneath the surface in the input component. Developers never have to worry about it. All right, last section, keyboard navigation. Anything you can do with a mouse, I can do with a keyboard, vice versa, right? I shouldn't need to use my mouse in order to use an application. So many times we create customized select dropdowns. So there is a native select element that uses option children. This gives you kind of a default look. Sometimes you need to go beyond that. You should have a very good use case for going beyond that. You'll see why in a second. But if we are creating our custom select dropdown, there are a few things we need to do to the markup to make sure it works for both keyboard navigation and screen readers. For example, the trigger needs an aria has pop up to true and aria expanded to true or false, whether or not the dropdown is showing or not. The containers surrounding the options should have a role of menu and each item should have a role of either menu item or placeholder. Placeholder is used like if you have a heading for a certain number of options and then you have another heading, those headings would be placeholders. We also set tab index equal to negative one so that we can programmatically focus on these items without introducing them into the tab series. So you shouldn't be able to get to them with a keyboard but this lets us give a kind of faux focused state, if you will. This is an example of all the extra markup you need to add and then we have to go a step further. Now when you interact with a select dropdown, especially the native one, you can trigger the dropdown to show by hitting enter space and then you can use your up and down arrows to go through the different options and then hit enter to select something. Now all of that is given to you by default at a box for free if you use the actual semantic select and option elements. If you're rolling your own version, you don't get that because why I emphasize have a very good reason for making your own because it's extra work. This is a bit of a pseudocode as an example. You need to be checking the different keys being pressed and see if it's something that you need to react to. If I'm hitting the up or down key, I'm going to stylistically maybe add a class that helps the user know, okay, where is my faux focus? Which one am I currently on in a sense? Same for escape. If I hit the escape key, I expect the dropdown to disappear. This is all stuff you have to wire up yourself if you're going to roll your own select dropdown. So this is my plea to you all to use a semantic element if it's present and if you don't need to build custom things then don't because it's definitely a lot more work. So given all of this, what is the big picture? These were just a certain set of components that I chose to talk about. We have about 54, maybe almost 60 now components in OUI. There's a lot of different things I could talk about. I could go in for hours. But I'm hoping that some of this will be relevant to whatever you're working on so that you can help create accessible technology. So my number one tip is start with your most used components. When I first started at Optimize.ly, I was looking at this list of about 60 components and wondering, okay, all of these need accessibility help. Where do I start? And my takeaway was let's look at what's most used in the interface, right? We use button icons all over the place. Many applications do because they're a great space saver, especially if we're doing editor type stuff. Taking up full length buttons with text every time might not be an option. So a lot of times we rely on button icons. Those are very prevalent in the Optimize.ly UI. Same for inputs, probably very common. Ours is very form based. There are a ton of inputs that you fill out on a regular basis. If those inputs aren't accessible, it's very hard to complete a standard workflow in Optimize.ly. And same for select dropdowns. We have custom select dropdowns, especially ones that we use for setting your project type or navigating. And trying to take any basic workflow with just your keyboard was very hard because our select dropdowns had no way of being keyboard accessible. So you never had a way to choose your next thing. So you're basically blocked, you're stuck. My recommendation is look at what is in your UI most often and see what gives you the most win for fixing. Second, make it easier to do the right thing. So as we saw with button icons, we can take the pressure off of our developers and move it onto the component itself. Do they need to worry about whether or not a color is passing the contrast ratio against white? They shouldn't have to, right? They should just be able to say, okay, I need, this is green because it's representing something maybe successful. I'm going to use the green fill, right? This makes it easier for our developers to create accessible UI without maybe even knowing that they're doing it. Some things shouldn't be flexible, like inputs, right? We don't want the flexibility of people using labels wherever they want. We need to control some things in order to ensure that we are keeping accessibility top of mind. This is also a great learning opportunity if people start asking you, well, why don't we have a label component? You can explain to them. They can learn that, oh, labels are always associated with inputs, so we've baked it in. Making that property, the label property required, is also a great learning moment. If people start wondering, oh, why is this label required? They might go look into the code and see what it's being used for. And lastly, good things take time and effort. Great life advice, really, it's not just for components. But as I was looking at a huge list of components that needs to be updated, I recommend tracking it against effort and impact, right? How much impact is this going to have and how long is it going to take? How much effort is it going to take to fix it? Some things might be huge impact and very low effort, like the button icons. I think that's a very large impact across our application because it's used so often, but it was a few lines of fixing, right? Pretty simple, versus select dropdown. Select dropdown also has a huge amount of impact because it's used so often, but it's also a lot more work to make accessible. So by kind of plotting these different components, you can get a sense of, okay, this is where I start. And hopefully by intentionally creating these accessible components, you can start to see the impact across your organization. Even if it's not immediate, just by giving somewhat similar presentations to this, I've had developers come up to me whenever they are creating new OUI components and start asking me, what do I need to do for accessibility? Is this accessible? How do I test this? What's the expected keyboard interaction? So just talking about these things and starting to build them out, introducing accessibility linters, it's a great way to start building out this accessible culture. A few resources. Marcy Sutton, really famous within accessibility world, especially, recently gave a talk at Clarity and introduced me to Fable and AccessWorks, which are amazing services that let you do usability testing with people with disabilities. And so if you work at a company that doesn't have anyone who natively uses a screen reader, this is a great way to ensure that you are truly meeting all the requirements and making it an enjoyable experience for someone who relies on a screen reader. The A11Y project is a site you can go to, has an amazing checklist. I've covered a few things off of their checklist, haven't gone into full depth just for the sake of time. So I highly recommend checking that out and reading over and learning what it means to be accessible. My biggest piece of advice is to use other design systems and component libraries. Don't reinvent the wheel, right? If you're gonna start building a date picker, my advice is don't build a date picker. Just don't do it. There are dozens out there, there are accessible ones. Airbnb's React dates is what we ended up using when we needed to build a date picker because the last thing you wanna do is try to make that picker keyboard accessible. There is a lot to it and screen reader usable. So many different things you have to take into account. It is not worth trying to do that yourself. So if there is something out there that you can use, start there. The very first starting point should be the semantic HTML elements that already exist. And then go from there. If you wanna learn more or come say hi, find me at the breaks or reach out on Twitter. If you wanna join me in building out accessible products, you can check out our job openings page. And with that, the promised pepper picture. Thank you very much.