 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 creative minds combined, we're going to find multiple ways to solve these interfaces and expand the diversity of our skills. And today's GUI Challenges, split buttons. Here is a split button, a primary action, like viewing your cart, you know, the most used action with a tucked away set of secondary actions. So in this case, we have checkout, quick pain, save for later. I think a really good example of a split button that you probably see all the time is the send action, where the send is the primary email action. And you have these additional options to save a draft, delete it or schedule it for later. And I think it's really important that the interface isn't being crowded constantly with all of your actions. They're tucking away some of the secondary, less used actions into a submenu. And if you're getting really fancy, I mean, you can promote things from a secondary action to a main one. Like I think that happens in GitHub. If I often squash and merge, it becomes the primary action. And that's just really nice that the application can kind of give me secondaries as an initial way to introduce me to actions, but then sort of promote them up into a primary one over time. Super cool. So anyway, the split button is full of all sorts of little nested components like we have this pop up, we have buttons, we have SVG, we have hover effects. We have all of that stuff. So you know where we need to go to talk about all that, right? We got to go to the debugging corner. Boom over here in the debugging corner, the safaris on top. Firefox in the bottom left, Chrome desktop, Chrome on Android. Got our nice little environment set up here with all of our actual browsers. Okay. So I'm going to pop up in the dev tools on Chrome here and start talking about the theme. If you notice, we have a light theme and a dark theme. The light theme is very bright and vibrant. The pop up is like a white card. And on the dark theme, we have a desaturated color set, still blue. We invoke the background and we get a nice dark piece of paper, right? We're in a dark theme. So how do we create these surface layers and how do we create all these interactions? I did it all with HSL. I really love desaturating the dark themes and I really like flipping, mostly lightness. So here, let's open up. I'm going to hit command shift C, grab our gooey split button here. And here's, let's look at the colors. So the light theme down here, you can see we have lights, lots of vibrant colors, a nice bright blue. We're getting into navies and some like light grays, but a few different blues here that seem all quite saturated and vibrant. And then up in the dark theme, look at how they all look desaturated. And we can even look at the values. Let's see. So hue, saturation, lightness, there's three channels in here. These are 75%, 75%. All of these are 75% saturated, which is pretty saturated. And up here, they've dropped down to 50%, 50%. Oh, the theme active is still 75%. So when I'm actively pushing it, oh, look, it even looks a little more saturated. I don't think that's too saturated though. It looks great. Well, anyway, I made the colors so that better be the way, right? That's how I did some of the colors. And these things just get passed around all the way down. There is one interesting concept though here, which is I liked this color here on theme. So that way, and look, this is also not black. It looks very black here. And this one also looks like it's like a really dark gray. But if we look in here, it's 90% saturated. That same blue hue, it just has 5% lightness in it. So it's very, very dark color, which makes it a really rich, dark navy. And that's nice because this is a dark navy sitting on blue. I just think that those always look better when it's not black on blue. You're doing a really, really dark navy. And as long as you can achieve your accessibility contrast scores, which we do on this show all the time with the same technique, I think it just ends up being really, really nice. So there's a couple of color tips in there for how to do in a light and a dark theme. And next I want to talk some of the shadows that are in here. There's some really interesting shadows. So let's go to the light theme first to talk about some of the shadows. The first one is you can see on the button here that the text has a little bit of a text shadow on it. Now the dark theme doesn't have that a dark theme with text shadows is kind of hard to do. I found that if you add a light text shadow to a dark button, it looks like it's embossed instead of where it does here now in the light theme where it kind of looks like it's sitting on top. And that embossed effect can be nice, but that's not really what I'm going for here. But anyway, I thought the text shadow was really nice. When you hover, that background text shadow becomes flat because it matches the same as the hover color. So it kind of disappears. So it's like the text pops until you hover and then it just sort of is. And I don't know. I thought that was cool. Another thing here is if we pop this open, we look at the shadows on this pop up. If you look really closely, it's not a black color. There is blue in there, right? There's a shadow being cast off of this and it's not ever going to be just white or black. There's always a tint of color in your shadows. And so I brought a little bit of our brand hue into the shadow even. And here it is being multi layered on its way down. And I thought that looked really good. And lastly, if we hover on these buttons, we can see a little bit of a text shadow on them. Right. Let's see. Yeah, just a little bit of a text shadow there. And I thought that turned out really nice. Now, the dark theme does have some text shadows. We use a shadow here. So notice the shadow as this pop up, pop up, pops up and look at it layer on here. So it's a really dark blue color similar to the other one. But it's it needs to be a little bit more dramatic to sit on black, but it also needs to sit on the button. Anyway, I thought that just turned out really nice how that worked. And if you look at these buttons, when they're not hovered, they're getting a little bit of that text shadow. Also, the icons have a filter drop shadow on them so that the shadow can follow the shape of the SVG. Turns out looking really sweet. So those are just a few of the shadow tips in here. I think there were little details that end up going a long way and making this thing feel really refined. And you can find all that code in the article, the colors and the shadows. I think they're just ready to take if you want. But always think about HSL and how you can how you can bring your brand color into these little thoughts here. And speaking of little details, we got to talk about some of those SVG little details here. Let me let's invoke this button with the let's see, hover focus within. Yeah, OK, so now I'm going to Command Shift C and find the SVG in here. I'm going to go to the SVG. OK, I'm going to stroke stroke down. I'm going to scroll down. Oh, that's so funny because I'm looking for stroke line cap, stroke line join and stroke width. So the width by default might have been like one pixel. And I was like, oh, that's just too thin. Let's give those a little bit of a boost to two pixels. Now, critically, I have stroke line cap and stroke line join set to round. And let's talk about what that means and how it works. So let's go bump up the size of our icons so that we can see our changes here. Excellent. That looks like it's plenty. Now I'm going to go turn off both of these and talk about what I see. And maybe you already saw the difference, but look at the line end here. So this is the line cap. And now we have a sharp ending right here. And if we look down on these ones, see, we have two little sharp endings on this horseshoe. And here we have a pointy connection point where these are joining. Now, what we do with round is we're telling both of these scenarios to round out those edges and watch what happens. Look at that. It's just a slightly softer edge and overall icon effect. And I just think those little things can really make a big difference. Let's go back down to two characters. And that was just a small tip about SVG. I wanted to share with you. I thought that was really important. That combined with the filter drop shadow just made for a really cool effect. I thought even more little details continue to go into all of the states that this thing handles. So let's check out the state. So we have like a dark and light theme. We're going to, of course, have reduced motion and we'll cover that in a second. But let's talk about all these different interactions that need to happen in here. We can see that there's a hover effect. If I click, there's an active effect. And here it is in the dark or in the light theme. If I hover and I click, I get a buttons. And I think also, in my opinion, clicks and hover events should increase contrast. So if you look to see like what I'm doing here, I'm trying to make sure that I work and hover towards a color that's going to make the button more legible instead of less legible. Anyway, I think that's just an easy mistake to fall into sometimes. And to get all of these effects in a full view here, let's open up our special little like state emulation tool and DevTools, which I love and just click through some of these. So let's go to the button and the button's going to, of course, have a hover effect and we can see here's the hover changes right here. We have a theme hover color and a theme on theme or color called on theme. And that's giving us a nice contrasting color. If I hit active, we're going to set the background to something a little bit brighter so that you can see your interaction there as a user, right? As you're clicking or you'll see as you're using space bar from a keyboard. Okay. So we'll get rid of those. We also have focus within. And so focus within is being used on this one. Focus within is going to prompt the pop up at which point we let's pull this down a little bit. We could dig in and see the pop up here. Yes. Right. So if the gooey pop up button is focused within, then find that pop up itself and bring it in. And so we're setting it to translate zero. It's opacity one. And we're giving it a speed and that's how it's showing up that way. Also knows pointer events is set to auto because when this thing is hovered out, we don't want any of those buttons to be interactive, right? That would be a bummer, which they are by default. I have to go turn those off. So if we come here to the pop up, we can see that it has pointer events, none opacity zero, right? Because we want these things to be not interactive and needs to be invisible. And look, I can hover on the buttons right now. And we also want it to be not interactive. So kind of tricky, but that was just a small thing to get in there. And I thought it turned out really nice. It was pretty easy to manage. So let's go back to invoking our focus within on our buttons and then find our way down here into some of these buttons. Because of as these get hovered, look at their state. Oh, look at their styles. Oh, nice. We can share some of the styles down here and hover and active. Excellent. See those pop in. And we have focus visible as well. I think we skipped focus visible on our upper button here. Let's check that one out. Focus visible. I liked this focus visible state. We can go look at how I did it as well, because I used a outline offset of negative five and negative five was kind of nice because instead of me trying to hit focus and have it crawl outside of my little viewports here, it's going inward and it still has a lot of contrast. And so it's able to not leak outside of the container. It's in while still providing nice ample focus. I thought that turned out really nice in this particular component to have this sort of inner offset for the focus. So that is most of the styles here, I think for like emulating the different states that we have the different interactions. We've seen a lot of the mouse interactions here. Let's talk about and show some of the keyboard interactions. So here, if I tab into here, you can see my tab focus. We were just emulating that, but now it's actually tapped because I used my keyboard to go in there. So it knows that it should be showing me that focus. That's the difference here in focus visible. If I hit spacebar, you can see me invoking those buttons. That's kind of nice. And if I hit tab again, I'm using my roving index library. My roving index library looked for focus to hit this element. And then it's going to forward focus into this button list. And we'll do the screen reader flow in here in just a second. But now inside of here, I can hit up and down to go through my buttons. I think you can also go left and right. Sure can can go up and down or left and right and find the button that you want. You can hit space to hit it, space, space, space. You can enter to hit it, which doesn't show the prompt, but it does push the button. And then, of course, you can hit escape. And if I was to come over here and hit escape to bring up the console, look, we can see all the buttons that I've been pushing. So there's definitely JavaScript waiting and is aware of these don't hear you, Kurt, is aware of what button is pushed. So, I mean, of course, you're going to need to take some action, right? So that's all handled in my JavaScript. But the roving UX, I thought was really nice. And what, you know, just that kind of cool feature that we got from other episodes is it saves its state. So here I have delete as the secondary action already focused. If I go back into it, it's still focused. So it's going to remember where you were. And that's just cool stuff, right? So we covered keyboard. We've covered mouse. Let's reduce motion. Let's say we'll pop up in here into the rendering tab. We'll scroll down. We'll say reduced motion. And here we'll emulate the light color again, just because it's nice. So we saw before that when we weren't emulating reduced motion, we were getting a slide up card here. But now it's just going to fade in. We're just getting a simple crossfade. So no motion, but we're still getting an animation. Now I left this as spinning still. And I thought that was just something that there's not motion here that's going to create a sickness. I didn't think this wasn't a sort of scrolling or a big amount of surface area that has motion. So I thought it was nice to leave that in there. Now, someone can comment and let me know if that's not going to be OK. But from my research and the folks that I know with this, a small icon rotation should still be OK. So let me know in the comments what you think of that design choice. Also notice that the if I don't emulate motion that it animates in at a different pace that it goes out. So I thought that it was really nice to sort of bring in something very calmly and slowly. It still has a nice pace, but then to dismiss it very quickly. But I don't want to dismiss it like instantly. I just wanted to have like a nice slow, I don't know. I wanted to be able to tell that it was dismissing, but have a nice slow introduction. So those are just some of like the animation considerations. I didn't do any color animation. I just have instant color animations, like interactions, because sometimes I like those a little bit better and they're a little bit less for like the GPU to do. So the user is not really going to care if there's like 300 milliseconds of hover time here. They're just going to make sure that the hover is there and that they're getting some feedback that that element is interactive. It has states like click states and it lets them know that this is a button. Speaking on whether or not and knowing if something is a button or not, let's check out the screen reader experience. I'm going to hit command F5 and invoke the macOS system one and try out the UX for the split button. Leaving DevTools, entering split buttons, GUI challenges web content. View cart button. Check out button list three items. You are currently on a button. To click this button, press control option space. Quick pay button save for later button. View cart button. And that's it. As we tabbed into it, we were told that it's a button list and how many buttons are in there and it did that based on some HTML and a few attributes. Save for later button list three items. You are currently on a button to click this button. Press control option space. Quick pay button. Pretty cool. Someone hit escape and close that and hit the hot key to turn off the screen reader. Voice over off. Even more detail can be put into this though. We are not done. We can handle right to left. So if I pop in here and I go to the top of the document and I change the direction here to right to left and hit enter, I can see that my button, which is using logical properties and a few other things is still usable. And look our icons have changed sides. I didn't do that. That was just flexbox. This button even being on this side changed because of flexbox. I didn't do that. I didn't have to change order or anything. What I did have to do though is make sure that I specified the rounding corners appropriately per logical properties so that this could be right to left to have the right borders and left to right to have the right borders, even this border side here. Let me inspect this. We'll go to this. Can we pop up a button? Let me take out the hover states. Let me close the console, pull open the styles more, scroll to the top. And we're looking for border inline start. Here it is for border. And if we go look, this is probably like one pixel solid theme border. Yep. And so there it is. That's instead of using border right or border left. I used border inline start. And now as I flip the direction on this from right to left and left to right, I don't have to care. I actually got to deploy less code and think about less stuff while reaching more people. And that is the power of logical properties in CSS. So that's how I handled that. And the pop up does use physical properties left, right, top and right. So if you wanted to do something a little bit smarter in here, let's go to right to left. In this mode, you could the pop up is locked to the box that this button is coming up inside of. So that's why it doesn't look like it's too far off here. This looks like a fine layout. And I thought it was fine. So you could though, write a media query and adjust this if you wanted to and make it a little bit more specifically positioned. So that's how I handled right to left. I got it mostly for free with flexbox. I love it. Speaking of flex, we got to go check out these layouts that are in here. So let's just check out one of these buttons. We've got the GUI split button. It has displayed flex already. So here it is display flex. And that's it for that style. Let's go to the layout panel actually and kind of hover over these individually, right? So okay, so here's our split button. That was not a whole lot of looking doesn't even show any alignment items in there because it's just a flex. And it looks like it's just making these sit next to each other. And we get the directionality for free and right to left. Okay, every button is a flex layout. That makes sense because especially because you're going to want to align item here, let's go to it. We're going to want to align items and put some gap in there between our icons. Yep, there it is. So here's our gap. And here's our align items to again display inline flex. Okay, let's go back to the layout panel. Let's look at the pop up button. Okay, so that one looks like it has some padding and probably some alignment properties. Let's go to the styles here, display inline flex as well. Align item center justify content center. So it's getting a centering here. Oh, look, we can hover on these to see. They're affecting our align item center and justify content center. Excellent. And let's go ahead while we're here and pop open the states and go focus within because we're going to want to look at the layouts of the pop up here. So here is a gooey pop up, right? That's a UL, right? This is a list of items. And we have no gap between them because look at the hover here. Well, it's pretty much going edge to edge for each button. Let's go look at the styles here. Styles we have, we've got display flex, flex direction column. Oh, that makes sense. And that's it. Again, a pretty light amount of layout styles being done here. This one is positioned absolute. So I usually don't position things absolute in this show or just in my UI in general. But this one ended up being an easy exception because the whole pop out is coming out of this little button here. It just seemed really nice to anchor them. It just felt anchored to the element. So I'm going to position it absolutely and anchor it to an element. It seems kind of straightforward. And the effect was really easy to manage. And I liked it. Okay. So let's see, layout panel probably got one more to look at here. We have the gooey, I know there's just buttons inside of there. So it's just a flex list, a UL flex list of buttons. So really there's like three or four very, um, essential display in line flex layouts that power this entire thing, except this one here that put them in display in a column. I mean, that was not that tricky right here. We go flex direction column. Let's, let's change the direction here to row. Ooh, I know that's interesting. A little pop up row of buttons. That's actually kind of neat. I could totally get behind that. Anyway, there's the direction that we originally set it to. So those are all of the layouts that are done to create this. And I thought that they were really kind of digestible for the first time. Um, everything was really nice. And we got a really powerful layout back. Let's change this back to the left to right. Left to right. Excellent. Well, now's the point of the show where we got to leave the debugging corner and go check out some of the JavaScript that powers these interactions, follow me to my IDE. I used two of my utility libraries to kind of help me, um, make this code a little bit more succinct today. The first one is called bling bling. And really it just gives you, it gives you this dollar sign, which makes selecting elements easier, putting some events on multiple elements easier, and it just has like a couple of conveniences that are sort of leftover from the jQuery days. And then we have this one here called roving index, which we've talked about on the show before, which is what's maintaining and enabling a roving index UX on that pop up. So the first thing that I do is I go grab the split buttons. So this will grab every one of the buttons on the page. And this will grab all of the pop up buttons. Now for each pop up button, we want to give them some roving index, right? So when that pop up button is focused, so here's the element. This is the pop up button itself. Uh, we forward the focus to these targets, to these buttons, and then the tool will maintain all of the different state inside of that target set. So that's how the roving index was set up. We also want to support that escape key. So on the pop up buttons, we're going to watch to see if escape gets pressed. So this is the thing that's prompting the pop up itself. We're watching for the escape bubble to sort of like come up into the parent element here. And if we see the character code as escape, we're going to blur on this item itself, which will, uh, remove focus within and therefore close the pop up kind of neat. Here's another one where we're explicitly on focus in setting some attributes, uh, so that a screen reader can still reflect the accurate state of the pop up, right? Someone can't see. So you have to set the state to expanded and set the expanded state to false, um, when it's opened and closed, that way someone who can't see, right, again, uh, can acknowledge and know the state of this element. And then last year, this is just some demo code to watch for clicks on these elements, but we're watching the split buttons and on click. Um, as long as the node name here is not equal to a button, we're going to, uh, load and console log the target text. So this is just saying like, Hey, the, you know, play button was pushed or the send button was pushed. And, um, this is filtering out anything that's not a button since we're using bubbling, we're watching for all the clicks. You could click on the very edge of the pop up and, uh, this wouldn't invoke any button texts because well, you didn't, you didn't click a button. So the JavaScript, it wasn't that, um, complex or a whole lot to put down, but I think it did add a whole lot of value, right? We're adding some unique things to, um, keyboard interactions with the escape key. We're adding some unique attributes for screen readers. And we're also tying in our clicks and making sure that we're getting some, uh, nice experience for mouse and keyboard users alike. And that is the end of this gooey challenge. I hope you liked the split buttons. Now it's your turn to fork, like, subscribe, do all that sort of great stuff, interact with this content, leave me a comment and show me how you would do it. I mean, that's the most important part here. You need to tell everyone and show everyone how you do it. What is your style? All right, y'all see in the next gooey challenge.