Accessible Slide Over in React with Tailwind UI and React-Aria

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey everyone today we'll be taking a look at how to build a fully accessible slide over component in react and we'll be using tailwind ui tailwind css react aria and framer motion we'll be using an existing tailwind ui component as the base for our component today and we will extend it with the reactaria library to ensure that it's fully accessible and then we'll also add framer motion just to provide some nice basic animations that will make the component really feel complete by the end of this video you should have a fully working implementation of the tailwind ui component that you'll be able to use in your react application so without further ado let's jump right in so if you haven't heard of tailwind css the utility first css framework that essentially removes the need for you to write your own custom css instead what you do is you use these utility classes provided by tailwind to build and style your ui we're also going to be using another product built by the tailwind team and it's called tailwind ui so what tailwind ui is is it's a collection of components that are built using just plain html and tailwind css and you can use them within your application or website now these components are fully customizable because what you get out of the box is literally just the html and the required tailwind css classes and then the rest is up to you so you can change them up in whichever way you see fit you can expand their functionality and so on this also means that if you want to use these components in your app that's built using a library like react review then you'll need to implement some of this interactivity yourself now i want to mention that tailwind ui is a paid product so you need to buy a license to have access to the entire collection but the tailwind team was gracious enough to provide some of them for free the sample that we'll be using is called slide over and it's located in the overlays category so if you click on here you'll see that the first example is available for free and what we get as i mentioned is if you click on the code tab we get our html and we get our classes from tailwind css that we need to build this right now mentions that it needs uh talent css 2.0 and then here you have the notes this mentions that this is background overlay and show hide based on the slide over state so we will need to implement the show hide functionality of the slider ourselves but we do have the basic specs here so for example over here we're provided with the animations that will be required and we're actually going to be using this information once we get to the framework motion uh part of the video so we won't worry about it for now but we do have that information so i've already got an app set up using create react app and tailwind css already installed and as you can see right now it doesn't do anything it's just a simple starting point for us so on the page you'll see that i've got some tailwind classes to define my layout i've got my button so the idea is we want to implement our slide over that when i click this button it will open up all right so first let's go back to tailwind ui and copy over the code that's included so just like i did with the button here uh i want to make this into a separate component so in my app here you'll notice that i have a folder called components so in this folder i'm going to create another file called slide over and [Music] right now it's just gonna be a simple react component so i'm gonna paste the the code from the oven ui over here and let's clean this up a little bit right so i don't need that we don't need this right now so as i mentioned we'll be using these um these options uh for the animations when we get to the uh framer motion part of our example so right now we don't need this i'm just going to remove all of this stuff [Music] and also the comments okay and here is where our component will go um or sorry our content of our slide over right so i'm just going to say placeholder for now all right so i've got i've got the um the basic skeleton of our slide over uh rendering here as you see this is all stuff that we got from uh from tailwind ui now the first thing we need to do is we need to update uh this attribute from class to class name right this way our tailwind actually works so let's save that and now in my app um i just want to include it on the main page so i need to import light over from slash slide over and then i'm just gonna put it below the button here [Music] so our slide over right so we got the slide over rendering which is cool but as you see it's not interactive so it's rendering on top of everything else so let's go ahead and fix that now a few things here uh you'll see how we have the panel title and the placeholder as well now right away i'm gonna know that this is something that i'll want um i want to pass to my component so let's go ahead and just include it uh here so we're gonna need a title and then i'm thinking we'll just do our placeholder as children so i can just reuse the whatever is passed to this component title and then i'm gonna put in here right okay and now where we user slide over let's say title let's say this will be an item details panel when you click on it i want to see more information about some item and let's say in here i'm gonna have uh an input [Music] text input and uh let's say i'll just have another button in here [Music] and let's i don't like the way it looks let's make that look a little bit better i'm going to have another div move that i'm going to make that flex make it flex call [Music] all right so there um what else uh let's style this input a little bit more as well um i'm gonna have order gray i don't know 500 let's say and i'm going to add make the edges around it like a button already [Music] yeah that's better and then i want my button to give a little bit of a space between the input there so i'm going to add a some top all right so we've got our slide over but it still doesn't um it's not interactive so let's let's do that next so one of the things we're gonna do in here is we'll have a we'll add a prop called is open to tell us whether the uh the slide over panel should be open or not and then for now we'll just simply show or hide it so if it's open we want to render right and then [Music] what did i do here on terminated oh yeah right [Music] all right so now as you see we don't see the slide over panel anymore and that's because currently is open prop is false because we're not passing it to the slide or component so let's now implement that on our main page where we're consuming the slide over [Music] so i'm just going to use a react uh use state look oops um and i'm just going to have [Music] is open and set is open and by default it will be false and then what we can do is when we click the button and add an unclick that will then set is open to true and then we also want to have the same thing to happen when user closes the slide over panel so maybe on let's say when we click the ok button we want that same thing to happen so we'll say unclick we want um that is open defaults right oh and then we need to pass that to our uh slide over component and you'll see uh you'll see in a little bit why i chose this name um this will we'll be using this very shortly so there's a there's a reason why i chose this specific name all right so we've got that so let's see when we click on the button the slide over appears and then when we click ok it goes away right now one thing is when we click on the x it doesn't close so let's do the same thing as we do for the ok button but put the um the close icon and that will be in our slide over component so actually one of the why don't we instead of instead of specifying a page button we know that that handler will be the same for anywhere in our slider component so let's just pass a function to that [Music] so we'll say unclose will be our callback and then and our on our close button which is this one um we can just say on click i'm going to call the unclosed handler okay let's save that and let's see if that works now if i click on the x oh right so we added the prop but we didn't actually pass anything so uh let's do that here let's um let's create a function called um handle on close and this will just say let it open and let's be one of the cool kids and turn this into an arrow function okay so now got our handle on closed so we can do well first of all we can replace that here right so we can say one click we want to handle on close and then the same thing for our slide over component we want to say on close we want to handle on quotes okay save that now if we refresh [Music] all right now notice how when we click on the button and the panel comes up if i move this over see how the outline is still on the button that we clicked at the the focus hasn't changed so for someone who's um either visually impaired or uh navigating with the keyboard they won't know that uh this panel opened up right i'd have to manually go and move to the next element and then i can also tab backwards using the keyboard and you'll notice in the background i still tab back to the uh the button so this is a problem generally we want the modal or the uh the slide over in our case we wanted to contain the focus and we wanted to move on the first element to be automatically focused as well so that our user knows that you know the context of whatever it is that they're doing it's now within this container here so that's that's problem number one problem number two and you can't see it right now but i'm gonna add a bunch more text to the bottom just so i can scroll the page so if i just go over here i'll add a paragraph and then [Music] add some text and then let's say and add some padding and just say copy it a bunch of times all right so right now um my page scrolls so if i open this back up notice how i can still scroll the page so all the content behind the slide over it's still scrollable which is not good we don't want that to happen uh much like with the focus we want the context of what the user is doing to be within this panel so that's another problem that we need to fix and one last thing if a user is navigating with the keyboard and they open this up in addition to the focus changing we also want the user to close our dialog with the escape key so right now if i press escape nothing happens and generally if the user is navigating the keyboard the expected behaviors for the escape key to close the uh model or the dialog or in our case the slide over panel so those three things are the main three points that we want to get to work in order to be able to say that our component meets all the accessibility criteria and actually one more point that i forgot to mention so if i go over to firefox where we have accessibility inspector and we open up the panel notice how everything on our page including the content behind our panel over here is still visible to the screen editor so when a screen reader parses through our page generally when the content when the content changes and the user's focus changes to this uh model here we don't want the screener to have all that extra content to worry about we we wanted to only focus on the context of where we are here so all this extra stuff it's unnecessary and it should not be should not be in our tree here so that's another thing that we'll need to we'll need to take care of so with all of that in mind as you can see this is quite a long list of things to take care of manually every time not just that but you also have to think of the proper accessibility patterns for each specific scenario and make sure that it's all semantically correct it's quite a lot luckily for us there's a library that helps us out with that and this library is called reactaria reactaria is one of the react spectrum set of libraries and has everything to do with accessibility so this helps us out when we're building out our components it helps us handle all the accessibility and related things so we'll see for our our use case today it'll have everything to do with overlays so we'll be utilizing a number of these hooks to handle all those uh all those concerns that we had right so for example use prevent scroll we will use this to handle uh our scrolling problem that we saw so to install pretty standard all right and i already have that installed uh in the project so we can just go ahead and start using some of them all right so the first one that we saw is the use prevent scroll [Music] so let's go ahead and add this to uh to our project so in our app dot js [Music] go ahead go ahead and import use prevent scroll from react area and then in our component here we can simply call that now remember that it expects uh one option right and that is disabled so we want to pass this disabled and we want it to be disabled whenever the slide panel is open and we want it to be enabled whenever slide panel is closed so we can take as open right and say when it's not opened it's disabled so that way when flight panel is closed our page will be able to scroll and when the site panel is open uh it will not uh the page will not scroll so let's save that and reload the page now when we expand it now i'm i'm trying to scroll right now and it's not moving right so that part that part is handled now when we close it we see that our scrolling is restored next let's handle our focus containment problem so for that react aria has this component called focus scope so focus scope manages focus for uh all of its descendants so this sounds exactly like what we need so let's go ahead and import that and in our component here we want to say that whenever uh whenever these slide over is open whatever it contains we want the focus to be contained there so in our case this looks like a good place to put that so whenever it's open we'll say we want to put focus scope and let's just wrap that and now we need to import it so import oops focus [Music] right and there's a few options there that are not options there's a few props that we can set here so one of them is called contain basically this specifies whether we want the focus to be locked to whatever is within here okay next one we want is restore focus and this one is whenever we have the slide over open [Music] and we close it back we want the focus to be back to what originated that action so in our case that's this button here so we want we want the focus to be restored back to that button whenever we close our panel so let's go ahead and add that as true as well and the last one is autofocus so this will automatically focus on the first focusable element within within the tree and we want that as well because we want whenever our panel opens up we want the first focusable element within there to be focused so let's uh let's do that as well okay now let's let's see if that worked so i'm going to tab to it press enter and look now the first focusable element which is the close button is uh automatically focused on not only that but now when i tab through it the focus stays within this panel very cool [Music] it still doesn't automatically dismiss when i press the escape key and it still doesn't close when i press on the background so we'll still need to handle that but our focus problem is solved so that's great and all we have to do for that is use one extra component next we're going to take a look at using a number of these hooks together so we're going to be using the use dialogue hook which in turn relies on also the used modal and the use overlay to work together in conjunction and what this will do is will essentially handle all of the uh remaining accessibility concerns for us so things like um hiding the content behind our panel from the screen readers um making sure that when we press the escape key or click on the outside of the panel it closes and all of those things so we're going to take a look at how we how we can utilize those now i'm going to be relying on the use dialogue example here in their documentation quite a bit um but there's a few things i'll do slightly differently so um if you'd like check out this example as well for uh for more details but so the first thing we need to do is we need to wrap our entire application in one of these overlay providers so an overlay provider basically uh contains um everything that has to do with the overlays uh that utilizes reactaria right so uh how do they behave when there's more than one of them on the page and things like that so let's do that first all right so we want to import our overlay provider and our app.js and i'm going to wrap my entire application in this provider so let's say at the top level here let's say overlay provider [Music] okay the next thing we need to do is we need to include an overlay container so an overlay container will basically contain uh what is the overlay that we want to designate as one unit so in our example this will be the slide over component so i'm going to import the overlay container from react aria and then basically i want this to be the top level uh component in my slide over component so it makes sense to put it as the top level elements and now instead of the fragment we have the overlay container right um so now before we proceed there's actually one thing i need to do um before we can start utilizing the uh the hooks uh i want to do one thing um basically the when i was working through this i noticed for some reason uh the hooks were not working properly when uh when my component didn't unmount completely so we need to ensure that wherever these hooks are used our component will fully unmount and in order to have that i'm going to create another component and call it light over content and it will take in props as one object because we're actually going to be utilizing uh props in our hooks so it just makes sense to use it as one now with that said we will need um we will need well first of all we'll need to copy all of this and let's put it here [Music] all right what is going on here ah right i want slide over content right and i guess our content in this case will be children that are passed to um this component right so we need to pass children down to the slide over content which means that we also need to extract a couple of these props so we'll need one close we'll need children and title from props okay and then we'll need to uh pass those along to our slide over content so title on close just unclose [Music] okay oh and one more thing i actually want to move the focus scope down a few uh because when we open this up i i only want the focus to be within this panel i don't want it to be on the um on the backdrop so i'm going to move this down a little bit down to the uh the section over here okay like so all right next uh we'll need to we'll need to um use a bunch of these hooks together so we're going to use the use overlay use modal and use dialogue and what we're going to do is we're going to pass some of the uh props uh to them so these props will be like title and the on close callback and so on i'm also passing it to uh to it ref to the uh basically our container all right so we'll need to uh we'll need to do these things here so let's just uh actually just copy from the example here and then now remember this will need to be in our slide over content component because we want these hooks to uh run every time the component mounts okay let's change that to const [Music] let's redo that [Music] okay so we can just copy from here and paste it in our code here now i'm just going to change the uh let it go const and use overlay so uh this will be from reactdaria right so we need to add it here and then we're also going to use use modal and use dialog okay so we've created our ref we've called the use overlay hook we passed with our props which will contain our title uh the on close callback and so on and when we get back is overlay props that we can utilize in our components so we'll need to do the same for uh model props i believe let's check yeah model props and then dialog props and title props okay so use mono and then the same thing we're still passing it to the same ref because uh it's just one container that we care about so dialog props and title props and this will be from those dialogue props and okay so now uh now that we've got these uh props let's actually apply them so where do we do that well the our overall container will be this section here so we can just apply it over here so we can say dot overlay props and then we can say dialog props and modal props right and now the only thing left is our title so our title is the h2 over here so we can simply um let's see we can just add it over here title props and i almost forgot we also need to uh apply a wrap right so a wrap uh that needs to be over here where we had all the other props so we're gonna say ref equal to ref okay so that takes care of our slide over content subcomponent so now if we go back to our main component over here there's a couple more props that we need to pass so one of the props is the is dismissible i believe yes so if we look at the use overlay hook and if we look at one of the props that we can pass to it you'll see that one of them is is dismissible so whether the whether they close the overlay when the user interacts outside of it so this is exactly what we want so let's copy that over here let's say it's dismissible and the last thing we want to indicate whether it's open or not remember i said there was a reason why i used the specific names for the props now this is why because these props need to be passed to the hooks in react area and this is also the reason why i left props as a single argument here because but i just didn't want to have to repeat repeat them throughout here [Music] okay now before i save this let's take a look at our current uh current functionality in the firefox accessibility tools so if we take a look at the add to tools here you'll notice that when we click on this notice how dialog is correctly identified right however there's still this section behind that is visible to the to the screen reader so let's see what that looks like if i save and now navigate to it with the keyboard and i press enter [Music] so we see the first element is still focused that's great i can tap through i still have my focus containment which is awesome but now if i press escape the slide over goes away and if i click outside it also closes [Music] right so our our dismiss functionality is working as expected not only that but if we go head over to the firefox accessibility inspector look at what happens if i drill down to where the uh the main content is which is labeled at this section here look what happens when i open our side uh slide over that section goes away right so to our screen reader it's not visible it's one one less tree it needs to parse not just that but check out how it's labeled so it's labeled as a dialogue so it's a very clear functionality and behavior indication to the screeners and also it's labeled with the title that we passed to our component okay so with that we've handled the accessibility part of this component so it's keyboard interactable focus is contained escape key works pressing on the outside works everything looks awesome from that perspective now one last thing and it's not really a requirement technically everything works but we we want our we want our slide over to look nice and we want it to be smooth so let's add some animations now if you remember in this tailwind ui uh code snippet we had these comments that provided the a number of animation properties that we can use so let's uh let's utilize these and for that we're going to use the library called framer motion now framer motion is a pretty powerful set of tools it's a library to handle all things that have to do with animation and we're going to utilize it so we're going to use a component called animate presence and what this does is it basically handles all the animations for you for the components that get removed from the react tree so whenever a component mounts and unmounts uh framer motion will handle everything that has to do with animating the components in and out of the dom with the most reasonable defaults so to speak so you don't have to worry about the intricacies of animating these elements frame promotion will handle that for you as long as you specify you know all the necessary options now i love this declarative nature of it where you can just say what you want done and you don't really care about how it's done exactly but you still have the options of getting a little bit more detailed like we'll see in our example okay so the first thing we need to do is we need to import the animate presence component as well as the motion set of components that we'll be using the first thing in our slide over we're going to import from framer motion and the first thing we'll do is we'll go to where our main slide over component is and just below the overlay container we'll add that where we're uh where we have our slide over content right so over add here and the next thing we need to do is like we'll see in the example here um so motion provides you a set of its own uh wrappers around the common html elements so we have motion.dip for example so we can utilize that in our component and then as you see you can provide a number of animation options uh to it and we'll go over those uh in a second so the first thing we need to do is in our slide over content over here um so actually before we do that if we go back to the tailwind ui and look at the code sample if we go back to these comments about the animations we can we can see what uh what the options that are needed so the first one is for the background overlay so this will be the uh the background when we open up our slide over so this portion here right so we want that background to animate nicely and as you see here we've got the entering animation so it goes from opacity of 0 to opacity of 100 and then on the leaving animation which basically when it closes we want the opacity to go from 100 down to zero and then the animations themselves are easing out and with the duration of 500. so even though in frame or motion we're not using these exact values um or rather the exact syntax we know the values that we need to get so if we go back to our code and within our slide over content the top most do or sorry not the top most but the second from the top this one here right we want to change that to emotion.dip so we still want to apply this these same class names but now what we can do is we can add the options for the uh framework motion so we want to say initial which is what is the initial state that it will be in and as we saw in the uh in these towing ui options we want the opacity to go from zero to 100 okay so we can say opacity zero and now the animation that will be done when our component is mounted we can specify that via the animate prop and that will say opacity and as we saw in the example on the framer motion website it's instead of 100 as one okay and then the last one we want is exit and we also want that to be zero so let's just add that here okay so that handles the background piece now let's check out whether that works or not so let's save that and you already got a glimpse of that there so let's do it again so now if we click on this notice that background faded in right and the same thing with the fade out so that works but this piece rendered quicker so let's handle that part as well now we saw in the tailwind ui code we had the second comment here which is the slide over panel and we see that this is regarding the section so we'll know that we need to apply this to the section element but let's see here the options are on entering we're going from translate x to full so basically this takes up the full width to translate x0 so basically this this will make it animate from kind of the outside of the page and animate it in from the side right so that will achieve that nice little uh animation of it sliding in so let's let's go ahead and add that okay now we use motion.div so we can do the same thing for our section which is this here and i can go and say update tag and i want that to be instead of section i want it to be a motion section okay now just like before we can say initial and that will be x right and we want that to be from 100 to 0. so let's go ahead and do that so we can say 100 and animate will be x of 0. and now the exit animation let's check we want to go from 0 to 100 so we'll say exit is 100 as well okay now one last thing we can do is we can specify the exact animation and its duration as well so we know that we want the ease type to be is in out so we will specify that in our motion component here so we can say transition is equal to and here we can say ease and the type let's ease in out and we'll also need duration which is 500 milliseconds so in frame of motion it needs to be in seconds so we'll say 0.5 and if we save that go back look at that nice animation background faded in and then the main content slid in from the side okay so as a recap what we've implemented today is a slide over panel that when activated notice you'll have the nice animations here so the background faded in with the made content sliding over from the side we'll have the first element within our panel focus right away which is the close button and if we tap through our elements notice how the focus is contained to only the panel so in addition the background content is not scrollable so scrolling is disabled for anything outside of our panel and also if we look at the accessibility inspector here it is semantically uh identified as a dialogue which for the screen readers is the uh the correct identification for something like this and you'll notice the title here uh as expected okay and then the one last thing is the uh our dialog or slide over panel is dismissible either with the escape key or by clicking on the outside of the panel here and then the focus is restored to the element that originally involved it if you're interested in looking at the code of the final result of what we did today the link for the github repo will be available in the description below all right so this will be it for today's video hopefully you found it useful and learn some new things and hopefully this gives you an idea of how to go about implementing a tailwind ui component in react thank you so much for tuning in and i'll see you all in the next video [Music] [Applause] [Music] you
Info
Channel: Mykhaylo Ryechkin
Views: 1,083
Rating: undefined out of 5
Keywords:
Id: 9EqJ-xgmIHc
Channel Id: undefined
Length: 53min 35sec (3215 seconds)
Published: Thu Jan 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.