Check out a free preview of the full Web App Accessibility (feat. React) course
The "Focus Management Exercise" Lesson is part of the full, Web App Accessibility (feat. React) course featured in this preview video. Here's what you'd learn in this lesson:
Students are instructed to add focus management to a modal. Focus should be sent into the modal when it is opened. Focus should be restored to the application after the modal is closed.
Transcript from the "Focus Management Exercise" Lesson
[00:00:00]
>> For our focus management exercise, we are going to add a more accessible modal layer, and we'll see how the mechanics of that work. We've learned about tab index and how to trap focus into new layers, so let's apply it in an example. We're gonna use pre-built components for this, so it should be a little less in the weeds than our ARIA example.
[00:00:29]
But let's go into this and see what we've got here. So for our image gallery that's in progress, when I click this, I have a layer that pops up. It's not totally done in that it does have a close button. I can open and close it, but I can still get behind that content.
[00:00:52]
So if that layer is open, I mean, the display looks funky for one, but it should really be blocking me from getting anywhere behind that layer when it's open. So totally not working. Let's make something that does work better. And we're gonna reach for components that are already built in, because it's a lot easier sometimes.
[00:01:23]
But we'll look at what are the kind of building box of what they're doing that make it actually accessible and make it work. So in our ProductimageGallery, let's add some components here. So let's see how it's working right now. There is a full screen image state that we're setting on and off when you click on that image.
[00:01:47]
So the image is, first of all, it's a div with an onClick. Let's make that a button. Let's give it an aria-label Open image in full-screen, because the alt attribute would supply text to that button, but it would just be the alt attribute from the image and that wouldn't really say what this action is gonna do.
[00:02:12]
So clicking on this button in this iteration will open it in a full screen layer. So this layer down here, as we've just a regular old div, it's got some positioning on it. It has a close button that is another div with a click event on it. I think we could just cut our losses and try a built pre-built component.
[00:02:38]
And we have some pre-built components in here using Chakra UI. And for React, I think they have view, versions, and maybe some other options as well. It's pretty solid, so I would definitely recommend checking it out if you're in this part of web development. So let's pull in, I'm gonna open up our modal, Chakra UI, and let's go over to the Components.
[00:03:12]
And I think it's, we need to go to React, Components, that's where they live, and then Modal. So interestingly, there's a set of components under the title overlay. And so that's this kind of general concept for something like a layer. Not to be confused with an accessibility overlay, which we're not even really discussing discussing today, but overlays, modals.
[00:03:46]
So for this example, we will grab these components. We already have Chakra UI React in our project, so it's pretty easy to grab these. They're really great about documenting how they're adding accessibility. So anytime you go to reach for a pre-built component, read up on what they have to offer on this kinda thing and test a demo.
[00:04:11]
Before you go through the work of importing it and seeing if it'll work, go test a demo site first. And so some of the things we wanna look for, they are very helpfully writing out here, including when the modal opens, they trap focus in it, hey, we know that one.
[00:04:26]
When the modal opens, focus is automatically set to the first enabled element, or you can tell it what element to focus on, that is awesome. So it's something they're calling initialFocusRef. So that is a way for us to reference an element in React to say, we wanna focus there when it opens initially.
[00:04:48]
And then they have a similar one called finalFocusRef so we can choose where to restore focus. But you don't have to, they automatically do it for you. That's amazing. You can click on it to close it, you ou can use the Esc key, scrolling is blocked behind the modal.
[00:05:09]
It's rendered in a portal attached to the end of the body, so it will break it out so that it's easier to put a NERT on it. That was that topic we were just talking about. So they're really thinking about all the right things here. So if you can use pre-built components, sometimes it is a good choice.
[00:05:29]
And then they have some ARIA stuff in here. So they use the aria-modal, I guess that's a state. And then they have some labeling already wired up for you, that's It's pretty magical. So let's go add that. We have an image component, so I'm going to add to it.
[00:05:49]
And for our modal, We're gonna go pull in some of these components. So I've got the imports, let's grab some of content as well. They have multiple overlays here. I wanna get the basic usage. So we already have a button to open it. We will grab this modal, we even have the state to open and close it.
[00:06:17]
We just want the markup from this component. So down here in JSX, I will leave our fullscreenImage state to render this. And instead of Modal isOpen, I will say, setFullscreenImage. Or let's see, what do I wanna call it? Yes, so, What did I add here before? Actually, onClose I will say, What did I have before?
[00:06:55]
So we had closedFullscreen, so I have a fullscreenImage and closeFullscreen, Back here, closeFullscreen. So since I'm not passing any arguments, I can just reference this callback function. For this one, I'm gonna take fullscreenImage and it will be a string, I believe. And so I can turn it into a truthy-falsy variable just by putting a double exclamation point in front of it.
[00:07:31]
So that will hinge off of that state that I'm already managing and we can go up here to see that fullscreenImage is being managed with useState. Okay, so we are not going to use a ModalFooter. The ModalBody will be our image. So I'm gonna grab the, The image, I think it's just scaled down in the smaller size.
[00:08:04]
So if I open it up with the same asset, it'll just have the display to show it bigger. But I think if you had different size image assets, you'd show a bigger one in the full screen gallery, right? So our Modal Title, this one, the design does not have a title showing.
[00:08:25]
Titles are pretty important for modals. So I think in this case, I might just include one and then I would talk with my team, how are we gonna handle this? The design doesn't have a title on it, but we have to include one. I could investigate adding a screen reader only class to this or something to keep it there, but not show it visually.
[00:08:47]
But for now, I'm going to put the alt attribute or maybe the product name. Any one of those. Okay, so we have a modal, let's see what it looks like. Hey, there it is. Our style looks a little weird, but it's already there. It opened up, it's in the full context of the Window.
[00:09:17]
And so I can probably control that with some relative positioning, but that was the easiest modal implementation I've ever done. [LAUGH] And we can take advantage of some of these libraries now. It didn't use to be that you could grab a modal off the shelf and have any hope that it would be accessible, but this is awesome.
[00:09:39]
So love you, Chakra, [LAUGH] thank you. So for this, let's see if we can control that. I'll say div className="relative", that is a Tailwind class that will add CSS relative positioning. So hopefully, try and contain some of this. We might just be kind of not impacting it in the right way, cuz it's in our slide references when the full page version is really what we're gonna care about.
[00:10:13]
There is a prop for this also to make the modal go full screen. I think it might be view="full". This is another area where I'm not gonna go down the Typescript rabbit hole, but sometimes it can be helpful. I can't quite recall what the prop is, but you do have a way to full screen this really.
[00:10:43]
So let's see. I'm actually going to open up our example page. Wow, that was pretty cool how easy that was to open and close. This title is not the right color nor is the button, but I think we can fix that. I mean, the button would be pretty.
[00:11:06]
I think I could do colorScheme. I think that's the Chakra way of calling things. I think I might be able to give it a black color scheme, which I remember. We'll play with it. And I can always go back to the Chakra Docs and sort that out. So for this one, let's see what it looks like in our full page.
[00:11:37]
So here's an example. So I do have the correct color of button here. I didn't end up including the title on this one, but we could figure that part out, too. So that is a modal that if I tab around, that close button is the only focusable thing.
[00:11:56]
But we know there's other elements on this page that were focusable before this. So this modal is doing some heavy lifting for us and that was the easiest copy of code I think I've ever done. So try using it, because this is really what we wanna get to, is to be able to send focus to the modal layer when it opens.
[00:12:19]
I can hit Esc and go back, my focus was back where we started, even though we couldn't quite see it. So yeah, that's some focus management right there.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops