 Hi there, my friend and friends. Tabs are one of those things that are pretty ubiquitous around the web, right? We see them all over the place, you know, whether you're shopping or something, they're always in like these types of sites. Big box stores absolutely love tabs. We get these style ones. You're on YouTube right now watching this and YouTube has its own tabs along the top here that you can go through. We have different types of tabs too. These you don't always think of tabs, but like these vertical ones are tabs as well that we can use. There's even these types of like carousel slash tabs where it's like a tab system that automatically runs, which you know, it already to me, if you're cycling through something, maybe it's a bad sign that you're trying to get through information and sort of force the user through things. It's like I'm totally aware that you often need to build tabs. You might be asked to build them or something like that. But before we get to actually looking at how to do it, I do want to say that like, they're not the most user friendly thing that you can come across on a website. So if you're creating a project and you decide to put some tabs in there, maybe stop for a second and think, do I really need to include tabs here? They hide information away from the user. You know, that's why we have to sort of cycle through them and let those auto playing ones were trying to make sure that the user sees that there's more stuff there, just like a carousel is hiding information away. They can be kind of awkward to use sometimes and not super straightforward. You might not even realize that they're an interactive element. They hide information from the user, which is why those auto playing ones are trying to like make sure that you get through all of the content there. They can even be awkward to use depending on how you're interacting with them. And in general, they don't actually add any value to a site. And one way I just want to sort of highlight that is this example here. We saw this when I was just looking at which is from a big box store, Canadian Tire here in Canada, where it's this lawnmower. And you can sort of, you have these tabs to go from the features to the specifications to the resources. But then here is another big box store that's selling lawnmowers, and it looks like they have a tab system. But if I go to overview, it brings me to overview. I go to specifications, it brings me there. And if I go to reviews, it brings me down to where the reviews are here at the bottom. A little bit different, but the overview and the specifications is basically the same thing that this one had, right, features and specifications. But this one, if I'm just scrolling down the page, and I don't stop to look at these, I can still get all of that information. And that's one wonderful thing about the web is we can scroll through it. We're not limited in the amount of space that we have. And so I do want you to stop and go, Do I really need them? Is there an actual benefit to having this as tabs? And the answer is probably not. But I'm also going to say that if you're watching this, maybe you don't have the choice here. You've been tasked with creating tabs, you have to do it, and you want to build it the right way, or at least try and build it the best way possible. So that's what we will be looking at in this video. But if you do have that power to not have to bother implementing them, maybe that would be the better choice. Just want to really preface that strongly at the beginning. But maybe you've been assigned tabs on your latest sprint, or your designer has handed you a design and he's won't budge on it. You need to make some tabs. And that is that. So let's dive in and see how we can do it. So let's jump into this, which is what I'm going to suggest that you start with. And for this video, I'm going to be doing a little, we're going to break down code a lot more, and we're going to sort of build it step by step. But I'm not going to write it all from scratch, just because I think it's going to go a little faster and be a little bit more clear this way. And you'll see here, I have my tab, I have a div of tab container that I have here at the top that's going down all the way down to here. And inside that tab container, I have a few different things. We're going to break this all down. But the first thing is I have my list right here. And then I have all my panels after, and you'll notice I'm using a list and I'm using links. And originally when I was first creating this, I was building this with buttons because I'm making an interactive element. And so buttons made more sense than links. But then after talking with Hayden Pickering, who gave me some very great advice for helping me come up with this, so I'll link to some of his stuff down below. I'd strongly recommend you check it out. So what this creates right now is something like this. And we don't really have any CSS organizing this. I just have some very basic style sheets changing some colors and stuff. But what that means is this first advertising one is just a regular link. So if I click on advertising, it brings me to there. We could even make this a little bit better possibly by highlighting what became targeted. I go to socials, we go to the social one and go to marketing. It brings me to each one of the paragraphs or the bit of text that's associated with that. We are going to be adding JavaScript to this. We're going to be making this a full tab system. But the idea here that we're going to be doing is doing it with progressive enhancement. And so if JavaScript doesn't load for whatever reason, the user has it turned off, who knows what it is. This is fully functional. And this sort of harkens back to that one of the Home Depot, which I actually think they did a decent job with that making it link to each section instead of hiding the content behind tabs. Because the other thing you have to think about is if you do have content in tabs and someone wants to like link to something within the page, but it's in a tab, how do you even do that? And there's a lot of, you know, the deep linking there can be very problematic. It's a lot of JavaScript to solve that whereas here the content is all exposed. So I'm just throwing a few things out there, again, just saying, do you really want to have tabs? But yes, you do. You're here. You're following along. So you definitely want tabs. So I have all of these set up here. And then in this next section, I have these tab panels. So I have one div tab panels. And then inside of my tab panels, I'm going and just making an individual one for each, I haven't given these like a tab panel class, you could definitely do that if you want. But I just have my tab tab panels. And then inside each one of those, I have the div and inside, you know, that's in this case, I just have a paragraph, you could put whatever you want in there. But the important thing for now is we have the links here. And these are just the href that are anchoring. And then I have the ID on each one of those right there. The other thing I have done on this is this UL is area labeled by the tabs title. So how can our company help you is the title for these tabs? And then we get that down there as well. So just add a little bit of extra context that if somebody gets to this list, they know what the list is about. But also once this turns into an actual tab system, they know the purpose of these tabs, it's giving us information about how the company can help us. And now I'm not actually going to style this up to look better in this state. But you could definitely add a little bit of styling just to make this a little bit nicer if you felt like you wanted to. And we're going to see that we could actually easily have two different styles for all of this. Because I'm going to be building all of my styles for the tabs, assuming that the JavaScript is working, even though it's only being done with CSS. And we'll see how that's going to work as well. So I think the very first thing we should do in this case is actually get the tabs working to like hide the content away, get them working. So when we click on the links, we're going to expose the correct paragraph or the correct tab panel. And then once we've done that, we'll actually style them up and make it look more like an actual tab system. So I'm going to jump on over to my JavaScript file here, which has nothing in it. And we're going to start off with a decent little chunk of code right here. And you'll see one of the problems that I had from the beginning, but we'll shrink this down just so we can see everything on the screen at once. And here, so I'm doing a const of my tab container, my tab list, my tab buttons and my tab panels. So we have a variable set up for each one of those. And we just have my tab container, we have the ul. In this case, I'm just doing ul and a little bit dangerous to actually do that. So you could come in and either give this ul a class or an ID to actually target it properly. I just have these as the regular links here. But again, a class on those that you could decide it could be your tab button class or whatever you want. Just to make those a little bit safer. I'm doing silly demo land. You're probably working on a real project. So you have to give that a little bit more thought than I had to worry about for my class naming. And then here in the tab panels, this you could definitely do. You know, you could give each one of these a class of tab panel, like I mentioned earlier, but I don't see any problem in doing something like this, where we can get our tab panels without having to worry about it too much. We have the tab panels, then every div in there will just be a panel. For me, that's straightforward. If you like a direct class on each one of them, go for it. And then there's this part here. And this is the part that's sort of setting the stage for what we're going to be doing, which is we're going through our tab buttons. So let's go look here, we're going through each one of the buttons. So we have four buttons that are here are my four links, which are my tab buttons in JavaScript land. And for each one of those tabs, we're going to grab the tab and we're going to grab the index. And index here is just it keeps track of the index. We have zero, one, two, three, for each one of them. And I've put this here for now, because we will have to build some stuff into this, but we're saying if the index is zero, we're going to do some other stuff later. But for index zero, we're not going to worry about it. But for all the other ones, we're going to do a set attribute hidden. And you'll notice that this is actually changed. And we have only one paragraph showing up now. And if I take this off and hit save, we have all four of them. So the hidden class is going to hide it visually. And it's also going to remove it from the accessibility tree. So that's no longer there. So if we come and look here, we'll see them here, but we have the hidden attribute that's been added to all of those. This is I'm assuming you always want your first tab to be the active tab when the page loads. If you wanted a different tab to be your active tab, you'd have to find a different approach here. But this is just assuming that the first tab, I think every site I've ever been on that does use tabs assumes that that it is assuming the first tab is going to be the active one. And this is probably the easiest way to do it. And we could definitely do this in a little bit of a different way. But since I want to be doing other stuff here as well, doing the if else here makes sense for me. And before we worry about all the other stuff that we might be doing here, what we want to do now is we've hidden away content. And if I click on one of these links, I want to make the content related to those to actually show up here, right. And the other thing is you'll see when I click advertising, it's jumping down. And I don't want that to happen. And the reason it's doing that is because that behavior is good if JavaScript isn't running or it's disabled for the user. But we want to disable that when the JavaScript comes in, again, we're using JavaScript to progressively enhance everything. So it functions if there's no JavaScript. But when we have JavaScript, we're going to sort of change the behaviors along the way and make it the experience you want it to be. So to do that, I'm going to bring in this code that we see right here, we're going to break all of this down. So the first thing we could do is do this, where we're going to go through our tabs container, we're going to add an event listener for a click. And it's going to prevent the default. And this is kind of interesting because even though I'm doing this on the tab container, and I'm not doing this on the buttons, this is still working because any event that happens when I click anywhere in here, it's a saying whatever the default event is, we're not going to do that. And that means I can add an event listener to my entire container instead of having to loop through and add an event listener to each one of the buttons. So it's just a little bit less work for the browser. Not that I think it would be a performance issue the other way, but you can see now when I click these, we're not, well, the advertising one's not jumping down like it was before. So that's a nice simple way just to do that again with one event listener. And now one thing that is happening here, let's just do a console log of E. And actually, I'm going to do E target. So E is just the event itself. And I'm going to look at like what we're being clicked on here. So if we come and look in my dev tools, let's just put the dev tools on this side. So if I come into my console, when I click on here, you can see what I'm clicking on. So if I click on the link, we're seeing the link. If I click in the middle of nowhere, I'm clicking on the ally because the ally stretches all the way across if I probably can manage somewhere along the way here just to click on the tab container itself as well. So it's keeping track of what we're clicking on. And ideally, we're going to be doing a bunch of different stuff here, but we only want it to actually do it if we're clicking directly on one of the links. If we're not clicking on a link, I don't want the JavaScript to do anything. So we can close this down. And the way that we can do that is before we even prevent default, and you could leave prevent default is the first thing, it wouldn't really matter. But what we can do is actually put this up here, I'm going to leave my console log, and we're going to look for what we've clicked on. So we're going to create a new variable called clicked tab. It could be a different name again, if you want. And it's going to look for the closest link. So this is really cool because and let's do that we'll do a console log of clicked tab now. So if I come in, look here, and I guess I shouldn't have closed my dev tools, but we can open those back up. Now if I click out here, you're seeing I'm getting null. And the reason that we're getting null is because I'm not clicking on a link. Whereas if I click on the link, it's going to come out. So normally the clicked, the clicked tab, it's saying there is no click tab. That's why it's saying null unless I click on the link. And then it's showing me which link I've clicked on. And so even though I have this event listener on the entire thing, I can know if I'm clicking only on one of the links like this. And what that means is we can come in with this means a if not clicked tab. So if we don't have a clicked tab, if it's returning null, we can return. And that means this entire thing is just gone. We're not going to continue with what we're doing in here, we're going to escape out and that just means the browser doesn't have to parse any more JavaScript. That's not actually going to do anything. So now again, if I open up my dev tools, and we take a look, when clicking anywhere in here, nothing is happening. But if I click on a link, now it's actually firing. So good. We're only doing something if we clicked on a tab, we can now do our prevent default, because we know those tabs are actually going to be links and we don't want those links to go anywhere. The other advantage with this too, is when I click on these, you'll notice I know my address bar is out, but because those were hashtags, I know you can't see my address bar. But when I was clicking on those before, it would go to the hashtag for that address, which is a good behavior, because that's what makes those anchor links work. But this prevents that completely from happening. So none of that's happening, we're just have no link behaviors happening at all. And the one thing that's cool here is that even though we've stopped getting like this, the hashtag won't get added to the URL when we click on it, we still have access to these. And these still can help us with the IDs that we have down here. So we're leaning into that original functionality that we had, and we can take advantage of that to get the JavaScript to actually show the panels that we want to show. And so let's go back to our JavaScript here. And so what we can do is we can add this right here. And what this is going to do is when we click on a link, we're going to get the clicked tab attribute href. And we're getting that because when I click on that, if I click on this tab, I'm getting the advertising or the social media or the content marketing, whatever it is, I'm getting that right there. So the click tabs href is the active panel ID, the new panel that I want to activate, that's the ID of it. And then we can use that to say that the active panel is my tabs. So the panel that I actually want to make the new one that I can see, we're going to do the tabs container query selector, and we can find that and you could do this without having it as two different variables. You could just do it with one and have all of this in there, but I just find it a little bit easier to do it this way. And now I'm going to do this at which, so we're going to loop through all of the panels, because if we come back up tab panels is my query selector all of each one of the individual panels that we'd created inside of there. And so we're going to loop through all of the panels. And for each panel, we're going to make them hidden. So actually, if I take this line off for a second and hit save, we see we have that one that's here. And when I click on socials, it disappears. And it's vanished. So they've all been set to hidden. And then I can go and I can find my active panel that we've got. And then I can remove the attribute of hidden. Oh, I've hidden false. We can just do that, I think. And it should work as well. I don't know why I had the false in there. Now we can see that it's working. So we're setting the attribute here and removing the attribute there of the one that we've clicked on. And it's a little bit of a lazy way to do it, but it works perfectly fine. So there we go. We can see that we're switching between and we have that cycling through. So that's pretty good. The only thing is to really progressively enhance this properly. While this is functional right now, it doesn't really work the way tabs are supposed to work in that if I tab into here and I push tab again, we're actually going through it, the different links here through my tab, which you'd expect is the actual behavior. But the AGP, which is the accessibility guidelines, actually says that we should have to use the arrow keys to go through our different tabs instead of using tab like this. And the reason for this, if I go to socials and I select it, I should be able to access this information down here. So I'm sort of going to the next part with my tab key instead of going to the next thing on there. And I'm going to talk a little bit about this interaction a little bit more later on. But to actually make this work the way we need it to, we have a lot more JavaScript that we're going to have to do. And right now, it's just from an accessibility point of view, we need to bake a lot more things into all of this to get it working properly. So what I'm going to do, because we will have a lot more behaviors coming in here when we're clicking on something, this is going to get pretty full. So I think it actually makes sense to pull this out of here. We're just going to do a function called switch tab. And we're going to switch to our clicked tab. And I just think that it's going to be a little bit cleaner and a little bit easier to keep track of what's going on. And then I just can take everything that I had before and just bring it down into this switch tab right here. So it's exactly the same, just instead of having the click tab, I'm passing new tab here. So I'm just using new tab right there. The only difference in what I had before we come back, it works exactly the same as it did for where it's just showing what we've clicked on. Now, the next part that we want to do is help with assistive technologies, because right now, we'll sort of as I was saying with the keyboard navigation of it, we need to fix that up. But also from an assistive technology standpoint, right now, this is kind of non functional. And we want to make sure that it works properly. So one thing that we do need to do to make that happen is to actually bring in some area rules. And I wasn't using those rules before, because if we don't have JavaScript enabled, we just get the regular list that links down that works as intended. And in general, the best rule of area is no area is good area, which applies most of the time, because we have semantic HTML that we can be using instead. But what happens when we're making these types of components, it's things that involve interaction that don't have like and that we don't have an HTML tabs interface as nice as that would be to have, but we don't have one. So for things like carousels for tabs for accordions and for these other things that you have to interact with that can involve different ways of interaction. Often there's area rules that can help us out when it comes to getting the screen reader experience to function properly. And it just gives a lot more information to users so they can use our interface properly, or at least hopefully use it properly. And one thing that can be hard when you're getting into and trying to figure this out is like, how do you find out what all these rules are? The main thing is if you are trying to build something look up first on the AGP, you could also just do like A11Y tabs or accessibility tabs in Google just to get a little bit more information and see how other people have done it. And often the AGP will come up as one of the first results. And it was heavily influenced the first draft of what I did here based on their guidelines. And then sort of after talking with Hayden went to do a more of a progressive enhancement version of that instead of just following it exactly how they had it. And there's one thing with their guidelines that I'll also talk about regarding ARIA controls that I've recently learned as well. So a few little interesting things that we're going to be able to cover as we go through this. But the best place to start is to start by finding some guidelines to help you get there the same way you'd read documentation on the MDM or whatever it is for how the section works or what's this new element or what's that new selector or whatever it is or this new CSS feature. So if you're looking at the documentation for things, it's the same thing if you want to make something accessible. Don't use like a third party tool that tries to force it in, try and just learn about it. And at the beginning, it will be a bit of a process, just like it's a process to learn HTML CSS and JavaScript. It's a process to learn these things as well. But the more you do it, the more second nature it will all become. And so what we need to decide now actually is do we want these to be automatic tabs, or do we want them to be manual tabs? And what I mean by that is do you want it to be a tab that when you're a keyboard navigating on it, when we switch tabs, do we want it to automatically go to that tab, or do we want it so we can cycle through different tabs and then click to select one of them? In this case, I'm going to go with automatic tabs, but it's a very small change if you do want to go with a manual tab. So you just a little bit of a change in your JavaScript to be able to do that. So what we're going to do, and actually I just realized something as I was preparing for this part, but here when I was saying like this could be a little bit dangerous, we are query selecting these only within the tabs container and then only within the tab list. So you're probably only getting the ones you wanted to anyway. So you could probably leave this the way I had it. Yeah. So yeah, just to say it's not as dangerous as I originally thought since I sculpt my query selectors a little bit, which is good. And the reason I mentioned that is because my next one that we're going to be adding in here where we can I'm going to come down here and I'm not going to do it within a function. My JavaScript is going to run when the page is loaded because I have a defer on there, but you could definitely make this into like a Tabify function if you wanted to. You could have an event listener for the page load or DOM content loaded. I think it is because DOM content loaded is a little bit different than using defer whereas it just waits for it to be loaded before the JavaScript starts to run instead of right now where I think it has to parse everything as well. Anyway, it shouldn't make a big difference. It all goes so quickly anyway, but if you wanted to add this into a function or you could even make a constructor or whatever to like get all of this to work, but we're just going to keep it kind of simple. And we're going to start with this where I'm going to do my tab list and we're going to set the attribute role to tab list. And so that's it saving for this. We're going to spend some time in our dev tools here. Sorry about that. Just because it's going to make it a little bit easier because we're adding stuff to the HTML that we're not going to see if we go over in our HTML tab. So now if we look here, I have my UL, which has the area labeled by that we looked at earlier on. And then I have this role of tab list that's coming on that. And this is the role that we want to add. And again, you'd get this from the AGP article. I have linked it down below or other ones as well that would explain that this is sort of now telling someone who's using an assistive technology that they're on a tablet, they're landing on something that's a tab. And when we do that, the next thing we want to do is make these into actual tabs. So we have our tab list, these instead of being list items should now be tabs. So there's two different things we need to do to accomplish that. So to be able to do that, and actually what we should probably do just because we have the tab buttons, I'm going to move this all the way up, just sort of sort of going in a bit of an order. We have the tab list we're here, we're setting, we're adding that role. And actually I misspoke a little bit because I said that we wanted to make the list items the role we wanted these to be our tabs, but we actually want the links to be the tabs because these are what we're interacting with. And we want to remove the semantics of the ally because we're no longer in a UL, we're now in a tab list, which is a little bit different. So we want to remove the semantics from the ally and add this tab semantics to the links themselves. So to do that, we're going to have two different things we're going to have to do. One of them will actually be able to take advantage of what we have here already, which is why I moved this tab list up here. But the first thing we'll do is this. So we're going to go through our tab list. I'm doing the tab list then query selector all of the ally, which should be in parentheses that are quotation marks there. So we'll get all of our list items. And then for each one of those list items, we'll set the role to presentation. So if we come and take a look, all of those list items now should, there we go, have the role of presentation on them. And so what we can do is down in this part here, before what we're doing is we wanted to set the attribute to hidden on the tab panels, right? And this loop through all the tabs and it was getting the index 0123. And then we could get that same index for the tab panels and only hide the ones we want. For this, we don't actually need to go through the index or anything. What we want to do is to say tab and then set attribute of tab index to negative one. So now if we come and take a look, and we inspect in here, we have my tab just fine. But if we come into the next one that's in here, we should have a tab index of negative one. And so now if I tab onto here, we're here. If I hit tab again, you can see it's jumping down all the way to here because that's the next thing in the tab order now. We do have to be really careful when you're changing tab indexes and you have to have a very important or very good reason to do it. And here it's just to follow the guidelines of how a tab system should work and that we shouldn't be able to tab through these. We need to keyboard navigate or arrow key navigate through them instead, which we can do. And we'll be doing that in a second. There is one thing though, and it's because of the way this interaction is working and talking about tab index, we might as well stick with it. Where when I tab to here, if I tab down to here, it's a little bit awkward with like, say, I click into socials. And then I want to be able to access this information right away. The best way to be able to do that is actually to allow the user that they're on the socials, then to be able to tab and actually reach this. And this is a behavior you generally is very rare. This happens. The only once again, I'm finding the guidelines and from just usability testing and all of that, that's tends to be the easiest way for users to be able to work. So right, because then so they don't have like, there's no other real shortcuts in their way to get there. And so how we can do that here, we have our tab list here, we have the list items themselves here, we have the buttons themselves. And of course, the container what I'm also going to come down to here is on the panels themselves. And maybe the container would make sense as the first one. But for the tab panels, what we're going to do is set the tab index to them to zero. And the reason we want to do that is we want to be able to go into our tab panel, select the tab. So say we get onto our marketing one. And then I hit tab and it would actually bring me down to that section. And this is for keyboard navigation and people using assistive technologies. It's the easiest way to actually be able to go from like their tab navigation into the content that they've now activated. Because if you activate that, you're assuming that now you want to go and read what is there. So definitely a bit of a different behavior than what you would normally have on most things. But this is the suggested way of doing it, which does lead to the question of also like testing and having, you know, making sure that users can actually interact with this properly. Because you're putting in all this work and people might get there. And it might still be a confusing experience for them. Just because tabs aren't super common, there's probably a lot of bad tabs out there. So there's different ways of interacting with them. So even when you follow best guidelines, you might end up finding out that people aren't using it the way that you think they would be. So, but you start by following what you can, and then you start asking people to test it. You try it on screen readers, get people to use the proper screen readers and all of that. And I'd mentioned earlier that Hayden had helped me. I also had help from Amber from Equalize Digital. Link to down below in the description there for what she's up to as well, which deals with like adding accessibility testing for WordPress and stuff like that. WordPress sites. And she kindly recorded some interactions with screen readers and showing me how it would work on that end of things, which was really helpful to like see how that goes because I'm not comfortable using them. So just getting some ideas on that, how that side of things worked really helped me out. So thank you for that, Amber. And the other suggestions that you gave me as well to improve things in here. And yeah, actually, and before I move on, I do want to mention that, like, I wouldn't have been able to build this completely by myself without the help of other people who specialize more in this stuff with Hayden and Amber's help. I think this is a million times better than what I would have done on my own. And I think when you're building stuff like this, and I had a bit of a discussion with Hayden on this, where the best way to be able to do this is to actually talk with people that are good with what they do. And there's a lot of people on Twitter and Mastodon who work in this field that are very willing to help out with people and like discussions that are going on. Because one thing that also came up was with these links, they should have area controls on them for the tab that they're going to. And originally it was buttons with the area controls. And through talking with Hayden, who's done a lot of testing and other things, it turns out that area controls doesn't actually do very much or what we think it does. Because it used to be announced. There was one screen reader that would actually announce what it was doing. This button is controlling this feature and they removed it because it was too verbose. It was like slowing people down. It was open menu. They know they're opening the menu. They don't need to know what menu they're opening necessarily type of thing, because they probably had the context already. And there's been quite a bit of discussion within the accessibility community about area controls and sort of what do we do with it now. But yeah, it was sort of enlightening on that front. So if you are looking to build things that are accessible first, make sure you talk, you know, look up what the best practices are, talk to people, test it like crazy through the different interactions you can have, ask other people to test it. If you do have the resources at hand, you're working in a larger company and they want to do this, and you're taking the time to build it properly, get the audience you're building this for to test it out and see if it works because you might find out that they'd suggest doing things in a different way. And the only way to do that is through test actual people using it, right? So it really important step along the way there. And you might not have those resources, you're just a student right now, but just try and talk with people in those cases. In those cases, like I said, follow the resources, the guidelines you can find, if you can find people doing videos like this, you can follow along with that and do the best you can. And then along the way, try and just have discussions and talk with people or follow discussions that are happening or whatever it is to try and learn more about it. But with that said, let's keep on going here, sorry for the little tangent. And actually, I do want to circle just really quickly to this, where I'm doing a tab index of zero on all my tab panels. This could be something that maybe would require a bit more testing because if I go to here and I hit tab, it's only highlighting that because that's the only thing that's here because we've hidden away the other ones. And we're only doing this through JavaScript. So remember, if for whatever reason, the JavaScript doesn't load and we go to that native experience, this isn't running the risk of breaking tab ordering and stuff and causing problems outside of like this progressive enhancement that we're creating right now. So that's really important because if all of the tab panels were visible and I would just tab through them, that would be kind of weird. So but I think how we set this up is safe because only one of them is actually visible to us, even from the accessibility point of view as well, because hidden will take it out of the accessibility tree. But while we're here and while we're talking about these panels, we should also be we've done the the attribute of role presentation, the role tab list, the role of so we can come on this and we can set the role of tab panel on the panels themselves as well. Because if we have the tab list inside the tab list, we should have tab panels. And on that note, we should also have tabs. So for all of these, what we can do is come through and I'm just going to say tab set role to tab. And this was before I meant to circle I meant to do this earlier and I forgot, but when we stripped away the semantics of the ally, we're saying this is no longer a list item because these are my tabs, we have to add that in here. And we do that with my role of tab on the individual items that are inside of there. So now if we go and we take a look, we should see a nicely marked up where we have in here, we have the ul which has the role of tab list, and it is being titled by my h2 right there. We have the allies that now have a role of presentation because we don't want the semantics of the ally because our a's here have the role of tab on them. So this is what's giving the semantics to it. And we've changed our tab index on those. Now we're going to do one last thing here. And it's going to have to deal with which one is currently selected because when we have our tabs, we need to gone this far. We wanted to also explain to the screen reader, which is the selected tab as well. And this is a little bit more useful if you're doing a manual one, just because then you could be going through your tabs, but it's not the selected tab. But we'll add this in here anyway, because I think it's still useful to have. So we're only going to we're going to go on this index zero. So we're choosing our first one, because that's our active tab when the page loads. And we can say is so if the index is zero, then that tab, we can do a set attribute. And that attribute will be area selected. And it will go to true. So now if we go and take a look there and the reason I'm doing this is because we're going to be starting to style things up soon. Exciting, right? It took all this time to get to some CSS. I don't know what one of my videos, it's not often we're doing so much JavaScript. But now we have an area selected of true on that first one. And it will only be on the first one when the page loads and we'll move things around with some JavaScript after. But the reason I'm doing that is let's jump over and do a little bit of CSS. So I have my style.css where I just have all the stuff that doesn't really matter. And let's start. So we're going to come to our I'm going to leave it like this, assuming the JavaScript doesn't load. And you could come up with your own styles, whatever you want. But to ensure and this is a little bit I've talked about this before where we can code things based like semantic, sorry, semantic selectors and semantic CSS where we're selecting things based on the attributes that are on something. Since we're using a lot of attributes in here. So what we could do here is our, if you remember, we're getting a role of tab list on the tab list, if it's actually going to be a functional tab list, right? So what we could do is we could say that if the role is equal to tab list, then we can do a list style of none. And that will take those away. And then we can also come in and say that it's a display flex. And they'll go next to one another. And I guess here too, you'd probably do your margin, margin of zero, adding of zero. And then we can also last thing we'll do here is a gap of like one RAM, just to space them out a little bit. And now the next thing we can do and we could definitely style these up a lot more than what I'm going to be looking at right now. But we're going to come and for now just do an area selected is equal to true. And let's do two things. Let's just for fun do a text decoration thickness, and we'll make it like 0.5 m to make it really thick. Maybe that's a bit too much. And then we'd also do a text underline offset and do that at like 0.5 m or something just to move it down. It's not perfect, but I just want to like maybe we can also we'll do color is yellow, orange, red, because just to make it really obvious how this is working. Again, not super worried about like styling styling right now. I'm just worried about more functionality. But also hooking into the things we've said here. And then if the page loaded just to show you if there was no JavaScript, none of those stylings are coming in. They're only going to come in if the JavaScript is loaded. So we're styling it progressively enhancing it through JavaScript, which is also then styling it appropriately. So let's jump back into the JavaScript now. And let's go to our switch tab function that we created here, because we have a little bit happening, right? When we click, we actually have that switching around. Now, another thing that we'd want to do, we want to sort of continue hooking into what we've just created there with our CSS, or vice versa, however you want to look at it. So active panel removing the attribute hidden, we could also come in and add this line right here. So new tab set attribute of area selected to true. Right. So now when I click that, you'll see that that one becomes true and true and true, except that's kind of awkward, because now they're all true, and they're clearly not all selected. So to be able to prevent that what we want to do is we can come right here, and we can say our tab buttons. And so for each one, the area selected will go to false every time we click on one of our links, because when we do our switch tab, and we'll also switch the Z index to negative one, because right now the Z index of zero was staying on this one. We don't want that to happen. So let's save that and see what happens now. So if I click, perfect. The only thing is we've killed our Z indexing. So the new tab will also need to do that. So let's just grab this, paste it here, and just switch that to new tab set attribute to zero. So now when I go like that, it's working. And if I tab and then tab, it goes to that one. Now, the only thing is, I can't switch to the other tabs, we're going to need to build that functionality in. And one thing I was I was saying before with the area controls, it doesn't quite do what we want it to do. If you do want to add in like an extra layer, there is a way to do that as well, where we can give a bit more context to this. This is definitely something where you'd want to test it. And obviously, there's issues if you have like internationalization going on with different languages and other stuff. But I'm not going to include this in the finished version of mine. But what you could do and I'm just going to throw it in the HTML here, but you'd probably want to have this also as a progressive enhancement, where you could do an area described by and then have like a this is looking at an ID. So and then in the advertising here, we could have a div that is has the ID of focus hint. And it would also be hidden. So we don't see it. Interesting thing, a lot of area attributes can access the information of these types of things. So this could be like press tab. And I don't need to hear anyway, we'll move this in a second, but press tab to move to the tab panel. Right. So and I put it here, but we don't want it inside that we probably have it right here instead. So we're doing our focus hint. So what this is doing is it's something that's completely hidden from the user and you just have this area described on each one of those. And again, you could use JavaScript to insert this. And the idea with it is that just if you do feel like the people you do some testing, they're having trouble understanding how to work with it, you could add this in. But again, you always have to be aware that maybe by adding it in that it ends up being a lot longer, you know, there's this extra information that's given when they're on these different things every time they go on it. So but just as an option for if you feel like you need something like that to give a little bit of an extra hint. So people understand how to interact with everything you're building here a little bit better, because it from everything I've from all the talking I've done tap interfaces for people who use screen readers. It's a struggle and you have to also remember screen readers aren't only for people that are blind. There's low site users and other things as well that are using them as it just helps them understand and interact with the websites. So you know, it's it's not just this very small niche you might be dealing with more people than you expect. And again, they're weird interfaces aren't something that they're used to coming across and always knowing how to interact with them. So sometimes that little bit of extra information can be helpful. But what's good here is because we made this it's our own like we have a function here called switch tab and our switch tab is working when we click, which is what we want. But we also want to be able to switch tab as I said with you know, if I'm on this tab, and I'm keyboard navigating, I want to be able to use my keys to be able to switch between the different tabs. And if we built all of this functionality all inside of this, the event listener here, the click event listener, then we wouldn't be able to do that. So that's another nice reason you have a sort of a separate function, when someone clicks we're doing something, take that doing something and make it its own function because then you can reuse it sometimes in good ways. And so let's come right here and we're going to do is we're going to create a new function. And we'll do a move left to start with and then we'll come back after and do a move right. And, of course, you got a spell function properly. And how this function is going to work is it's going to look at what the currently active tab is. And so that means like if we've tabbed onto something, you know, this is in focus right now, or even if I've clicked on it, it is in focus, but it's not getting the focus ring just because it's not the focus within type of thing that we have on these days, which is really nice or not the focus visible, I should say. So we can get that by saying that our current tab is the current active element, which is a nice easy way to be able to get which one are active one is here. And it is assuming that we're currently interacting with our tab system, because the move left and move right, it shouldn't do anything. And where we're going to use this function is only going to be if we're inside of this, like we're actively interacting with it anyway. So this won't have any like if I'm tabbed down to here, and I'm using my arrow keys, it's not it's never going to get fired. So we don't have to worry about that. Now the thing with the tab is when I go when I push left, I want it to move left. But if I'm on advertising, and I push left again, I actually want it to cycle through back to this side. So we can cycle all the way through one way, or eventually at the right, we want to be able to get if we get to email and they push right, I want to go back to the start that way. So the simple way without worrying about that is we can do this, where we can go switch, we can run move left will switch tab to the current tab. So it's going to look at the current tab, it's going to go to the parent element. And then it's going to go to the previous element sibling. And it's going to find the link that's in there. And then that link is what is the new tab that will get activated through our switch tab functionality. Now this might seem a little bit weird. It's just because we're doing some DOM DOM traversal traversal traversal. So right so Sam on socials and I push left. What I needed to do is go to the parent element, the parent element. So if I'm on my socials, and that means I'm on this. And then so we're saying, if we look here, we're going to the parent element. So the parent element is my presentation. Then we're going to the previous element sibling. So the previous element, which is a sibling will be this li right here. And then from there, we're doing a query selector of a so we're going and grabbing this right there. So we're just moving from here down a level across and then back up. So it's not that bad to be able to do it. But of course, as I said, we don't want this to function all the time. Because if I'm on advertising and I push to the left, I do want to be able to get to email over here. And that one's a little bit trickier. Maybe there's a way we could traverse to always the first one. So what we want to do now is, you know, if, as I said, if we're at the end of the list, what do we do then. And so I'm going to do this. So if the current tab parent element previous sibling, we don't have one with the escalation point here. So if that doesn't happen, then we want to switch tab to our tab buttons. And we're going to look at the index. So because it's a node list, we can pick based on that. And then we just look at tab buttons dot length minus one. And the reason we do a minus one is we have four items here, but we're counting from zero. So this last one, the index of that one is three, right. So we just always subtract one. And by doing it this way, you can have two tabs or 10 tabs, and it's always going to work. And it's always going to choose the last one right there. So we can say if that, and then else, I'll just select everything there and hit save to format it. Thanks to prettier. So we say if there isn't a previous sibling, we'll cycle over to here. And the rest of the time we'll just move on over. Now, of course, we want to actually be able to do this. So to be able to do that, we're going to add another event listener. So right here, we have our event listener for when we click, and we're going to do another tabs container event listener. So we can add an event listener that looks like this, which is key down. And remember, I said that this is only going to work if we're actively in our tabs container. And that's because this event listener is only going to be looking for key down events in there. It's the only time we'll ever call this. So I guess this could be move left tab or something like something more explicit to say that it's working with your tab system. Just in case you have other move left functions that you might need, you know, for now, let's just say move left, just so we can see if it's even working or not. Because the worst is when you try something like this and then it doesn't work. And so there we go. If I push a key, so if I click here and I push to the left, it's moved over to the left. But now it's actually stuck because this is still my active one. So you see how like my focus is there. I'm pushing left. The focus is still here, but it's moved that over there. Well, that's really awkward. Luckily, that's actually very easy to fix. We're just going to go back up to our switch tabs function, which I think is all the way at the bottom. So here we're saying our new tab is getting the attribute of area selected, it's getting the tab index of zero. So it is selectable with keyboard focus. And the last thing we want to do is make sure our new tab gains focus, which we can just nice and easily do like that. So now we go on to let's say marketing, I should push to the left. And then you go, you can see it moves over, it moves over, and it's going over. And actually, it's doing this no matter what key I hit on my keyboard, because we never set it up to work properly. But we're always going around and we can cycle all the way through. Awesome. So at least that's working. Let's go and take that move left that we've just created. And we might as well duplicate it and make our move right while we're here because it's a small little update that we need to make for that. So the only difference is we're going to call it move right. And instead of saying if there's no previous element sibling, we want to check if there's a next element element sibling. If there is not a next element sibling, because we're at the end here, we're at email, we want to go all the way back to here, we don't need to check all of this, then we can just say go to zero. And then else switch tab. So if they're if say we're on advertising, we want to go to the next one over, we can go to the parent element. Instead of previous element sibling, we just go on over to the next element sibling and then grab the link that is in there. So now let's try that one out and see if that move works. So we can switch this from move left to move right. And let's see if that's working now. So go to social, and we can see we can cycle through that way now. Perfect. That's great. But obviously, we don't want to do this anytime any key whatsoever is clicked on. We want to do it in specific use cases. So how can we do that? There are actually a few different ways we could build in and if else through this, but we're actually going to have a few different things because we're going to have left key, right key. And I'm also going to do a home and end keys as well, because a home can bring us to advertising and the end can bring us to email. So the first or the last item. And because it's if we're doing it with if else, there's like lots of different things like it would be if this, if else this, if else this, if else this for me, it just becomes easier in those types of situations to use a switch statement instead. So that's what we're going to do here is use a switch statement. And so here we can bring in the basics of a switch statement. And what we're doing is when we we're tracking the E so anytime someone pushes key down, we're seeing what key or we're seeing what the event is. So I'm actually just to show you, let's we can do that, we can say console log E, just so we can get an idea of what that is in case you haven't really done much with it. So if I come here, we go to my console, and then when I push a key, we see that it's a keyboard event. And this is only going to fire if it is a keyboard event, because we're looking for where is it we're looking for the key down to fire. And we want to know what key they've pushed. So here we can actually see that we can grab the key. So that's exactly what I've done switch and then E key. So we're only looking for what key they've pushed. And now there's key codes that you can get for like all the different types of keys like here if I push the letter a, you can see the key a key code and there's all the different information that you can get. This is the key code I was thinking of all the keys have like individual numbers that they're assigned. So you can definitely look for the number. You can also just get the key itself. So not the code for the key, but just key. So if we come up here and I pushed the left, we should see if I scroll down to this one, right there, we can see key is arrow left. So instead of like looking up an abstract key like that, we can say the case is arrow left just like that. So if they do an arrow left, we want to do something. And what do we want to do? We want to move left, right? Nice and easy. And we're also going to put in a break. And the reason we want to do break is because we want to say like if that's happened, we're out of here now. We don't want to keep checking anything else of the other statements, anything. We did this. Now we're leaving. We're done with this function. It's sort of like when you return, right? So well, it's not the function. It's getting out of the switch statement. So we're breaking out of there. Let's bring up our console. Let's clear it out. So if I if I'm in here and I push any key, we see those keyboard events are going because I have that console log that's still happening. But you can see nothing's actually switched. But now if I hit left, you can see it's actually switched over and I can cycle through by pushing left. And again, I can hit any other key and nothing is actually going to fire. It's only the left that's actually doing anything now. So I'm going to take out that console log. So we definitely don't need that in there. And then we can take this that we have right here and duplicate it. But we can say that if it's arrow, right, we want to move to the right. And now if I tab, we can go that way. And then I can do left and we can go that way. So look at that. That's that's functional. And if I hit tab, we go to the related one shift tab to go back. And we can go through those the way we want to. Now I did also mention we want to be able to use the home and end keys to go either to the start or to the end automatically just jump every over everything. So we can do that case. When the key is the home key, we can switch tab to the first one. And then if it's the end key, and I forgot the break here, we throw that in. If it's the end key that we're pushing, just like we did before, we can use that and go to the last item in our of our tab buttons. So if we come here and I'm on marketing, I can push the home key and it goes there. And if I push and a bit of a mistake there, but we go to the end one. So on both of these, it might also be useful to do an e prevent default just to make sure that the page doesn't also scroll because home and away by default will scroll the page. So let's try that again now social. And I'll hit my home key that goes there. I hit the other one and we can go back and forth between the two that way as well without it accidentally scrolling the page. And this will only be going if we're inside the tabs container. So as soon as we leave the tab container, even this could even be on your tab list maybe. But as soon as we are outside of that, then we'll be able to use the home and end to also navigate the page itself. And of course, now there's a lot more you could do with tabs to style them up to make them look better to do a hundred different things. But the functionality will generally always be the same. The big thing that you might change is you might be going to a manual tab instead. And in those cases, all you'd be doing is your move left and move right wouldn't actually be changing. You'd be changing the focus, but you wouldn't be changing the area selected until someone's actually selected that tab. That would really be the big difference. So you'd have to wait until like the key down to then be switching to the area selected and changing all of that to actually activate the tab. And then you'd have to have different focus states and everything along the way with those as well. But I really wanted to focus mostly on the functionality of it here since you can style these up in any way you want. And then of course, the idea of styling them based on the roles that are only getting added with the JavaScript. So when we are progressively enhancing it, that we're making that next step. And again, this is if you really need to have them because of course, I'm sure you've seen it where you have a narrow item and you have too many tabs and then like, what would you do? Or if you want to make it responsive, what do you do? They're not the easiest thing to work with. And they're not something easy to interact with and they're not easy to implement properly. So just like I opened it, I will close things off by saying that I, you know, use them if you really have to use them, which I know can happen when we work in the real world, you're given a job, you got to do it, or maybe you're just doing something that you want to put in your portfolio and show that you're able to do it and do it properly. And yeah, I hope this was a fun lesson looking at accessibility, progressive enhancement and all those other things. The JavaScript in this case could probably be optimized a little bit and set up more specifically, like this is just all running in a JS file right now, you might want a function that's adding all the accessibility in instead of just these things that are sitting here and you're waiting for the DOM to load before that comes in, whatever it is. My main thing here was focusing on setting everything up with the accessibility in mind and the progressive enhancement in mind and how you want to take those next steps with it is completely up to you. And if you enjoyed this video and you'd like to see a much simpler accessibility fix that you could make, you can you can check out this video right here that looks at the skip to main that a lot of sites don't have really easy to implement much simpler than what we're looking at here. So you can check that one out. And with that, I would really like to thank my enablers of awesome Andrew James and Rico, Michael, Simon, Tim and Johnny, as well as all my other patrons for their monthly support. And of course, until next time, don't forget to make your appointment on the internet just a little bit more awesome.