![Accessibility in JavaScript Applications](https://static.frontendmasters.com/assets/courses/2019-08-28-javascript-accessibility/thumb.webp)
Check out a free preview of the full Accessibility in JavaScript Applications course
The "Coding a Progressive Enhancement Component" Lesson is part of the full, Accessibility in JavaScript Applications course featured in this preview video. Here's what you'd learn in this lesson:
Marcy creates a component that is prepared for a lack of JavaScript in the browser, and then builds the course website to show the visual and source code differences between the page with and without JavaScript.
Transcript from the "Coding a Progressive Enhancement Component" Lesson
[00:00:00]
>> Marcy Sutton: So for a progressive enhancement demo. Because Gatsby is doing this automatically, I have to go and do a little bit more if I have interactive things that I want to fall back more gracefully. So an example would be a tab switcher or a menu, something that's really interactive and maybe it's collapsed by default and you need JavaScript to open it.
[00:00:23]
Those styles, like if CSS loads but JavaScript doesn't, that widget's just locked up and no one can use it. So instead, if JavaScript's disabled, what if it's just expanded by default? And that's just where I start with. So you start with this accessible base line and then layer on top.
[00:00:40]
But with Gatsby, that's kind of not as intuitive. So in talking with the team about how they would approach this, I came up with a pretty good pattern. So I'm going to go and implement this. Let's go back to our app. I have this section called Enhanced Tablist.
[00:00:58]
And it is blank right now cuz I'm gonna go and write the bare bones like basics of how to actually override what Gatsby is compiling by default. So I'm gonna go into this enhanced tab list. It is pulling in the sort of shell of a component called Enhancing List.
[00:01:17]
And I'm gonna pass in a number of items. So the sort of conceptual basis for this component would be a tab switcher that starts out life as just a list of content. And so I'm going to go start that in the components area. So I've got this TabList in here, and it has a little bit of stuff in here by default, things that I am really interested in.
[00:01:44]
So this TabList, it's using React State and then useEffect. So we used the useEffect Hook for things like sending focus to the first item in the drop down. Sending that like click outside listener. In this case, when the JavaScript downloads and executes, it's like, I have a handle on it, now I have client rendered environment.
[00:02:07]
Okay, now I can enhance things. Interesting. So if I use this useState Hook and useEffect, I can go in here and do a little bit more work to actually change how my layouts render. Okay, so let's start out here by adding an unordered list, and this might be the markup that gets transformed into something much more interactive later on.
[00:02:33]
But I can go an use this logic. I'm gonna spread the isClient state variable. And this is a really interesting trick that I didn't know about before. I can say, if it's the client, I can go and add an aria role. So I'm gonna add a role of TabList.
[00:02:55]
This is only going to be added in the client JavaScript part of my app. So if JavaScript is turned off, this is just gonna be a regular owner list. Because if I'm adding aria roles and aria states that required JavaScript to operate, and then someone turns JavaScript off and turns on a screen reader, they're gonna be like, why is this thing called the TabList when it's not interactive.
[00:03:16]
So, that's why I'm making these changes. So I've got this list. I am going to iterate over the items. So the items that I was passing in from the page where this is called, I'm gonna say items.map. I'm gonna pass in an item, and that needs to go inside the parentheses.
[00:03:40]
And I need to close it.
>> Marcy Sutton: Didn't do this right. I'm gonna back up. So I normally put this like that. Okay, still need closing paren. I feel like something wrong here. Okay, it's because it just needs to be a paren, not brackets, okay. Now, I've got my map function.
[00:04:06]
Okay, so I'm gonna go in here and do a really similar thing. I'm gonna say li.key, because I'm iterating over these items. And I need some sort of like a unique identifier or reaction that will complain at me. So I've got this list item here. And I'm gonna do the similar spread of the isClient state variable.
[00:04:31]
And I'm gonna do something, actually I need to do this on the list item itself. So I'm gonna move this carrot and I'm gonna say role of tab. So this will dynamically change what role, and I can add aria here in a Gatsby environment, when otherwise it's kind of abstracted away from me.
[00:04:53]
So item.label is what I'm gonna get from this component. Let me see what else I missed.
>> Speaker 2: Your items is dot map. It has a opening curly burst.
>> Speaker 3: A closing curly burst after the right parentheses.
>> Marcy Sutton: Here we go. Now, still not right. I need another closing print.
[00:05:14]
Okay, yeah, I'm in this JSX environment, and the way that you kind of toggle between dynamic code and code that will output as HTML like this ankle bracket UL is to use these curlies. I think we're just getting in a part of the day when it's kinda getting hard to do it all.
[00:05:32]
[LAUGH] So thanks for sticking with me. So I've got this item. It's iterating over these times. It's got a label in it. And that's pretty much all I'm gonna add here. I just want to see it add these roles and turn things on and off. So I'm gonna do something super interesting and hope the demo gods work great here.
[00:05:53]
I'm gonna do Gatsby Build. Actually gonna do a Gatsby Clean first cuz I'm using Gatsby Themes, and those are MPM dependencies. So I need to blow that away sometimes. So Gatsby Build and Gatsby Serve. I'm gonna build it and it's going to compile these web like this into an actual static site, that if I turn off JavaScript, the pages will generate.
[00:06:16]
And that's what I mentioned earlier how Gatsby Develop and Gatsby Build differ develop when you turn off JavaScript, cuz its development mode like you don't need to build all that every time. But when you do run Gatsby Build to deploy it, that's when you get like full HTML static pages.
[00:06:33]
And then if JavaScript is available, it will execute client side scripts. So I'm building this right now, and then I'm just gonna serve it in the browser and go turn off JavaScript. Will toggle it on and off and see what effect that had on this little component. It takes a little bit longer to build this, so maybe that'll paint the picture of why developed mode is so useful.
[00:06:57]
So this is the same site, just running on local host 9000. And if I go to the enhanced TabList, so it's like really straightforward markup, just to show. So here's our role RUI, role of TabList, and role of Tab. So if I was making this into a full accessible tab switcher, and I wanted something that worked without JavaScript slightly differently, these are those hooks that I could use for that.
[00:07:23]
So I'm gonna go to Chrome settings. I gonna go turn JavaScript off in my Advanced. They really don't want you to turn JavaScript off do they? So JavaScript, turn it off. Let's go see what's happening here. That's 8000. I need 9000. So I'm gonna go inspect this markup again.
[00:07:49]
And it's just the regular straightforward, unordered list. And if I do, if I look at the view source, there's a bunch of HTML. It's all minified because that's faster for performance. So it might not be super human readable but this is for machines to read not for humans to read.
[00:08:09]
I think that's fine. You could use a purifier if you really wanted to read it. Dev Tools is fine in my opinion. But if I go over to the local host, the develop mode, it's a lot shorter. So that's fine for development mode. If you're doing things for progressive enhancement, this does give you the control to actually change what is output, which is pretty awesome.
[00:08:33]
I had for other JavaScript frameworks it's always like a whole system that you have to figure out, and then it gets might be customed to every application. And this API, I find to get this sweet spot in between like supporting progressive enhancement and static sites and doing something really interactive.
[00:08:54]
There's a lot of potential here. So we've got that working. Here's a the noScript I mentioned earlier. So if I inspect that, this is a noScript element that just works in the browser. I didn't have to do anything for that. So that's how that works. I'm gonna go back to view as code and I'm gonna clean it again.
[00:09:19]
>> Marcy Sutton: I think it didn't matter this time. So the reason I have to clean is because when I deploy, I'm using this thing called prefix paths. So it actually builds the site with a path prefix. So in GitHub, it's the name of the repo, and that's a difference from how I'm running it locally.
[00:09:36]
And so sometimes you might need to clean the cache. Little bit of back story while we're getting this development mode back up.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops