Enhance accessibility in your Angular builds | Workshop

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] EMMA TWERSKY: Hi, everyone. My name is Emma Twersky and I'm a developer relations engineer at Google on the Angular team. And I'm super excited to be here today, talking about how to build more accessible Angular applications. So we're going to spend the next hour, hour and a half-ish talking all about accessibility and Angular and web accessibility. And I'm happy to answer any of your questions along the way. But to get started, I know there were some links sent out ahead of the time, but you can find everything that we're going to be talking about on codelabs.developer.google.com backslash Angular-a11y, and I'll throw that in the chat as well. And I'll throw that a few more times as I see people coming in. So that's we're going to head to get started. And so let's talk a little bit about this topic first, before we dig into some code. And I really want to spend the most time looking at actual code, asking questions about some common pitfalls and stuff like that. But just to back up before all of that, let's talk about why we should care about accessibility, right? So accessibility is super important for all web developers to know about. It really touches every point of the development lifecycle, from design to development to testing. Everyone needs to sort of have an accessibility hat on as developers and anywhere in that. And in fact, one in four US adults have been found to have some sort of disability that impacts major parts of their life. So you can think about that as obviously, there are some of the things we initially think about when we think about accessibility, so things like blindness or low vision, deafness, hearing impairments, motor restrictions, things like that. But it can also be things that are temporary, so things like maybe I broke my arm a few years ago and I couldn't type with one hand, and it made it much harder to navigate my job of how do I code with only one hand, especially if it's my left hand? Like, I can't do anything with my left hand. So I think it's really important to think about the fact that accessibility is really important for a certain part of the population, but it applies to everyone and we can all benefit from it. A great example of that is if you think about closed captioning, right? I have closed captioning on in this Google Meet, and if that's something you're interested in, I would highly recommend going to the Settings tab at the bottom and turning those on because sometimes it's hard to understand certain words that people are saying. Or I watch Netflix a lot and I always turn on my closed captions because sometimes I have the volume low so that I can be doing other things, or I'm vacuuming while trying to watch TV, right? And so while I was not the intended audience of that accessibility feature, I benefit from it. And if you think about that more broadly, adding accessibility to your web applications that you're building, especially in Angular, just broadens the impact that that website can have and the usability in general. So important from a web standard perspective, but also important just because it makes things more usable. So to dig in, today we are going to be building an application. I have all of the source code for you to get started. I thought it'd be fun and cheeky to do a dumpling shop. I love a good dumpling. Maybe throw in the chat what your favorite form of dumpling is. I am really into gyoza right now. There's a really good cheap dumpling shop down the street from my apartment. But we will be taking an application that I intentionally built without really thinking about accessibility in mind, and we will be addressing eight different pitfalls of things that I think everyone can go back to applications you're building in your daily life and add some accessibility in there. I'm also happy to answer any other questions about Angular. I work on the Angular team and I'm super excited about our focus on accessibility right now. So we are going to navigate to the next tab here, and can everyone see my screen? Is this large enough for y'all? Feel free to throw in the chat any questions you have, or if you need me to go back to a line of code or anything like that, I'm happy to do that. So to get set up, again, this link was sent out to everybody, but I just want to make sure. You're going to go to the GitHub Codelabs repository here on GitHub. You're going to clone my repository. I already have a fork of it. I see some other people have done that, maybe started-- oops, I'm not logged in in this browser. You cannot see that I in fact have started my own repository. But we're going to be working from this, so make sure to fork, fetch my branches, and we're going to be starting on the get-started branch. So in your local setup, I am assuming you already have Angular npm installed. You have everything up and running. But if you are struggling to do anything there, please make sure you can go to angular.io backslash start, and that will get started. So if you're having any dependency issues with TypeScript or getting the Angular CLI up and running or anything like that, this is going to be the tab to go to, and maybe just for the rest of the codelab, you'll just follow along and look at my code. But that said, we have our GitHub repository. We've taken our code. We've cloned it locally. And so I have my local version here. Again, just this Angular accessibility repository in my local. You're going to want to make sure you have npm installed. I've already done this, so hopefully it's all cached. Doo-doo-doo. And then I'm going to have ng served. So here we're just going to run ng serve. Again, I already had it once, but I'll do it again for you. And we're going to use the CLI to make sure that we can build our code. Look at some fun lobsters in the background. I highly recommend having a cool computer background to look out for while you're building. And the super exciting thing about this-- ooh, compiled successfully-- the super exciting thing about all of this is I'm doing this all in Angular version 13. So if you've been following Angular closely, version 13 has only been out for like a week. So maybe this is the first time you're touching version 13 code. Kind of exciting, kind of cool. I think everyone should give a little pat on your backs for that. We love an updated code repository. And this is what we've built, right? So if we go to our local host, 4200, this is our repository. And we are currently on, again, if I just check out my Git branch to go back to my terminal, I can see that if I do git branch, I am on the get-started branch. So make sure to fetch both branches. There should be two. get-started is where we're starting in our starting place and the Main is where we're headed. So if you at any point get lost along the way, you can always go to Main and all the code will be there that we're adding. And the other way to do that, just to give you that ahead of time, is that if we go to Main, we can see in our commits on GitHub that each one of the steps we're about to do are all an individual commit. So if any one of these changes somehow gets ahead of you, you can also just check out on a certain commit on GitHub. So let's go back to the codelab. We have our code, we've checked it all out, we feel good about it. Let's talk about this application. Besides being a dumpling application, I just want to take a look at what's there. So my photos are in dark mode. I'm going to do that so that my face is less pink for the light. But we have our shop, which is our main page-- also if you click the Home. And it has a bunch of dumplings so I can see what I'm buying. In my make believe land, the idea here is that I get to pick-- I can order up to 13 dumplings. So this is like a custom dumpling website. I know a lot of holidays are coming up. Maybe you want to order some really fancy, special dumplings for a loved one. So we get to pick what fillings we want in it, we get to pick how many we want. And then the super cool feature of my dumpling website, I've decided, is that you can also dye your dumplings to a series of rainbow colors. So for example, let's get some sky blue chicken and bok choy dumplings. And you can click Purchase. Obviously, that is not built out, but in our console, we are logging that in theory, we are purchasing these dumplings. We could send you to Shopify or something, right? If you want to know more about this make believe dumpling company, I have an About page. And then you can also find us. Again, it's a development mode, so you can't actually find us. We're located somewhere in San Francisco. I am also located somewhere in San Francisco, so I thought that was fitting. And we have generally good hours. It is actually after hours for us today locally, but that's OK, we're going to continue with our dumpling purchases. So besides that, if we look through more of what's going on, let's look at the accessibility of this website, right? So like, great. I built a cool, fun application. I think it looks kind of cute. But we recognize it's not accessible, right? Like right out of the box, there are some things that I feel like I could have done better to build this in a more accessible way. And this is what I really want to focus on today. So to start out by recognizing what we want to fix, there are two types of accessibility testing that I want to talk about today. There's manual testing, which is going to be where the bulk of your accessibility testing happens, right? So this is where I as a user am going to say, my designer told me that I need to be able to go to my website, select any type of dumping I want, click Purchase, and know that I purchased those dumplings. And that is a user flow, and I want to make sure that an accessible user using something like a screen reader could successfully do that. So if I was a developer, I would turn on VoiceOver, I would navigate, try and do that workflow, and make sure that it still works. The other type of accessibility testing is going to be automated testing. So this is where we use other tooling. For example, today, we're going to be using the Lighthouse tool in Chrome Developer Tools to run an automated check for other things. Now, the thing about this is we can't automate all accessibility testing, at least right now. Like something that's really important in accessibility is that when you are read the choices on a slider, that you understand what those mean. So there's a cognitive aspect of that. And computers are smart, machine learning is getting there, but we can't automate knowing that a user will understand what's being read to them. We can say a user is being read a sentence, and that can be automated, but does that sentence make sense is where the manual part comes in. If that makes sense. So to run our automated tests, we're going to go into our application again. We're going to go into-- if you hit Command-Option-J, we're opening the Chrome Developer Tools. Again, I'm working in Chrome. It's going to be a little bit different if you are using a different browser. And I'm going to go to the Lighthouse tab. If it doesn't show up there, then it might be just under these dropdowns and it's going to be one of these. You can see I also have the Angular DevTools. My favoritism is clear. And we're going to pick which ones we want. So for today, just for the sake of time, I've already run these reports, but we're going to pick Accessibility and then click Generate Report. Oop. And it looks like I'm going to have to do it again anyways. Cool. And it's going to run my report. Again, I just clicked-- I only selected desktop. You can also do this for mobile. Today we're just talking about the desktop or web accessibility, so for the sake of time. But there's some other cool stuff in Chrome if you want to do it. Anyways, so we got our report. We got 87. So that's not bad, right? Like, that's 87 points out of 100, right? 100 would be here. So we're doing pretty good. But we can do better. I want to hit 100. I'm a perfectionist and also, I want to make sure this works for everyone. And if there are things I can fix, I'm going to do it. And we see that we have some things highlighted here and we're going to add them to our to-do lists. Then the third type of check that we're going to run is linting. And so this is where in Angular, I'm using ESLint, and I'm specifically looking at the Angular ESLint rules to make sure that I can lint my code. So this is before it even compiles, like, are there things wrong with my code that I could have fixed? And so I have, let's see, one, two, three-- I have 10 different checks here in my ESLint rules. So if I go to the .eslintrc JSON file, I can see those, and I've set them all to 2, which means an error. Which means if I have lint checks on and I run linting, it's going to run an error. And see, these are the 10 things that lint can do. And this is even more than the usability of what's on the screen, so things like color, stuff like that. This is like, hey, this slider should have a role or something like that, right? So to do this, we're going to open our code. So here back in my terminal, I'm just going to run code and open this. Whoops. And I have it right here. And my code opens and I can go to, again, that linting file and I can look at my lint rules, and I can see that I have, again, 10 rules here set to those things for my ESLint rules. So if you're using ESLint, and these are also available in other linting, it's going to be the same set of rules. Just a slightly different declaration. For Angular applications, I highly recommend that you add accessibility check rules. So I have them here and that means again, when I go back to my terminal and I do ng lint, I can see my linter is going to run. It's going to say, hey, I'm checking your code for all these things. And there's an error. Right? And so the 2 here is saying I want to make these errors. I believe that they should be strict, right? My recommendation is obviously, if you're using a large repository, maybe introduce some as a 1 and that's going to throw a warning. 2 is going to be an error, and depending on your CI/CD pipeline, it's going to stop you from building. But we want that, right? We want to write the best code we can, and this is going to push us to do that. And so this lint is finding-- what's it finding? It's finding that any click must be accompanied by a key up, key down, or key press, right? So I have something in my shop component that I'm saying you can press or click, and I'm not actually giving any sort of instructions to it. And so we're going to fix that. So if I go back to my code line, those are the different ways we're going to test. So again, I've collected all of the errors here and I've collected my linting errors here. And so let's now go through each one and talk about the code, which is probably what you're here for. So we're going to start with maybe the largest issues and work down in granularity and see how much time we have. And I'm happy to answer questions along the way or at the end as we do this. We can also talk about coding best practices as we do this. So to start with, what I think every Angular developer-- if you're walking away from this, if you do nothing else, if you turn off the video right after you're doing this, I want to make sure that you are defining unique page titles. So single page applications, which Angular is, are super powerful, right, because the whole idea is I have one page. I have all these things, but at the end of the day, this is all one page. And I'm changing out components with a navigation, but really, this is one page. And that's super powerful for development. Most modern frameworks use this sort of architecture. There's a lot of really great performance benefits. It really is the modern web, right? This whole idea of a single page application. And that is so cool, except at the top here, if you see this, if you zoom in, it just says "a11y in Angular" or accessibility a 11 letters y in Angular. If you've ever wondered what accessibility and a11y are, they're the same thing. And that's great, except let's say I'm over here. And I'm using a screen reader and I'm like, hey, what's this tab over here? And I'm tabbing through my options. I don't know what this is. I just know it's accessibility in Angular. And there's different things in here. So let's say I have a store here, a description page. You know, that should be reflected here, because these are different things that we're talking about. And it's really inaccessible to have-- let's say I open up 10 of these, right, and I have different tabs that are on different pages. If I have a bunch of local host, they're all going to be the same no matter what I have open and no matter the status of them, and how are you going to tell the difference? So that is a huge pitfall of single page applications. And what we're going to do is we're going to use the router to define a page title. So in our routing module, we're going to navigate to-- in our code, I'm going to search for my TODO number 4, because we're on step 4, and I'm going to find-- oops. I'm going to find two files that I want to edit. OK. So first, we're going to go to our route module and we're going to look and we're going to say, OK, so I defined my different components. So if it's at shop, I'm going to load the ShopComponent, about, About, locate, LocationComponent. So pretty self-explanatory, right? That maps exactly to these three tabs that are three routes here. And because it's a different route, I want a different title, or I at least want to reflect my different routes in my title. So I'm going to add some data to each of those to define a title. So if I go back to my code, I'm going to add one additional thing here, which is my data. I'm zoomed in so much you can't really see all this. Hopefully, if I zoom out, that still works. And again, I'm just adding-- let's see, so this is going to be About. And then I have data again. I'm going to pass an object. I'm going to define a title. And what I'm doing here is I'm saying-- let's see, Locate Me dash a11y in Angular. It's hard to type and talk. So what I'm doing here is I'm saying, OK, I have a route. I can lazy load it if I want. And I have some additional data that I want to pass to this route, and then I want to populate-- I'm going to then go into my component and use that data to give a page title, right? And so the data I'm going to pass per route is the title I want. So I'm defining a data object. I'm using the key name title. This is just what I've named it. Obviously, you can name it something different. And then I'm going to pass this along. And something really cool that's coming in a future version of Angular is we actually are cognizant of this, and after I wrote this codelab, I helped our team define a way so that this will actually be known. So you're not even going to have to do this next part. But for now, what you're going to do is we've defined all of our titles. So we now know what we want to do. And then in our AppComponent, we now need to handle that title, right? So we're passing along the route. We're saying, if we're at this route, I want you to load this component, and I have a new title for you. And so now I want to change out. So if I go to my-- let's see, let me move these around. If I go to my AppComponent, once I save that, I'm going to say, I need a title. So I'm going to start out by defining just like a basic title variable, just so that-- oops. Let's see. Oh, I already have my title. So I already have my title. I'm just defining my basic title. And then I'm going to create a constructor that handles that title, right? So I'm bad at typing and doing, so we're going to cut and paste and talk about this code instead. OK. So what I'm doing is I-- oops. Let's do that. What I'm doing here is I've created a constructor that imports a titleService, right? And what I'm going to do in my titleService is I'm going to say, have a title. Oops, that's not-- OK. So I'm going to define a constructor. I'm going to create a titleService that holds a title. I'm going to-- again, I have my router and my activated route. And what I'm going to do is OnInit, I'm going to say, hey, can you get the title? And every time you get the title, what I want you to do with it is I want to take the router, I want to take the router and I want to pipe in and filter and say, hey, does my data have a title? Is the route that I'm at have a title? And if so, I want to give it that title. And otherwise, I'm going to default back to the title that I've defined here. And that's really all I'm doing. So if I see that and I go back. And I don't need that anymore. Oops. I can say oops even without changing it. So this is like a great example, right? I can already tell, without having to click on this, that it's working. And specifically, I can tell that I know what I'm at, right? So this is exactly what I'm talking about. It helps obviously for accessibility reasons, but it also helps me and I don't have any accessibility services turned on, right? So by using my router to define a title, I now know that this is open to the Locate Me tab. And that's super helpful. Again, if I have a bunch open and I'm looking for a specific one, I know that. Just to test it, we can click on Our Story and we can see it now says About. We can click on Shop, we can see it says Our Shop. And so we now know that for each of the major pages, we have a unique title service. So super helpful. If you're following along, feel free to give a thumbs up in the chat or maybe comment if you have used a different title name or some questions there. A common question here is like, OK, so what's a good title? Like, how do we differentiate, right? They're all dumpling shop. Why doesn't it say Dumpling Shop? Great question. It could. What you really want to reflect is whatever the difference is, you want to put first. So if you notice here, I said About dash Accessibility in Angular. But if we look up here, we see that I actually have a bunch of Angular Docs pages up, and this is a great larger example of that, right? Where we know that we're on the Angular doc so we have Angular dash, and then whatever the page I'm on is what's showing here. So let's say I have 400 pages of the Angular Docs up. It would be super annoying if they all said Angular. Like, that's super unhelpful. And so it's really easy to know, without even having to click into it, that here I'm on the Accessibility in Angular page, but here I'm on Get Started, right? Super helpful. So if you think about it scaling up to something like, again, the Docs page has what, something like 400 individual routes, it's really important that you're reflecting that information without forcing a user to go navigate to the page, then navigate from all of the navigation features into here, which is going to be something like 10 different tabs. Right? So that's a really terrible experience for people using VoiceOver or things like that, as well as, again, I don't use those in my daily navigation of websites and I benefit from it. So just doubling down on it's useful for everyone. So again, this is a really great code snippet for doing that. But you're just typing and filtering your routes. And I think it's quite fun to do. So that said-- that's going to bother me that these are not tabbed. OK, whatever. So let's do our next one, right? One check off the box. Again, we hit the highest possible thing. So again, if you do nothing else, go add this code snippet, think about your routes. If you develop in an Angular application for your work every day and you're thinking about something that you can do to impact the entire website, this is a great low-hanging fruit. Again, super small code snippet, big impact. So the next thing that I think has equally large impact is color. So this is one that our snapshot definitely found, right? So if I go to my application, I can see that it saw something with contrast. It said, hey, this contrast is terrible. And I can even test that and say, mm, is it, though, and use my Inspector and get to it and say, oh, it is. It looks like my contrast is 20%, which is far below the required amount. So let's fix that. Now, color contrast is super important because if you think about color contrast on the web, again, even if you are a partially sighted user or have users with low vision, this is going to be super impactful. If I have everything that is really light gray on black or something that has really low contrast, it's super hard to read that. So think about it. This screen right now has black text on a white background. There's really high contrast there, so it makes it really easy to read. But if I inspect this page and I change this to, let's say, color yellow, I cannot read this code blob anymore, right? So if I was trying to teach this or if I was trying to look through and I had to highlight it to create enough contrast to read it, this becomes completely unusable. So any work you did, like all the great typing you did. Let's say you maintain a really cool blog with a ton of really good information. If there's not enough contrast for people to read it, they're not going to be able to get all the information from your website. So in order to fix this, again, we're looking at this accent color that looks wrong. So let's go into our code and look at what that is. So here, we are going to look for TODO number 5. So in our styles.css, I'm using Angular Material in this application and I'm defining a bunch of color palettes with it. And so let me indent this to see this a little bit better. So it looks like in my light palette, which is where the issue was, right? So just for context, this pink red is our light scheme and this blue green is our dark color palette. So with this light, it looks like I have a pink and I have a default. And I have a lighter color and I have a text color. And it looks like what is wrong is-- let's play with this and see what is going wrong here. So again, I'm just going to pick a bunch of colors here and see where these colors are coming through. So if you saw that, with Angular Material, if you're not familiar, you define a color palette and you pass in those color palette variables. So if I go to my-- here, let's just do it. If I go to my Angular Material NPM node module and I go to my styles, I can see that in this palette, I'm exporting these color palettes. So I have a red palette. I think I was using a pink palette. And so with my pink palette, I can call on any of these variable colors to refer to these hex codes and they're defined by the Material organization, which is the design system that Google relies on called Angular-- called Material, and this implementation is obviously Angular Material. And so I'm using my pink palette. I have a default. I'm using A100, so that's going to be this color as my default. Again, that checks out. And then I think I have a lighter color, which is my 100, so again, I'm using these nice pinks. And then what I have here that's the problem is I have this text color, and I think it was-- yeah, it was 500. And so I was trying to say anytime there's text, I want it to be this. But it's going to sit on this A100, which is super close in color, right? Like I don't know if you can see these little squares without zooming in, but they're really far away from each other. So I'm going to use 900. I think in the codelab maybe I used something else, but I'm just going to change it to 900, because I think that's safe. And I'm going to save and I'm going to go back to my app and wait for it to build. And it loads. And yeah, there you go. So I can clearly see that now, right? That's so much more visible than it was before. And if I want to inspect it, let's check it. Ooh, looks like it still doesn't like that contrast. Ooh, that's not great. Let's run our Lighthouse check and see if it agrees. So again, let's see. I just changed that single variable. Ope, OK. So it's going to pass for our Lighthouse check, but it looks like maybe the contrast, here is a little less happy. So 50% is pretty good. I would say that is far above the ARIA recommendation. But it looks like since I wrote this codelab, Chrome has gotten a little bit stricter in its recommendations. So we could even say maybe I want to make it this darker. I don't have a darker color in my palette, but what I could do is make everything else a little bit lighter and see if that helps. So let's see. I could go to the 50 and just make it as contrasted as possible and see if that helps. Oh. Let's see. Yep. Now what's it think? OK. Yeah, so if I do something really drastic like that, I can see that again, maybe you can see this, maybe you can't. But if you're using your own Inspect Element, you zoom in-- I'm not sure I can zoom in on the pop-up tools. No, I can't. I am so sorry. But if you zoom in, you can see that really small there, the Contrast tab is saying Contrast 83% with a green checkmark next to it. So it's saying it's good with that accessibility. I'm going to go back to A100 because I liked that better and it passed our Lighthouse check. But again, just something you want to check out of what those contrast ratios are and if they're matching. I am using Chrome Canary, so I will say that a lot of the tools I'm using are experimental and maybe pushing the bounds of these checks. But there's a bunch of cool stuff in Chrome Canary that I think is worth it. So that said, we fixed our contrasting. So in general, what I would recommend in color contrast is obviously, I'm using a color palette, which is super helpful because anything with a design system, I'm going to make sure that I can define in a singular place everything is relying on this default color. And these three colors are sort of explaining to my entire screen what our colors should be. And the more you have color variables, so using things like CSS variables and making sure there's a constant singular source of truth for colors, make sure that if you've checked the color contrast in those colors that it's going to populate to your entire application. Something that you're going to want to do is when checking, you saw that I ran Lighthouse and I checked for the contrast errors there and that's where it was reporting it. And then you also saw that in Chrome DevTools, I used this inspection element and I was hovering over. So for example, here I can hover and I can see that this black on pink gets a contrast ratio of 59% and a green checkmark. Or maybe even down here, this blue has a pretty good contrast as well. So again, just using that hover and looking for the accessibility panel there and where it says Contrast is going to be the best way to quickly see and check for that contrast. So we've done two things now, right? So we've done our TODO for step 4 and step 5-- unique page titles and color contrast. From here on out, we're going to get a little bit more semantic. So we're going to dig into a little bit more code. And maybe these issues are less overarching, right? So page title affects your entire page. Color contrast affects your entire page. Now let's dig into some very specific issues. So the next one we're going to dig into is using semantic HTML. Semantic HTML, you might be thinking, why is this included in an Angular accessibility course? But the thing is, we're all writing HTML. Like, all of your Angular applications-- let's see. If I search for spaces and anything in an HTML file, look at all the HTML. Right? So we're all guilty of writing HTML. Sometimes we don't write the best HTML. And I want to make sure we walk away from this writing the best HTML that we can. So let's look at our next step, which is step 6. Now, step 6 is all about using semantic HTML. The idea here is if I have-- on this screen, for example, I have this thing here, right? It's like a big div and I click on it, and you can see here that I'm logging something. In theory, again, remember maybe I navigate to another page. This is a make believe land in which you can click this magical button and it purchases our dumplings for us. But when I click it, you can see that it's acting as a button. But if I inspect it, what it really is, is a div. It's a div with a click event and it's a div with an H3 with a click event, which really isn't making use of semantic HTML to include ARIA accessibility. So ARIA accessibility is capital A, capital R, capital I, capital A, and those are accessibility rules that we're going to give to our HTML to manage accessibility for us, especially when interacting with things like screen readers and those types of accessibility services. So when we don't use semantic HTML, we completely bypass the web's path towards accessibility for us and we essentially force ourselves to reinvent the wheel. And there's very few times, especially in something as small as creating a button, that it's worth saying, I'm not going to use the button HTML. I'm going to create a div and do it my own way. Better to use the button, right? Another example of this is on our Story page, you can see that I have all of this text. And if I inspect it, I see that they're all-- let's see. This is an H3, this is an H2, this is an H5, an H6, an H5, right? And so all of these H numbers that I'm reading out are headers. And typically, when you think about a page, it starts with an H1, which is your big title, right? So that's like Dumpling Shop, our H1, then we have some navigation items. And really, what should come next is an H2 and then an H3, and then maybe it could go back up to an H2. And what you're thinking about here is the structure of text, where each of our headers should be subsets of one another. So it makes sense that it goes from the largest header, so a header 1 or a title, down to our smallest, a header 6 and some text inside of that. The more we confuse that, the more we confuse screen readers, right? So screen readers like to read what level of header it is, and that conveys to our screen reader users where we are at within a text document. So if you jump from an H1 down to an H6 and back up to an H2, especially if you don't actually mean that in the context of it. So right, like if I look at this, "Who are we?" seems like one of the main questions. "How are we different?" seems like a question at the same level. So in theory, those should be our headers, and all of this information inside of it is probably detail information that should be at a lower header number to convey that to users. So those are both things we're going to fix. So again, we're going to fix our headers to have a semantic ordering, to use semantic HTML properly so that our screen readers can understand what's a header and what's description for those headers. And then we're going to go back to this Purchase button and we're going to make it-- well, we're going to make it a button because right now, it's acting as a button and it's not a button. And the way we can tell that, again-- I can tell you that because I've built this and I know that it's wrong, but I can also look at my Lighthouse and say, like, huh, in Navigation I have this thing that says "Header elements are not in sequentially descending order." And that's exactly what I just described, right? Things that are headings should be ordered properly so that people don't skip levels. Because if I'm navigating this, I'm going to skip through to all my H2s and I'm going to get some weird things read to me here. And then also, it's not complaining here because it doesn't know that it needs to be a button. But if I went through on a screen reader, which I'm not going to do because it is going to essentially try and screen read me out of this meet that we're in. But if I did turn on the screen reader by triple-clicking my Escape key, or you can go to VoiceOver preferences on your Mac or other device to figure out how to turn your personal devices on, and I navigated through to all of the options, the Purchase wouldn't let me click it. It would just be like, "Purchase. Div." Right? And we want it to say "Purchase button. Click Space to click." So we want this to be interactable on a screen reader. So to do that, let's look at our codelab to think about what we need to change. So our first thing is in our Shop component. Let's make this a button. So right now, you can see this is exactly what it was complaining about. And this is what our linting caught, right? So if I look here, it was saying, hey, in our Shop component, you're trying to click something, but nothing's going to happen, especially in a screen reader, right? This click event needs to be accompanied by a screen reader way for it to tell us what to do. So I'm going to take this code. I'm going to copy and paste it in my new button. I'm going to get rid of that button. It'll say my new button's better. And this is just a button. I'm using the mat-flat-button, which is a Material flat style button. I'm giving it a color of primary and I'm giving it some classes, just so I could style it if I wanted. And then I'm giving it that same click event, but now I'm going to [INAUDIBLE] the click event to a button. And the benefit here is using semantic HTML, it's going to compile, it's going to know to add ARIA roles and support to this, and it's going to be able to handle it for screen readers. So I can save that. I can go back. And I can see already the biggest indicator that that worked is do you see that when I navigate over, my mouse now can handle and shows that I can click that? And when I click it, there's an action? So just to show that difference again, if I go back to this button, when I hover over the old button, it looks like I just can select text. There's no indication with my pointer that I can actually click that or that anything is going to happen. So if I go back to my new button, clearly significantly better. The other thing that I was going to do here is I was going to change my headers. I'm going to copy and paste for the sake of time. But in my About component, which again is TODO number 6 we're on, we're going to replace all of these. It's the same text, but I'm going to replace them with semantic headings. So if you see-- here, let's look at the before and after. So if we look at the before and after, hopefully this is zoomed in enough for everyone reading my screen, you can look and see that before, we had H3, H2, H5, H6, H5, a div-- like, what's happening here? And now if we think about it, again, we have two H2s, the two questions we're trying to answer, and then everything inside of that is a paragraph. And we've added some styling so that we keep a similar cool, sort of funky stylistic look. But for screen readers, if people are navigating just through the headers, they can see that the two header sections I have here are my two questions-- what is the shop you're on and why is it different? And now everything else is identified as something less than that. If you're writing a blog, for example, a lot of people have blog apps in Angular, this is a great thing to think about. Do your headers make sense? Are they semantically in an order that makes sense? Are you using the correct semantic HTML tags, like p, like buttons, anything like that, right? A semantic HTML tag is literally anything that has meaning when you're going in your HTML and you're writing-- title, for example, is semantic HTML. So we have fixed that, and let's look at that. Doo-doo-doo. Did it reload? [INAUDIBLE] I think it did. Now if I go to our Story tab, it looks similar, but now we have two highlights. We have our two questions and everything inside of that is still styled, but it's more visually clear what the headers are there. And again, if I turned on my screen reader and navigated through my headers, I could see that. So for the sake of continuing to check our work as we go, we just did two things. We added the fact that this is now a button, clearly a button. I'm going to run my linter again because remember, when we did ng lint the last time, it got mad at us for that click event. And while it's linting-- yeah. While it's linting, I'm going to go back and I'm going to rerun my accessibility check again and I'm going to see if it catches that semantic change we made. Because this got mad at us for on our Story page the fact that we had those headers that didn't make sense. And look, it's no longer mad about this. So we're already into the green section. We've already fixed enough stuff that we're into the green 91, and we still have things to do. And if I go back to my linting, I see that all files are passing linting. So pretty good progress, right? Semantic HTML got us pretty far. It got us into the green, it got us to a fully passing linting file, and there's still things that we can fix. So again, if you are just joining us and looking for the repository, it is all linked within our codelab and we are now on-- we've now done unique page titles, we've now done color contrast, and we've added our semantic HTML. And now let's look at our controls. So the next thing we're going to fix is something that is Angular Material related. So if you look at our shop here, we have something that's pretty complicated, actually, especially for accessibility services. And that's the fact that we have nested controls. So for example, I have some fillings here that I'm focusing on. Let's just zoom into our fillings to focus on this. Ignore-- my dumplings really don't like to be zoomed in this aggressively. But I do for purposes of accessibility of you seeing my screen. So I have all my toppings here, right? I have meat and vegan. I don't eat meat, so I added Impossible burger meat. But if you do, you can order chicken, don't worry. And so I allow you to click all these things, right? And there's some cool stuff here where I can click Vegan and get both. If I unclick Bok Choy, it knows that it's not the fully vegan one. I can make some fun selections here, right? But nested checkboxes are really not the best practice for accessibility. And this happens a lot, right? This is a pattern maybe designers come to you with a lot for your different applications you're writing, and I would highly recommend you push back and think about, hey, I attended an accessibility workshop and I heard that this wasn't a best practice, and let me tell you why. So it is very hard when you're navigating through something like nested checkboxes with a screen reader to understand the nested complexity. So let's say I have everything checked and I navigate from Vegan into Bok Choy and uncheck Tofu. It is hard to then reflect to users without navigating back up that they've unchecked the Vegan selection. So when you have a nested structure like this that has nested use cases, it's hard to convey-- again, if I have navigated-- let's say I selected Vegan and I navigate to Bok Choy, then Tofu, then Meat, then Chicken, which is the correct tab order, and I get to Impossible Meat and I unselect Impossible Meat, you're going to next tab to Quantity and you're never going to be able to reflect to users that they've unselected Meat. So really not a great best practice. If there's a way to do this that doesn't require nested checkboxes, we're going to prefer that. And we're going to prefer that because it's more semantically sensical and we want things to be as simple to users as possible, especially for cognitive disabilities and things like that, but also because it's going to create a better UI. So even if I like look at this from afar, I don't really understand what's happening here with my Vegan versus Meat, right? Like, I mean, Impossible Meat is vegan anyways, so maybe that should be up here. But also, when I uncheck Chicken, is it really not a meat one because I still have some meat in there? There's a lot of questions you could ask there. And we've really made things more complicated than they need to be. So let's change our controls to make them more accessible. The other thing is that by simplifying menus, we're making them more navigatable, or navigable. And the other thing is that we're going to use Angular Material to ensure that the checkboxes we create have built-in accessibility. So this is where I do a subtle plug that using something like a component library is the best way to get accessibility, especially for Angular Material, which is Google's component library. And that's because we really care about accessibility and make accessibility a priority 0 or the top priority. So we want to make sure that we're delivering the most accessible components to you all. So if you are ever looking for, like, hey, I want to create some checkboxes and I want to do it really quick for my application and I need a scaffold, use a component library. Use Angular Material, because you're going to get accessibility out of the box. So in order to do this, we're going to replace our checkboxes with Material checkboxes. And to do that, we're going to go to our component and we're going to change how we add these things. So we are now on TODO number 7. I've marked these things just to make them a little bit more sensical for me. And we're going to go here. Oops. We're going to start-- yeah, we're going to start here. So in our shop.component.cs-- again, this is the component file where we are defining all of our fun things for navigation. And we are going to add our selectable controls. So we are going to change our fillings to be, instead of an object with a set of Boolean-- so again, this was maintaining-- the filling variable was saying, is this Bok Choy true or false? Is this Tofu true or false? And I was passing that to that checkbox. Now I'm going to have a list of strings, and these are going to be a list of options of what's out there. And in doing so, I've also leveled up our options a little bit. If you'd like to level them up to something you like that is different, go ahead. I'm super into chili crunch right now. There's a bunch of really good chili crunch in the local supermarket. So I have added some chili crunch as an option. I've also added some tofu. I kept the Impossible Meat. Eh, let's get rid of that. Maybe let's make it just like spinach, Extra Spinach. So I've changed my fillings to my list of strings. And then I've also created a selectedFillings variable, and this is going to maintain what is selected. And I'm going to keep everything else. And then now in my fauxPurchase, I also want to make sure to change how I print my fauxPurchase since I've changed my object of fillings to be a little bit different. So I just want to change how I select my flavor by going through-- oops. Why is it mad about this? Oops. There we go. Oop. Did I get that? Maybe I didn't. Oops. There we go. OK. Sorry, I'm just fixing my single quotes. Yeah, so I'm just maintaining that my flavor is going to be whatever is in my selected objects from my array here. So I've defined my array of fillings. I have four beautiful flavors. I'm maintaining a list of what is actually selected from my filling choices. And then every time I make that purchase, I just want to make sure that I'm iterating through that list and adding them so that when I print, it knows what to do. So now that I have a new list of what my fillings are, I want to go in and I want to change my object. And I'm going to use mat-selection-list. So in my component object in my HTML, I'm going to get rid of-- you can just collapse, even, this really long UL list. I'm just going to delete it. And we don't even need to look at how ugly that was. And instead, I'm going to add in a cool mat-selection-list. And you can copy this code all from right here, but let's talk through it. So my mat-selection-list is my Material selection list. This is a list of things we can select. I'm going to give it an ng model, which is going to be a model of what I have selected. I've handed it my selectedFillings variable, which again is a list of strings. And I've given it an ARIA label so that I can explicitly say, hey, when you get to here, this is a selection list of my dumpling fillings, and that's what's going to be read to screen readers. And then for each of my options, I'm going to ng 4 and iterate through all of the fillings I have to have a flavor, give it that value, some color, and just give it that text. If I select that and I save, this should be able to go here. And yep, it is reflected. So if you remember, we used to have some nested controls that didn't really make sense. I was doing that weird meat/vegan thing. And now I just have four checkboxes of some extra flavors, my extra spinach, new flavors of dumplings. So I've reinvented my dumpling flavors and I've made it more navigatable? That is a hard word to say. Navigable? So it's more navigable. It's also more cognitively intuitive for users to understand what's happening. You're selecting your fillings, you can select more than one, there's no nested dynamics of what that means. And they also have some styling. And they were also-- I was able to give it an ARIA control or ARIA label so that when it's read to users, there's context for what they're selecting. And so that's really great. So that was, again, this form doesn't have associated labels, so let's rerun and see if that fixes that. Yeah. And we're up to 98, right, and we got rid of that weird form error here, right? Because it was saying, you haven't given any context. You're making people navigate through these weird nested controls and they're selecting fillings, but fillings for what? There's no context. So now we've used Angular Material. We've used built-in components that have accessibility included. And we've used the mat-selection-list and ARIA label to ensure that we're providing context and a clear, more intuitive way to select these things so that when you're navigating through a screen reader, you're not getting stuck in a weird context hole of not knowing where you are. So we're at a great point. Let's just do a check. Again, that was creating selectable controls with Material. And let's just keep trucking on. It looks like we're at about an hour. We have halfway to go, so I'm going to speed up a little bit. But luckily, these next ones are pretty easy. So the next one is super similar-- provide controls with ARIA. So we've already talked about ARIA, but the screen reader isn't reading these slider values. And if I go to my Lighthouse score-- oops. Oh. If I go to my Lighthouse score, this is exactly what this is saying here, right? My input doesn't have an accessible name. This is an ARIA issue, and we want to improve our usage of ARIA. So what we're going to do is we're going to say, it's yelling about my slider. Very specifically, this error is saying this mat-slider doesn't tell me what it is. And without that, I'm going to get stuck in moving the slider and it's not going to tell me what it is. And a really simple way to do that is to use ARIA. So I'm going to go to my Shop component and I'm going to take my mat-slider-- whoops. And very simply, I don't even have to do any of these other things. I have all this stuff here. All I'm going to do is give an ARIA label. So in my mat-slider, I'm going to use aria-label and I'm going to give it some text that explains what it does. So here I think the example I gave was "Dumpling order quantity slider." Dumpling order quantity. And I don't even have to say slider, right, because it's going to read its role. So an ARIA role is already going to be applied on this to say that it's a slider. So it's even a better practice to not include that role, right? Like, I'm going to correct my codelab. A better use is to just say, when you think of ARIA, we need to read role, value, and then action, or description, value, role. And so this description here is "dumpling order quantity," its role is going to be a slider-- it knows that already. And then the action is going to be entering the slider. And all of that's going to be handled by the voice screen reader. So we've added that, and if I go back-- I've saved that, right? Yup. If I go back, I run, I think it's going to say 100% because I fixed it. Yeah, cool. So we're at 100%, which is great. And I'm going to push that even further, right, because why not 110%? No, really. So we're at the-- we've already fixed everything that is automated, and this is exactly where I say you can't automate all your checks. So this runs. Again, we ran our linter, everything passes there. We still have manual testing, right? We can still push this and say, I know that I've fixed everything that an automated check can fix, but I can still do more. So ARIA controls, color, page titles, those are all things that are automated. But there's more you can do, and so something that I'm really going to encourage everyone to check out is the CDK Accessibility Package. So this is where you're going to run-- oops. Sorry. This is where you're going to navigate to material.angular.io and you're going to go in and say, there's this thing called the CDK, and the CDK has something called Accessibility. And this is an entire package built for Angular-- and you don't have to use Angular Material to use this-- that is specifically focused on accessibility. So this has things like, there's list key management, because that's important, or FocusTrap-- we're going to talk about that. But there's all these tools for things that we recognize that when writing components, if you're writing your own components, you're going to have to manage these things. And there's an Angular-specific way to manage it and we want to provide you the tools to build better components so that if you're building an enterprise application or you're maintaining an open source package or something like that that has anything to do with a UI, you should know about this page. So again, material Docs, CDK, and the a11y one, accessibility. So to add that, we're going to go to our app module and we're just going to make sure that we've added this Accessibility module. So if I go to my app, I want to make sure that, again, I add this import. So I'm going to import it from the right place, and then I'm going to take my module and I'm going to add it to my imports. And actually, I like alphabetical or semi-alphabetical, I guess. Somehow these things have gotten slightly unalphabetical, but A comes first. So I'm going to import it. And now you're not going to see anything, but if I go to my NgTerminal, you can see that I just recompiled. It noticed that there was a new module it needed to bring in, and so it did so. And now we're going to make use of it, right? So what we did here is we just added to our module. If you're familiar with Angular applications, we added a new module that has the ability to ensure that we can make use of all of these things. So again, I'm looking at these Docs. I'm like, wow, there's some cool stuff in here that I want to use. In order to do that, we need to bring in the module. We just did that. Now let's go use the things. So 10, FocusTrap. I just talked about this, right? So I just said, hey, I notice here there's this thing. Let's see. There's list key management, there's LiveAnnouncer, there's focus monitoring, and there's FocusTrap. But what's FocusTrap? Well, the CDK FocusTrap or trap focus directive is a way for us to ensure that when we're tabbing through our elements with something like a screen reader that we're trapping the focus to where we want. So really great example of this is if we open our shop-- we've changed the color a few times, right? So we said, hey, I want five bok choy chili crunch tofu mushroom dumplings. I don't like this gold color of this wrapper. Let's make them plum. And this right here is a modal that I'm opening. And so if I was navigating with a screen reader, I would want to make sure that the screen reader knows when I'm navigating within this to trap focus before I apply color, right? So let's say I'm in a screen reader and I open my wrapper color, and then I'm navigating through this and somehow, I'm on this Home button up here and I'm trying to click it. That makes no sense, right? But for a nonsighted user or somebody who is using a VoiceOver service, you don't have the context to understand that you've escaped this modal that you're supposed to be trapped in. So the best practice is if a modal is open, focus should be trapped to that so that users can understand that there is an action that has to occur to navigate outside of that. Right? You're not really in a place to select fillings right now. You're selecting your wrapper color. So let's go with this nice-- we're going hot pink. So now that we have our hot pink five fun dumplings, let's look at how to add FocusTrap. And this is going to be super easy. All you're going to do is add the directive. So a directive in Angular, again, is sort of like a control that you're adding to something. And all we're going to do is use this attribute called cdkFocusInitial and add it to our Material context. Now, we're mostly just doing this to show what it would be like because, since we are using Angular Material, our focus is already going to be trapped. Let's see, where is this? On step 10. But in our color picker dialog, let's look at this. So in our color picker dialog HTML, we have a selection list again-- sounds familiar. But this time, we want to make sure that the focus is trapped. So all we're going to do is add cdkFocusInitial to ensure that we're focusing on the selection list when we first open the dialog. So when we open the dialog, we're not accidentally focusing on, again, this home page or our shop, because our focus really should be within this. If we think about our other mat-selection-list-- oops. Let's think about our other mat-selection-list-- this wouldn't make sense for using that CDK directive, right, because here we don't want to trap focus. Here, again, this list of fillings, once you enter this, you can navigate out of it. There's other things on this page. But here, [INAUDIBLE] on the page, right? So we want to add that directive. So if we go back, we've added the cdkFocusInitial directive to our selection list. And let's save. And again, nothing's going to actually show up for us, but in theory, we now know that we're trapping focus when we have that behavior. Moving on, step 11, we're going to do another CDK thing, which is using LiveAnnouncer. So LiveAnnouncer is the idea that when a change is made to the page, we want to reflect that to VoiceOver. So for example, a great example is again, I really like my color picker. Let's say I navigate through and I change to hot pink. Here, let me see if I can do it. Oop, did I do it? Mm. Well. Whoa. OK. Yep, VoiceOver does not like my meat. Anyways, so obviously, you can't hear my VoiceOver, which is why I'm not presenting it. But if I was to inspect and go into this module again, VoiceOver is going to read all of these things. And let's say I click light green and then I apply color, there is no notification to the user that that successfully happened. So let's say it failed, or let's say, like, I accidentally selected gold and I clicked Apply Color, and then I didn't know that I changed my color and I went to purchase them. We want to make sure that when a user exits this modal, they understand the selection they just made and they're notified of that change, because there's a visual change happening on the screen. So any time there's a visual change happening on the screen-- a great example would be, let's say I had a form and I tried to submit a form, and a bunch of errors happened. Obviously, there's a red error. The error message is red. But for people using screen readers, they're not going to know that all those errors have appeared on the screen because they're not highlighted, especially let's say there's like 10 errors. You can't highlight all of them. So the best practice is to announce those to the user. And there's a few different ways to do that. You can do that politely, you can do that more urgently, but all of that is going to be done using the LiveAnnouncer. So if you want to recreate that, there are steps to identify the issue. Again, I cannot have my screen reader read to you, unfortunately. But to fix this, we're going to add the LiveAnnouncer to our color picker. So we're going to go to our code. We're on TODO step, I think we're on number 11. Oh, where are we? Yeah. Da-da-da. Yeah. OK. And in our component, let's first make sure that we notify the change. So first in our dialog component in our constructor, we're going to change our constructor to have a reference to the LiveAnnouncer. So I'm going to copy and paste this code. I'm going to give it-- and I'm going to make sure that I import my LiveAnnouncer and some data. Oops. [INAUDIBLE] there you go. OK. Just wanted to make sure I imported the things I needed to. Why is it mad at me? Oh. OK. There we go. Cool. So what I'm doing here is I'm creating a constructor. I already had my dialog reference, but now I'm just injecting to make sure that I know what data is being selected from that color dialog data. So again, I want to make sure I know which color was just selected within my color picker component. And then I'm going to use this LiveAnnouncer thing. So remember we imported the module cdk/a11y? Now I'm importing my LiveAnnouncer from my cdk/a11y because I want to use it because I'm going to announce something. I'm basically a sports announcer at this point. And then I'm going to create a changeColor. Oops. Now I'm going to do one other thing, which is before I close my component, so before I use my dialogRef to close because I've made a color, if I've changed my color-- so not if I've exited, because I don't want to do anything then, right? There's no change to reflect. But if I change my color, then I'm going to go to my LiveAnnouncer object that I've already constructed from LiveAnnouncer and I'm going to use the announce API call to say I've selected a color. And I'm going to look at whatever color I have as an object and I'm going to make sure to announce that, right? And that's it. So it's the liveAnnouncer.announce. Super intuitive. If you're interested in this, again, I can go to the LiveAnnouncer docs. I can say, hey, there's LiveAnnouncer, and I can go to my API reference to make sure that I understand what is there. But look, my main method is announce. And now if I were to go and do that again, remember, any time I'm clicking a new option and I'm applying the color and it's emitting that change, I'm also going to announce to my screen reader "Select color hot pink" or "Select color green yellow," right, so that I can notify users even if you're not visually seeing a change on the screen that a change was made. So, cool. Now I've used LiveAnnouncer. We've done that. We can verify. And there's one last change I want to make, and then we'll wrap it up. And this one last change is one more thing in that cdk/a11y package, and this is HighContrast mode. And so HighContrast mode, I don't have Windows open right now, but it's a Windows-specific feature called HighContrast mode. I think that there are plans in the Chrome organization to do something similar. And this is the idea that you can change the appearance of all of your applications to dramatically increase contrast. So in HighContrast mode, very typically instead of pink and red and blue and all these colors on screen, it would just be white and black to create the highest possible contrast. So again, we already did, like, I'm checking all these things for contrast ratios. I'm seeing the 50s, the 60s. We want to make sure everything is essentially 100%, right-- is the highest possible contrast. This is great for users who may be prone to migraines. I have team members that use this because they get headaches if they look at screens too long, right? Like we all live in a world where we stare at screens all day. HighContrast mode is super useful for that. And those are disabilities, right? They may not be thought of in the same way as more typical disabilities, but they are just as valuable to ensure that you have an application that is thinking about those use cases to make sure that everyone is able to use the services you're creating. So HighContrast mode is super cool. Again, it's on Windows. And we have something cool, which is the high contrast mode detector in the cdk/a11y package. And so what you're going to do here is you're going to actually go into CSS, and this is super rare, right, that I feel like you can make accessibility changes purely out of CSS, especially that intelligently know that this thing happens. And so what we're going to do is we're going to import our cdk/a11y. You don't need the tilde anymore, if you're following along here. But that is a recent change to version 12. And then we're going to add some new CSS. So what you're seeing here is if I go to my Purchase button, I can add that when I have a cdk-high-contrast mode, which I'm detecting using, again, this import that I just made from the cdk/a11y, I now have access to a new mix-in or a new media query to say when cdk-high-contrast is on, for my button, let's use that as the use case and let's make it look really high contrast. So let's make the background color the lightest possible and let's make our outline super thick, so like the thickest possible. And we're just going to do the same for dark mode just to make sure that both themes have that because I think that's important. And now let's go to our application and see what that looks like. Oops. Ooh, why is it mad? OK. No. Hmm, I'm going to try and rebuild. A fun thing where rebuilding might save us. Or I will say, I got through 12 steps before I ran into an issue. So I think that's kind of impressive, all things considered. Yeah. Ooh, it does not like that import. Do not know why it does not like that import. Let's think about-- [HUMMING] OK. Well, I have something I can do. Remember how I said at the end, you can git checkout main? Look, I have all my changes. Oop, and that's why. So it looks like we've actually changed it. So you just import the CDK, not cdk/a11y. So I should go and change my codelab since that changed in version 13. So instead of this import statement, you're just going to remove that tilde and remove the accessibility reference, and this is all going to be within CDK. As part of the most recent version, we were more intentional about elevating how you import things like that. So if you're interested in that, feel free to tweet me if I forget to change the codelab. Bonus points. So yeah, you can see that in HighContrast mode, this would be applied, right? So cdk.high-contrast is how we're going to reference this. And again, I actually think this codelab is even more incorrect because cdk-high-contrast mode is for version 12 and below and we've now changed the reference to cdk.high-contrast, just if you're following along specifically. And main should reflect version 13's version of these things. The codelab just is version 12 and below, so I need to make that code change. But I did get to the very end of this codelab before I ran into this, so I'm going to take that as a success. So since I'm not in HighContrast mode, I just want to show what that would look like by removing that media query, just that you can see. And so that is a great example of what HighContrast mode looks like. We're still like using a little bit of hue because we think it's fun, but an even better practice would just be to make it white, right? Like the highest possible contrast. And we could even make this even thicker, right? So making sure that people have the highest possible contrast there. We can make the text even larger, something like that. But that is going to visually read as a very clear button without having any sort of visual clashing. Or like, this green could be really jarring on certain eyes. So I want to make sure to respect that in high contrast mode, especially for those users, by providing some styling specific to that. So again, this is a super cool mix and I think it's really cool that the CDK has the ability to find these things. And it's very cool to be a part of the modern web doing that. And with that, I think that we have 10 extra minutes, so I just want to say congratulations. So if we think about it, remember, we successfully-- oops, should not have that open-- we successfully went from a very inaccessible application to a completely accessible one, right? We ran Lighthouse to generate our score. Again, we did this a while ago. Pretty sure it's still going to be at 100%, but let's just do it to check. It feels good to give us some pats on the back for this. So yeah, so we got 100% there. Remember, we went linted with our lint rules that we added. Oops. I'll run it again just to prove how good we are. So we did linting. We used Lighthouse to check our accessibility. We also talked about how to manually test. And for those of you following along, hopefully you have checked out how to turn on VoiceOver and do these things. And then we went through eight different things, right? So we talked about why single page applications are great, but why we should think about unique page titles and how to add them, especially using the Angular router to do so, and then manage those routes in our app component at the highest level. We talked about how to check contrast ratios and add them, especially when maintaining a design system like Angular Material to ensure that-- we only changed one line of code, right? We just changed the color of the text to make sure that that was accessible, and the entire app suddenly was passing for contrast. We talked about semantic HTML using buttons, using headers appropriately. We talked about selectable controls and how to make sure that instead of confusing nested checkboxes, we were using a more intuitive, more cognitively dissonant version of these things. We talked about ARIA labels and how to add those to things like our sliders to ensure that we were defining the ARIA input so that our ARIA was meaningful, so that if I'm navigating this thing, I can successfully buy my dumplings. And then we also talked about cdk/a11y and some different things including FocusTrap, live announcing, and HighContrast mode in CSS. And so with that, you can count how many different commits you have, but feel free to again revisit this codelab if there were specific steps that were tricky for you. Feel free to open issues on the GitHub repository or tag me on Twitter @twerske. It's my last name, but instead of the Y, an E. And I'd love to talk about all these things with you. Yeah. And let's see, I know that the chat has been pretty quiet, but if you have any questions, now is the time to throw them. I know we have seven extra minutes, but I just wanted to wrap up and say thank you. Again, it's really cool to see people care about accessibility, especially with Angular. You have a huge impact by doing these things, so. Even just running the Core Web Vitals to see where you're at now and make little adjustments is a great place to start. Let's see. There was also a feedback link sent out in the chat, so please go ahead and add it there. And again, you can find me on Twitter. I'll throw that in the chat as well, because that is the easiest way to get a hold of me. Yeah, let's see. I see some questions. "Can you please help me with debugging with Chrome DevTools?" There's some really great resources if you prefer Chrome DevTools. If you even go to just codelabs.developers.google.com, there's some great codelabs there that are on DevTools. Yeah, let's see. Oops. Oh, OK. Well, I spelled it wrong. But if you spelled it right, you would get more. Yeah, so there's some great videos there. There's also some videos on the Angular YouTube for that. Debugging is a super broad question. If there's something specific to accessibility that you want me to answer, feel free to add that in the chat. "How is Angular's app architecture different from other frameworks?" Angular is super opinionated, but it's also-- it has a lot of solutions out of the box. So Angular, if we look at our application, each of my components, I have a very familiar structure where I have HTML, CSS, or Sass in this case, and then the component. And the component is where I have all of my logic. The Sass is where I have all of my styling. And then the HTML is where I have the actual structure of that. And that's going to be the same no matter what application you go into. And so it's super familiar, right? So really easy to onboard to a new application, even if you're not familiar with the actual code you're working with. And it also has all these things out of the box, so we have the a11y package, we have all these things, versus in other frameworks, you would be bringing in third party libraries. Which is also great, but just a different approach. So Angular sometimes is thought of as a slightly larger solution, especially for enterprises, but really what that means is instead of putting it on your hands to say I need accessibility, I need to go find an accessibility package and bring that in and make my app larger by doing so, we say, hey, at its core, you need accessibility. We're going to give that to you and we're going to say that it is going to be a little bit larger out of the box, but that's because out of the box, we also are giving you solutions to these things. Let's see. A recording will be provided. "Suppose I need business logic. Could you share-- you were only telling--" [INAUDIBLE].. OK, there's a question about business logic resources for debugging, it looks like. So Chrome DevTools is mostly for styling and visual changes, like all of these panels really are about debugging visual things. If you're talking about performance or things like that and you're developing with Angular, I highly recommend you download Angular DevTools, which does have things like a profiler where I can record my change detection cycles and then debug for performance. So-- ooh, let's stop that. I can see that somewhere back there, that didn't do so well. My app component was making sort of a costly change. So if you want to know more about this, we have entire videos about this. Angular.io backslash guide backslash DevTools. And DevTools would be a great way to start debugging for performance. For business logic, you're going to have to do a lot of that debugging yourself. Lighthouse is what I use. Oh, yep. We've talked a lot about Lighthouse tonight. But yeah, I just want to say, again, we have two minutes left, but thank you so much for joining. Again, feel free to reach out on Twitter. I know a recording of this will be sent out and you have all of the code to play around with. So if you're interested in any of the specific recommendations I made, again, the codelab is online and available at all times. [MUSIC PLAYING]
Info
Channel: Google Chrome Developers
Views: 508
Rating: undefined out of 5
Keywords: Chrome Dev Summit, Chrome Dev Summit 21, Chrome Dev Summit 2021, Chrome, Chrome Developers, Chrome Development, what's new in chrome, chrome development updates, Chrome developer updates, new in chrome, type: Conference Talk (Full production), pr_pr: Chrome
Id: juf_HneUbMk
Channel Id: undefined
Length: 88min 18sec (5298 seconds)
Published: Wed Dec 01 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.