 Welcome to another episode of GUI CHALLENGES! Where I build interfaces my way, and then I challenge you to do it your way. Because with our brains combined, we will find multiple ways to solve these interfaces and expand the diversity of our skills. In today's GUI CHALLENGE, we are going to... It's not going to be that spooky the whole time, there's just no way. But in this GUI CHALLENGE, we're talking about multi-select. And look at this, multi-select, right? This is like a filtering system. People don't need to be making some choices in your interface to sort of filter a big set of data that you're trying to reduce cognitive overload by giving some powers to the user. And look at these new controls in iOS. These are cool. Love it. So I'm going to tell you how we got these controls, how I set this up. Because look, we have desktop users being empowered, we have mobile users being empowered. Here it is over on Android. Got to love this here. We'll make two selections and look at our filters set here and over here, right? Power through with our keyboard space, everything works just as we want. So there's multiple controls in here. And all of them are just trying to serve these different users that need to make some filter choices that we want their input and they're going to want to skim and make choices really fast and not be bogged down by some sort of, I don't know, really extravagant filtering system. So anyway, this is the one that I chose to build. This was my style today. And let me show you some of the other cool features it has. Like the theme that's in here, right? We have a light and a dark theme. We cover color schemes in one of the earlier GUI challenges. So I'm just going to quote down. That's where all these values came from. Go there if you want to learn about it more. There is a subtle thing though I want to show you in here. And that is if you look at the accent color on these checkboxes here, they match the focus within state border of this field set. And I don't change the focus color of the, and that's just one comes with the browser here. Let's come over here. Ah, see how the focus within is set and the checkbox accent color is coming from the same one. And I just thought that gave a really nice look is like you're interacting with this group here and you're interacting with this group. And the colors kind of come through as this sort of like focus color. Well, it's not really focused, but you know what I'm doing? I'm bringing attention to these areas using like oriented colors that are making them pop off the page. Anyway, it's really easy to miss it first. Not that it had a really powerful effect. And this component is also managing a lot of the states. So if we look up here, look, this is holding on to three items. So this is a state where there's more than one down here. There's more than one here. I'm just going to refresh Firefox. Oh, which Firefox persists your checkboxes like your choices, which is kind of a cool feature, actually. Anyway, so here I am a refresh. I've none selected, which means I see everything, right? And that's an interesting state for this component and this other component to have a relationship with. Now I didn't go into how we built this today. Now this sweet grid is built with Isotope, just a library I love to work with. And it has a sort and filter API that will automatically rearrange all of the items in here. And then of course, you know, I just love delays. So I put a little bit of a delay between each one, which is again part of its API. And it just looks so nice, doesn't it? Anyway, Isotope kick, but if you've never used it before, go check it out. It's really fun. But anyway, the component today that we're talking about is this managing. In this case, the items that are selected, the filters. And so we have none selected. There's a scenario where there's one selected. You can have many selected. And then you can have like all of them selected. And that's just the states that it needs to manage. And the hard part between my solution here is that I have a checkbox system and a select box system, right? This one is using a multi-select. Here we are in iOS, right? And I love this interface. So I think this is just so much better than I would build. But I have to integrate with it as a separate type of component for users that are coming from touch, right? They're going to be very familiar with this interface. This is going to look nearly native to them. And, you know, I think the results are really fast. So I don't think they need anything additional. Plus, you get to save so much space on mobile. Look at all that space we save. Oh, that's so cool. But, yeah, I have to manage two different components. And so that trade-off was something I was willing to work with. And I'll show you that in the JavaScript as I resolve both of the choices from the user into the same object so that I can submit them to a database as a normalized value set. Anyway, we'll get there. But first, let's look at more of the interaction models because there's some cool things I want to show you, like keyboard traversal. Here, let's spend some time in iOS right now. I'll hit tab. I'll hit space. I'll hit space. I'll hit shift tab, shift tab space, shift tab space, right? You can even be using a gamepad right now. Imagine you're on your Switch and you're just hitting up and down in the Nintendo Store, right? And you have different games showing up here on the right. Super easy interface for keyboards, gamepads, and stuff like that. Nothing too surprising. But follow me over to a larger browser where I've kind of fooled my system. And let's take a look. Over here, I'm in the responsive mode of DevTools in desktop touch. So I don't really know right now desktop touch scenarios. So maybe you tell me one where you wouldn't have a mouse or wouldn't have a stylus or something where you're only on desktop. I mean, Windows probably has this. But anyway, in that rare scenario, you may see an input like this one. And this is the multi-select. And here, I have it over here. Select multiple. And this is the default layout you get when something can be multiple selected. Like here, if I hit shift, I can select both of those or I can hit click and just get one. I can command click. So here, I'm going to get 30 days command click and I can make multiple selections like this. But what's really fun is if I hit just down and up here, I can go through all these items on my keyboard. And anyway, I just like showing you this because the grid is so responsive and the choices are so cool that I can hear a whole shift and just go up all down. It's just fun. This is just a fun visual thing to do. And hopefully you were entertained by all the swooshy squares like I was when I realized this. Anyway, let's go back to talking about some of the other features in the debugging corner. Now we got to talk a little bit about reduced motion because you know, I just love that. And today I'm going to show you through simulation in our operating system. Usually you open it up in DevTools, but let's go into accessibility today to display and reduce motion. Pull that back. And what should change? Okay, first off, we see an instant highlights, right? We're not scaling that because why not? That looks great. And when we choose, we see an instant result in our grid. Very nice. So mindful, right? Light and dark. Motion, no motion. We're just flipping tiny little variables in our system to make sure that this all works. And that's so cool. I'm going to go ahead and turn reduced motion off. Go back to the overview. And yeah, that's so nice. Okay, cool. Let's turn off the lights again because I think that's just fun when we do the screen reader experience. And I'm going to go through our checkbox system. Check it out. So here I'm going to dive into Chrome. I'm going to hit Command F5. Multi-select vertical line GUI challenges, web content. All right, we are inside of the web content. And I'm going to tab into our first field set and make a couple of filter choices. Leaving to our item palette. Entering multi-select GUI challenges, web content. Last 30 days, unchecked checkbox. No group. Last six months, unchecked checkbox. Checked two filters, giving six results. Table lamps, desk lamps, unchecked checkbox. Checked three filters, giving 10 results. Did you hear how that's telling me how many filters I have applied across all of there and how many results there are? Isn't that neat? I mean, wouldn't you want to know that if you were hitting filters and nothing was sort of telling you how many were behind each choice that as soon as you made a choice you were reminded how many filters you've chosen. And then I thought that was so cool. The way that I did it is a combination of counters and JavaScript and using some ARIA roles. And by assigning an element, a certain ARIA status, it's able to announce the changes that are happening. And I thought that was just the neatest little experience. So let me go ahead and turn that off. I hope you found that interesting. The article, of course, will have all of it spelled out very clearly for you. But, okay, let's turn on the lights. I mean, it was the spooky episode. Oh, so maybe we should leave them. No, let's turn them on. Let's turn them on. Okay. Voice over off. That was nice. All right. Next, I want to check out the right to left. Let's go look at a bigger browser. I'm going to open up the DevTools. And notice we have a select element here with all the option groups. And that's how you get all those different grouped areas. Anyway, cool feature. Okay. Right to left. Right to left. Here we go. And, well, look at that. Isn't that handy? We hover on each of our labels. They automatically highlight the checkbox. And if we choose them, we get a nice filtered grid. That's just so cool. If you've got a keen eye, though, do you see the bug in the grid here? This is isotopaling it out, not CSS grid. And these two squares should be over here. Because the inline start is here, right? This is the directionality now is going from right to left. So interesting, right? By using a library, which gave us a lot of cool tools. It actually is hindering some of our internationalization of our content. But maybe it's not hindering it. But in this case, we can, you know, maybe someone would notice. But kind of cool. Still all of our styles here in the sidebar and the multi-select and just sort of that interaction we want, that though all works in right to left. Let's go back to the left to right. Nice. Now the layouts in this multi-select scenario ended up not being that exciting. So we have the body in the main. Those are centering all the content here, putting some space between our grid and our header for this little layout here. But if we go to the side, the side has no special layout. Other than, you can see our counter reset though or filters counter set. So we were talking about that earlier. Our form, though, does have a layout. And so we're using the form to group all of the input types. So we're trying to collect information from our users and putting it into one spot so we can just use the form as an object for kind of querying what the values are for these. But look, it's a grid. It's a grid has a gap. That's nice. Look, I can drag the gap. Wee. The new length tools looking sweet and dev tools. I don't know if you tried it yet. It's also got a type pop up. Look at that. You can change all the different units right here. So in case you're even learning units, they're right there. Okay, anyway, enough fan boing about the length tool. This though is interesting. So display grid, not interesting length tool. Well, that was, I think very interesting, but the max inline size at 30 characters. This is kind of crucial in that I'm setting the sidebar size on the form with a character unit selector or character unit, relative unit, which is sort of like making sure that the items here never go beyond a certain width. And I think that's really normal for a sidebar to sort of have a max width and then you let lines wrap for these different label elements. Anyway, so that's how I did it. It was with a max inline size of 30 characters. And I felt like 30 characters was a good size for showing a filter in a sidebar. And that sets pretty much the width for the entire thing all the way down. Kind of interesting. So here let's look at a field set. Field set just has some spacing. Nothing really that interesting here. We're using two, I love using two characters everywhere. It's just sort of a great unit. The legend here that's inside of this field set. Now it's not necessarily layout related, but look at how it sits in here. It's a very unique way that it's positioned and it's unique to the field set and legend. This just comes free with the browser. And I thought it looked really nice here as we're not only visually grouping the elements, we're giving it a label, but that label is also read to screen readers. And so when it said, you know, last 30 days, that's what this one is. It's like a new, this is a new category section. And so new is what's written here. And screen readers and, you know, sighted users are all going to get to see this value. And I just thought it worked out really nice that way. And down here, this is just our label and our checkbox. We're using flex and they're aligned to the center. So it's just really cool, right? So there's our layout, nothing really too surprising, but really stable and really nice for us. Now there was like one kind of crucial thing that I do want to go over, which was toggling the visibility of this select up here. So by default, the select is set to display none because we're kind of assuming a user is coming with a mouse. Now, if they're not visiting with a mouse, they're visiting with pointer course, let's go see what we do. For example, here in the field set. So our field set, here's all of our styles. We have this media query called use select. So if we're using the select in this particular use case, so this would come back as, you know, true or false based on if the user is using a mouse or if they're using their finger. And if they're using their finger, we want to set the field sets to display none. So no checkboxes. Those are just too tedious for your finger. And we'll go turn the select element on. And it can now show and be the dominant way to put input into the form. So that was it. I use custom media up here with the rest of my stashed custom medias like motion okay in dark and light, which we use in all sorts of episodes. And this one is called the use select. And I just thought it made things nice to read. Time to talk about JavaScript. I'll just try to briefly go over because I think what's more interesting is the results on the console. So here's where I'm importing isotope. So I initialize isotope here, give it some of my preferences here that I use to make a grid. And then here's my filter grid function that gets called with the sort of things that's trying to be matched. And here's where I check prefers reduce motion on the client. And this is where I set the new filter. So I range I set the new query that's going to set what is to be shown and what's not. Here's the stagger which changes the delay for each of them by 25 milliseconds. And then the transition duration which I set to either zero if motion is not okay. Or I set it to something if it is okay. Down here I like prepare the select options. So when you use a select element there's a way to get all the values out of it using element.selected options. And here I make an array from it and sort of push things into a data format that looks a lot like what the form is getting with the checkboxes. Here's where I'm watching the select to change so that I know if I need to go prepare the values. Then here's where I'm invoking or creating a query and then invoking isotope to filter the grid. Down here this is the checkboxes. So the checkboxes is watching all the forms for input whenever the checkboxes change. We go grab form data for the whole form and we output a new object to the console. I'll show you that in a second. And here's where I create another query this time again for isotope. And I set the filter here. And then down here at the very bottom a query selector applied filters text content. It's giving this many results. And so this is what's spoken out to the screen reader because it's being inserted into an element that it knows to announce to the user. So we modify it with CSS and JavaScript in both those combined into an announcement to the user. Okay, let's go look at the results in the console because I think it's kind of fun. All right, let me pull open the console hit escape down here. So we pull up in the JavaScript. Look, we've already been making some choices but all of our choices have been checkboxes so far. So if I hit refresh, well, I want to see some grid items. There we go. And if I check one, I check two. Look, we have an array. There's the group and here's the value. Here's the group and the value last 30 days. So this means that they're on, right? These are binary. So these are only if they're on are they going to show up in this list. And that was the way that the checkbox element and the form element reported these. So these could be submitted to a server. Let's fool the browser a little bit here and change some of these. Great. So now I have multi-select down here, right? So I've named them in my console warning. That's what's giving me this nice little yellow here. And if I twirl this open new last 30 days, last six months. So I'm making sure that the data structure that's getting created by the multi-select and the data structure that's being created by the checkboxes are the same thing so that it can submit them to one place and that API only has to care about one type of filter set or one type of sorting set. But my interface on the client side can sort of do the hard work to manage a touch input and a desktop input and a gamepad input in all these different interfaces on mobile and tablet and desktop and combine them into one so that the server doesn't have to care, right? The server doesn't want to have to care that there's a user using this brand new input on Android or they're using a brand new input on iOS. They just want to get some values and show them to their user. Just really really neat stuff. So I hope you enjoyed this multi-select episode. This is a fun type of user experience that I've built so many times over the years and I know you've built one to send it to me. It can always make for these really neat interactions, right? Where we're just sort of like going in and showing and hiding different elements based on selections. What have you built? I'm dying to see it. Dying to see it! And I hope you have a good holiday and take care y'all. I'll see you in the next GUI Challenge.