
How to make your Python Dashboard look Professional! (Layouts in Shiny)
This is part 3 of our multi-part series on creating professional dashboards with Shiny for Python. In this video, we focus on enhancing the visual appeal and structure of your Shiny dashboards using various layout components. We'll cover: - Implementing layout templates for quick setup - Using cards and sidebars for a clean, organized look - Customizing columns and grids for better data presentation - Adding tab options for multiple views within a dashboard By the end of this video, you'll have a more polished and professional-looking dashboard, setting the stage for advanced visualizations in upcoming videos. Shiny for Python Homepage: https://shiny.posit.co/py/ Access the GitHub repo with all parts of this project: https://github.com/KeithGalli/shiny-python-projects Check out the complete documentation here: https://shiny.posit.co/py/api/express/ Video by @KeithGalli Video Timeline! 0:00 - Video Overview & Progress Thus Far 1:28 - Using Shiny Templates to Get Started Fast 3:21 - Using Layout Components to Customize our Apps (Cards, Sidebars, Tabs, etc.) 7:55 - Adding a Sidebar within a Card 12:38 - Adding a Card with Tabs to Display Various Visualizations 17:35 - Structuring Data in Columns / Grids (layout_columns() & layout_column_wrap()) 26:30 - Final Touches & Tips (Filling in Visualizations into our Tab Views) Stay tuned for part 4, where we'll add more advanced visualizations, and part 5, where we'll focus on customizing styles and adding final touches. If you enjoyed this video, give it a thumbs up and subscribe to the channel to stay updated! All videos in the series: Part 1 - How to Build, Deploy, & Share a Python Application in 20 minutes! (Using Shiny): https://www.youtube.com/watch?v=I2W7i7QyJPI&t=0s Part 2 - How to make Interactive Python Dashboards! (Reactivity in Shiny): https://www.youtube.com/watch?v=SLkA-Z8HTAE&t=0s Part 3 - How to make your Python Dashboard look Professional! (Layouts in Shiny): https://www.youtube.com/watch?v=jemk7DoN4qk&t=0s Part 4 - How to combine Matplotlib, Plotly, Seaborn, & more in a single Python Dashboard! (Shiny for Python): https://youtu.be/xDgO5hB4-VU?si=kk20yhdpsBqkMYcC Part 5 - How to Perfect Your Python Dashboard with Advanced Styling! (HTML/CSS - Shiny for Python): https://youtu.be/uYZUS-eFbqw
image: thumbnail.jpg
Transcript#
This transcript was generated automatically and may contain errors.
Hey what's up everyone and welcome back to another video. In this video we're going to learn how we can make our dashboards in Shiny look a lot more professional and that's using layouts. So as a reminder, basically in this video series we're working our way up to build a dashboard that looks like this. And in the last video of the series we kind of had a dashboard that looked like this. We focused on reactivity and you know making these toggle inputs that could dynamically affect our graph. So we're going to build off of that in this video and we're specifically going to look at how we can start structuring things more professionally using cards, using sidebars, using all these different layout components that are available via Shiny.
It makes a big difference when you start using these components to make your dashboards just look much better. We're not going to completely finish our app today but we'll have templated components that we can fill in in the videos four and five. To get started with the code you can go to the GitHub repo that is associated with this project and all the different parts are listed here in the readme and you can find the finished source code from each part. So feel free to jump along, jump in at any point, but we'll be working off of the part two code so you can go here to access that. All linked in the description.
Using templates as a starting point
When thinking about how to format your dashboards and applications professionally I like to start at the Shiny for Python homepage and I think probably the quickest way to get a nice looking dashboard or application is by going into components and going to templates. So here you'll see a bunch of different starter apps that if you have a specific goal in mind these are probably pretty good to kind of take the exact source code and kind of run with them and fill in your own graphs and charts and information as needed. So for example maybe I wanted to just take this basic dashboard. I can click on it. I can copy this terminal command. I can go over to Visual Studio Code and I could do something like paste in this command and go ahead and run that.
We see now we have this dashboard app in the folder that we're working off of and if I run the app.py there, open up the specific file in there, and we're in the dashboard folder. First step we'll need to do is install the requirements from that template. So we can do pip install requirements.txt and it even suggests that right here as we can see. And now we should see this FA icons is installed properly. That was the only I think library that we didn't have. And we can go ahead now and run this app and we see we have that dashboard that was in the templates.
So if I was working on my own, I might take a dashboard like this and fill in the information specific to the data set that I need, but it gets me started and have something to work off of super, super quickly. So really suggest templates as a good starting point and there's a bunch to choose from.
Adding cards to organize content
But let's say we have a template that we want to run. So let's say we had something completely custom in mind. What would we do in that situation? So kind of thinking back to our code from the last video, we had some graphs already started and maybe we want to put that in a specific way that isn't, there isn't really a good starter template for us to use. Well in that situation, and I'm going to go back to the code real quick so we can see what we're working off of. Hide this dashboard real quick and we're going to go into our sales folder, go into the app there, we're going to run this app.
So we have this dashboard over here. So how could we make this look just a little bit more professional and customize the layout, everything? Well for that purpose, I would go into components and I would go into layouts. And in this layouts, we see kind of a cheat sheet of the different options that we have with layouts. One of the things that I would really start with is cards. So we can see we have a bunch of different card options as we look through this. So like sidebar within a card, even just contents in cards. And for me, when I think of cards, I kind of just think that it isolates the different pieces of our application. It just makes it cleaner, easier to look at.
So I like kind of to start with putting things in cards. What would that look like in our code? Well, as we can see with this dashboard that we have currently, it's all just kind of scattered along. So I think that we should group things that are similar into their own card. So like the number of items here should be in the same card as the graph here. Same thing with the city here should be in the same card as the data and visualization here. And we can actually already see that our data frame already has a card around it. So that's nice. So let's go ahead and do that.
Well, how do we do that? Well, we can click on content and cards. We can see that there's some example code right here. And it's actually using columns, too. And we'll kind of get into columns in a little bit. But if I just use this with UI card, we can start adding things directly to that. So we see that there's also a card header property. You could add text to your cards. And we see that here and here. So it's good to always look through the documentation on these cards.
So I'm going to copy the with UI card. And I'm going to put our number of items and this graph into one card. So we could do that by doing with UI. And we imported UI from up here from Shiny Express dot card. I want to render that plotly. So I'm going to nest that in here. And I'm also going to put the input control, the number of items here. We'll put that in the card as well. So we need now we need to delete it from here. OK, rerun this. And now we see it's nicely in its own card. It's a bit more isolated from everything else. So we should do the same thing for the select a city option.
So again, you can just copy the same thing with UI.card. Nest this in. And I'm doing highlighting it all and then doing tab to indent it and nest this in. And now we have another card. Nice. So that looks pretty good. All right. What else do we want to do here? Well, I think first off, I want to change this to video three just so we know what we're talking about here.
OK, what next? Well, if I'm going to make this look a little bit more professional, I think I might just kind of get rid of this make bars red. I feel like this is kind of weird to have just sitting in here. So I might just remove that quick as we start formatting things more. We'll play around with the style and the colors in the fifth video in the series, the final part. And in that you'll see all these different ways that you can really customize the various different graphs and styles that you use within your Shiny application. But if I was to remove this, we would also need to remove things that depend on this input. So if you remember, we had this update traces in both of our charts that leverages that.
Building a sidebar layout
All right. Well, we're ultimately working towards a dashboard in this video that kind of looks like this. So we want to move up our city to the top. We want to move this down and have another column here for a heat map. And we want to have a card that's kind of listed out here that we can start playing around with. And we also have these toggle options.
OK, so how can we start doing that? Well, let's go back to our components and see what different layouts that we have access to. And we see like sidebar, collapse sidebar, navbar at top, navbar at bottom. So looking at our final dashboard that we're working towards in this video, we have a card header and a sidebar in the first card. So let's try to make this happen using the components we see in the documentation. So we have sidebar within a card. Maybe this would be helpful for us. OK, I'm going to go ahead and copy all of this into our code and paste that in.
Let's see what that looks like. OK, so what we wanted to have is have our input within the sidebar. So I'm going to paste this in the sidebar. Make sure it's nested properly. That looks good. We want to have our chart in the content area. So I'm going to paste it with the same level of nesting that the little preview text had. Run, save that.
I guess it's running into an error maybe because I had an extra floating UI card. Save that. We see now we have the chart within the sidebar. I realized I actually put the wrong chart. I wanted the other chart in there. So I'm going to quickly undo things. And actually paste in this UI input select ties into the sidebar area. Nest that in. Now we see we have the city in there and the card content still floating here. So I need that now to post in this render plotly function into the card content area.
And I like the text can be used for placeholders because it just makes it a little bit, I feel like easier to know where you should put things. And you can always use the text as a placeholder if you haven't finished all your graphs yet. Cool. So I'm going to go ahead and paste that in. That looks good. We're running into an issue with our render plotly, and that's because we actually accidentally deleted our input. So I just need to quickly paste that input back in into this card.
All right. That looks pretty good. I can extend this to kind of see it already. We're doing pretty well. I want to just run this from scratch again real quick. Cool. That looks good.
One thing that it's worth mentioning real quick with like these sidebars is you always can go into your sidebar into your function. If you have a platform like Visual Studio Code, I'll show you some of your arguments that you can use. And one that I sometimes like to use with sidebars is make sure that by default it's open. If we look at this, if I change this to false, when we render this, it will start closed. It looks like we have an error. It's not open equals true or false. It's the actual text. So I can say it starts as closed, for example.
And we see that we only see like Boston and I don't like it starting as closed because I feel like it's not clear that you could even do this that way. So like I would want to ensure that it is open to start. And so you can do that. Make sure you enforce that with this. It's good to know these keyword arguments.
All right. Now we have this. Well, if we look at our kind of final chart, if we look at our final chart, we see we also have a header here. So you can add that very easily by doing. Oh, I guess we already have a header. We can just change this to sales by city 2023.
Cool. Now let's see what else is different in the chart that we're doing and kind of how I would think about this if I was to do this from scratch. I know we're kind of working off a template here, but I feel like you could like use even a piece of paper and kind of sketch out what charts, what visualizations you want there. And then kind of how I'd approach it is I'd probably stub out what that looks like with cards and stuff and just have pieces of text as we can see, like a piece of text here with the heat map here. And then when I'm actually filling in my graphs and stuff, start putting those pieces in. That's how I like to kind of think about styling and all that. I like to kind of have my placeholders first and then it's just a matter of filling in the graphs. But everyone kind of has their own personal preferences here.
I like to kind of have my placeholders first and then it's just a matter of filling in the graphs.
Adding tab panels
OK, so but we see that this has different tab options, which I think is pretty a pretty cool feature. And we also have this number of items control here that adjusts and plays around with all of them. So let's start working towards this. What does this look like? Well, going back to our documentation, Shiny deposit code slash pie slash layouts. We scroll down, scroll down. We see that we have all these different tab options. Maybe we want to take a card with pill tab set, for example. And I can go ahead and copy some of this code.
Copy it. And we're ultimately going to do it in the second area where we currently have this card. So if I just added this as is, what would it look like? We see we have that all working, so it's nice to test how that works. That looks pretty good. And what we could very easily do is we could just paste in our graph code and nest that within one of these tabs. So now we see we do have this graph right there.
And we kind of have placeholders for the other pieces of that. And if you have a keen eye, you notice that the one that we're actually working towards with this template is this underline now set. So there's just different styles of tabs. Everyone can have their own personal preference. I kind of like this underline style. So really, there's only a small change we need to make right now. We have this nav set card pill. But if we look at the documentation, on these relevant functions, we see that there's also this nav set card tab or actually wait, I'm looking for underline. So I don't actually see it here in the layouts, but doing a little bit more digging inside of the full documentation, we see that one of the options we have is nav set underline. So I'm going to go ahead and use this nav set underline.
Save that. I think I have to do nav set card underline. Cool. Look at that. So we now have that all working. Nav set card underline. And we can customize what it says in these by changing up the text in the UI.nav panel. The nav panel is kind of the nested element under all these high level tab options. So we could do like top sellers here, and we see that that changes. The other options in our dashboard are top sellers value, lowest sellers, and lowest sellers values. So I might as well fill those in now. And we see that there's this other links option. I might get rid of that menu and just use the nav panels for each one.
Look at that. We see we have everything, at least stubbed out there. I think before we fill in the different details here, I think we should real quick switch gears and just also understand how we can have this split the screen. So if we wanted it to split the screen with cards, how can we go about doing that?
Column layouts and grids
Going into our layouts. One of the things that you'll see if you scroll around here is columns, grid layouts, et cetera. So all these range element features. So I think the things that you'll probably use the most are layout columns and layout columns wrap. One thing that I particularly like about the documentation is that if you just scroll down just a little bit, there's a nice little how-to guide on when to use layout columns and when to use layout columns wrap. If you want your cards like the same size and height, same width and height, and kind of a regular cadence, it makes sense to use layout column wrap. If you want to customize the layout column widths and have different sizes and different points, it makes sense to use layout columns.
So I think we want to use layout columns wrap for our use case, but I'm going to just quickly show layout columns just so you have an idea of how it works. So if I did a width UI.layout columns here, I can put all of my cards underneath this. So I could add a little, some placeholder cards, UI.cards, card, placeholder. With UI.card, placeholder. So there's going to be some default options that it does by default. And we see it kind of just splits it evenly by default, but we can kind of customize it. So I could specify column widths here. And let's say I wanted my first column to take up most of the room. I could say 822 here. And I'll break down these numbers, 822 in a second. But we see that, yeah, that takes up two thirds of the space and then placeholder and placeholder take up one sixth, respectively.
If I customize this to be like, you know, same ratio, four, one, one, you might think that it will do the same exact thing, but we see that it actually squeezes it in. So this is not just ratios. This is actually based off of a 12 column grid. So if you want to fill the full screen, you got to use all 12 of those columns. And that's all specified here in the documentation. If you look at column widths, it's all based on 12 column grid. So that's one good thing to know that's not immediately maybe clear that you might not intuitively know, but it's just good to kind of dig into the documentation, understand that.
This is actually based off of a 12 column grid. So if you want to fill the full screen, you got to use all 12 of those columns.
There's a bunch of different options. If you want it to change size based on how big or small your screen space is, there's options to do that. Bunch of different options with layout columns on how you might specify things and tweak the layout. And you could just keep adding cards here. I could add another card. And we see it fills in some space and that could also be specified. Maybe I wanted that to fill up the rest of the space. I could do a six here and we see that it fills in the rest of the space here, but everything's getting a little bit too squeezed. So I think maybe it makes sense to just have things just two cards here.
So I'm gonna remove these two. Probably gonna get an error right now because it doesn't know what to do, but I guess it's fine. It just uses the first two elements here, but I might want it to just be half and half of the screen. So I could specify that with six and six. And we see, we get a nice even split. A similar way to do that would be to use the layout columns wrap and specify widths equals one half. And we'll see that we get the same. Oh, if I could properly use parentheses, right? We'll see that when I save this, layout column wrap, not layout columns wrap. Layout column wrap. We see we get the same type of deal. So that's a little bit about columns.
And I also, it's worth mentioning, if I now with the layout columns wrap, add more cards and save this, because it knows to specify, because it knows that this should be one half of the screen, it should have placed just one or two items on a single row. But I realized if I look at the documentation real quick, I accidentally made a small mistake where it's not widths, it's width here. So I'll just double check the documentation and I could do width equals one half. And we'll see now it nicely puts it into a grid where each item takes up half of the available screen real estate. And it will dynamically adjust based on how much real estate there is.
If I did make this, let's say one third, then they're evenly gonna take up one third of the screen. And then the fourth item in that column wrap will go to the next row. So this makes it easy to do grids and all of that. You can also like set fixed widths. If you want something to be a specific, you know, pixel size, go into fixed width. You can see that we can do that. So maybe I wanted my first element or all my elements to be, I don't know, 300, 500 pixels, let's say.
Delete this width equals one third. We'll see how this updates things. Oh, oops. This is just a Boolean. So I actually need to specify. This is why we read the documentation. So I would need to do width. If I did width equals 1,000 pixels, you see it does one thing. If I do fixed width equals true, then it's gonna actually do that 1,000 and not dynamically adjust. It's going to not do the same type of dynamic adjusting it would if it wasn't fixed width equals true. You can play around with all these parameters. There's a lot of customization.
I think oftentimes it's trickier to get into like, you know, these fixed width scenarios. I usually think it's better practice to just, you know, let things dynamically fill the space based on how much screen real estate you have. So I kind of like, you know, doing this width equals one half type approach. So I'm gonna go ahead and do that.
Filling in the dashboard structure
Cool. And so if we look at our chart, our final kind of what we're working towards, we see we have a heat map here. And then we have this like US map of sales and here that takes up the full space. So how can we fill in these details? Well, I don't need these extra nav panel or I don't need the extra cards down here. I could do a card that is the sales by location data or map here. And note that this is outside of our layout column wrap. So as we see, it fills up the whole space. It doesn't fill up half of the row because it's outside of that column wrap item. I might even do a UI dot card header here and put the sales location map in that so it's a little bit cleaner.
So you got that. Nice little placeholder for that. This placeholder was a heat map. So I could even also add a card header here. And this is basically going to be sales by time. So sales by time of day heat map, I might say here is the header. And we can fill that in in videos four and five.
And then finally, I think the last thing I really wanna do in this video specifically is how can we customize these tabs to actually show the different content? Well, we can basically copy this plot and paste it into the other areas. Okay, so let's start with one. We're gonna have to name this differently. So I'm gonna say plot two to start. And we see that we have an issue. So duplicate input output IDs found and it's yelling because we have this input numeric in both the first nav panel and the second nav panel. So that's an issue. So I can go ahead and delete this from the second one. And now we see we have a chart that looks like this.
I go to top sellers value and it's not there, but I can adjust things. And if I go to this other panel, we do see that it also adjusts there. So that's good to know. But it's not really ideal because I think it's a little clunky to have only the input available in one of the tabs and not the others. So how do we solve this? How do we get this input available in all of them? There's a nice little keyword argument that we can pass in this input numeric into. So I copied that. And if you look at the nav set card underline options, do a comma and see the kind of what we can fill in. One of the things you'll see here is this footer option. So you could either do header or footer, but this is very convenient because we can pass in like inputs and whatnot into this footer and have it propagate for all the nav panels within the nav set card underline. So this can all be seen in the documentation.
I like to kind of view what keyword arguments I have available to me via like Visual Studio Code and that, but I'm gonna paste in that input numeric and now look what we have. So we have the top sellers, top sellers value, that number of items is there for both of them. So that's pretty nice. Let's give these more descriptive names. So this is like, how about plot top sellers. This will be plot top sellers value.
And what is the difference between top sellers and top sellers value? So top sellers is based on purely the quantity ordered, whereas top sellers value in my eyes is there's these columns quantity ordered and price each. So it's gonna be equal to the quantity ordered times the price each. So I could add a new column here. And remember, we don't want to directly modify a reactive calc value. So we see that this data frame is part of a reactive calc because this value is ultimately cached. And if we modify the value, it just all sorts of weird stuff happens. So we either need to copy this data frame from the cached value and then modify the copied data frame.
So I could do something like value equals DF quantity ordered times DF price each, that would work. And then we could modify this chart to use the value instead. That's one approach. I think honestly though, it's probably helpful for all of our graphs to have access to this value column. So I'm gonna go ahead and actually modify the reactive calc to include this. So DF value equals DF quantity ordered times DF price each. And if I rerun this, we'll now see that we have a value column here. And then we can use this value column in our top sellers value chart, switch this Y input to value, switch the group by to value.
And now if we look at our top sellers, we see that AAA batteries sold the most quantity, but value wise, a MacBook Pro laptop made the most value, which makes sense. Batteries are cheap. You're gonna sell a lot of these cheap batteries. We might not sell as many MacBook Pros, but each MacBook Pro is a thousand plus dollars. So it makes sense that the top sellers value amount is greater for MacBook Pros.
We can repeat this process with our other charts. So lowest sellers, what would that look like? Plot lowest sellers. And all we need to change here is that there's this N largest here. That's the largest quantity ordered. We can change this to the built in pandas N smallest to make this lowest sellers. And then we can copy the top sellers value from here, paste it in lowest sellers value. And again, this should be N smallest here. And this is plot lowest sellers value. Now, if we look at this, we have options for each. I can dynamically adjust this. We see that we have all of those filled in with this nice little footer. We have some other cards that are ready to be filled in. We have the sidebar.
So we've now shown how we can do a bunch of different customizations to our layout and start really getting something that's more professional. Something we're more proud to publish by leveraging these layout components. And we'll continue building off of this in videos four and five, but this is kind of a good starting point. Having this separation in your visualizations just makes it much easier to read and follow a dashboard like this.
Having this separation in your visualizations just makes it much easier to read and follow a dashboard like this.
All resources mentioned in this video can be found in the description. And again, just as a reminder, we're ultimately working our way towards an app that looks like this. And so in videos four and five, we'll see how we can start adding these different additional visualizations to our chart. And then in video five, we'll see how we can customize the colors and add a nice fancy title like this to really make this dashboard your own. Hopefully you enjoyed this video on layouts in Shiny. If you did enjoy it, make sure to throw this video a thumbs up and subscribe if you haven't already. The fourth video in the series will be published in less than 14 days. So be on the lookout for that. Until next time, everyone, peace.
