
Introducing Shiny for Python Templates | Carson Sievert | Posit
Last month we introduced the Shiny for Python Components and Layouts galleries, which are a simple, visual overview of what Shiny can do, mixed with cheatsheet-like information. They are for new and seasoned users alike. We’re excited to announce a third section which brings those two things together into opinionated boilerplate code: Shiny Templates. This is just a start… We expect this gallery to grow as time goes on. These will allow you to hit the ground running, whether you need a quick simple app or a quick complicated one . Get started at https://shiny.posit.co/py/templates/ 0:00 Introduction to Shiny for Python Templates 0:38 How to work with a template locally in VS Code 2:24 Preview your app with the Shiny for Python VS Code Extension 2:45 A data_frame is a quick and easy way to see the contents of your data 4:39 See everything in your window with the “fillable=True” page_opts 5:16 Modifying inputs 7:40 Fix the logic in your @render.plot to show your modified inputs 9:00 Add a component to the sidebar 9:05 How to add input_dark_mode to your app 9:54 How to make your plot change to dark mode as well
image: thumbnail.jpg
Transcript#
This transcript was generated automatically and may contain errors.
Hi, I'm Carson. I'm an engineer on the Shiny team here at Posit, and I'm excited to show you today a page that we've added to the Shiny for Python website called Templates. And the idea with Templates is basically to give you a template to give you something useful in terms of a complete Shiny app, and kind of use that to create your own applications more quickly.
The first three here are going to be pretty nice starting points. I especially like the ReactivePlot inside bar. So if I want to take this template and start working with it locally, remember that we have this code block at the very start of each page. And note that in this code block here, I have two different tabs. Typically, if you're just getting started, it's probably best to start out with Shiny Express. So we're going to take this Shiny Create Express code, and I'm going to paste this into my terminal.
And this is going to grab the template from GitHub, and then ask me where I would like to basically locate those files in a local directory. So I'm going to call this just basic sidebar. And now I get some more instructions here that my next step should be to open and edit this app file. But we're also going to want to make sure that we install any packages that are needed for that particular template. So before I open this, I'm just going to go into this directory that I've just created. If I list the files, you can see that I have the app.py. There's also a CSV file that this app is going to be reading from, as well as a shared module that will be used by the app, and a requirements file for installing dependencies. So I'm going to take this command here, and make sure I have all the dependencies I need for this application.
Opening the template in VS Code
And now I'm going to open up this directory in VS Code. So now if I open my app.py file, here is the template for my basic sidebar layout. And as long as I have the Shiny VS Code extension installed, you should see this play button come up in the top right corner of your VS Code editor, that if you hover over it, it'll say run your Shiny app, which is what I want to see. I can press that, and it will come up with a preview.
Now what I might want to do is, you know, if I want to add any sort of customization to this, maybe one of the first things I want to get a sense for is, what is the actual data that's being used for this template? And a nice quick and easy way I can do that is to add another render statement here. So in Shiny, the way we create outputs is through these render decorators. So I know that I'm going to want to render a data frame below the plot. And actually, instead of below the plot, let's put it above the plot so we can see it better to start off with. And GitHub Copilot has actually given me a nice recommendation here where this decorator is going to need a function to decorate. And you can give this function any name that you want. Just make sure it doesn't clash with any other names in your environment. So this is a nice recommendation of name this function data and just have it return this df object.
So if you look carefully at this render plot code, you would maybe notice that df is a data frame that's being used to create these plots. So if I just put that df inside of a render data frame, we can get this nice interactive table. I have quite a small window here, but by default, tables have a 500 pixel height. So there's a lot of data here, but it won't render all of the rows. It will stop at a certain point and tell you which rows that you're viewing. And then if you keep scrolling down the page, you'll see we still have the plot here.
Customizing the layout and inputs
If I really wanted to try to squish everything in this window, one thing that I could do is I could come up to the page options for this express app and flip on fillable equal to true. And this will basically do its best to allow content in the main content area of the sidebar layout to either grow or shrink to fit the page. So if I make this smaller or bigger, that content will grow and shrink to keep fitting the page.
A couple of things I noticed here is this data set has a species variable and that's being used for the group by species input control. There's also an island column. There's also several numeric variables for build depth, flipper length, body mass, and also the sex of the penguins. So maybe what I want to do is if I look at this code, these input controls that are within the actual sidebar, then maybe what I will want to do is add some more choices here because actually I just have two variables for my choices, but I have other numeric variables available to me. So what I'll do is add a build depth, mm. And now I've basically just added a choice to the select variable. So now I can also look at the build depth, um, for these penguins.
Another thing I might want to look into is, you know, here I'm just grouping by species, but I have other categorical variables available to me. Um, so I could also be splitting up, um, these things to see if there's any variation, um, across islands or sex. So maybe instead of a switch input control, we could basically do something very similar to the first input control. And let's call this input, give it an ID of group and let's say select group. And that's a good recommendation group by variable. And here, instead of numeric variables, I'm going to want to put categorical variables, island and sex. And this isn't going to be quite right, um, at the moment because I've basically wanting to get rid of this species input control and notice that the logic down here in the render plot, uh, function is to give this hue variable, a species string when the species input control is truthy. Uh, instead what we could do is what we do input dot group, and that's just going to contain the variable name that I want to use for the hue anyways. So now let's, let's get rid of this switch control just so that we're not getting confused that that actually does anything. And now I can switch from species to island or sex and basically see, you know, if there's variation in the variable that I've selected across these groups.
Adding dark mode support
Maybe let's go back to just having the plot and turn off the fillable. Let's say you want to add maybe another component to the sidebar. Um, maybe you've been going through our component gallery and notice something like the input dark mode switch. And if I just put this input dark mode switch, it will turn my application to dark mode because by default it's going to be based on whatever the user's system preferences are. And I have my personal preferences as dark mode. Um, but if you wanted to make sure that, you know, this component always starts the application in light mode, then you can specify what mode I know that I want to start out in. And this kind of renders in this kind of neat sun and moon icon that users can click to switch between light and dark mode.
Now, if you notice, you know, when I switched to dark mode here, this isn't like a hundred percent complete in, in some sense, um, in the sense that the plot here isn't actually updating to be like based on a dark mode look. But if you look into this enough, um, you can figure out how to do this actually with, um, with matplotlib. And one of the things I want, we're going to want to leverage here is that this render plot decorator and really any decorator, uh, can also be called like a function. And when you call this decorator, like a function, it gives you an additional amount of parameters to pass. Well, this will vary by decorator by decorator, but in this particular case of render plot, uh, you have an option for adding some alt text. So this would be helpful for making my plot more accessible. So I'll do something real simple to say, um, densities density plot. Um, but then you also have some additional keyword arguments here. And if you were to read up on the doc string for render plot, you'd notice that these keyword arcs are passed along to matplotlib and especially it's, um, in particular it's save figure function. And that has an option of being able to create a plot with a transparent background.
So now I have my alt text and transparent background. And now if I start, if I go to dark mode, there's an improvement here that the background is now transparent and matching the background color of my app. But now I have a problem of the foreground text color, um, not contrasting that background very well. Again, if you were to kind of Google around for how to maybe set the text color of my matplotlib, you'd eventually, um, come across some code like this. I've looked this up ahead of time, but I'm going to import matplotlib and add some code here to make the matplotlib style, use a dark background. And this isn't going to be right for my light mode, right? But if I flip to dark mode, this is going to be exactly what I want, where this is kind of the right matplotlib setting to tell it like all of the, the borders and the lines and the text colors should actually be assuming a dark background.
Now I kind of have this problem of, you know, if I'm in light mode, the text colors, I actually want them to be black. I don't want them to be white. So I'm going to need to only do this when, um, a dark background is relevant. So one way I can approach that is to give this dark mode input an ID so that I can tell in, um, any reactive code that I have in Shiny, I can read this, um, read whatever the current value is for the dark mode feature server side. So by giving an ID, I can then read this input value of dark mode. And before I do anything with that, let me just print this to show you every time this histogram code runs, it's going to print out this value here.
Dark mode is input dot dark mode. So right now, since we're in light mode, it's going to give me a value of light. But now if I switch to dark mode, this print statement is going to run again and give me a dark mode value of dark. So really what I would like to do is something along the lines of if input dark mode is dark, do this. Otherwise use the default style. Right? So now when I'm in light mode, it's just using the default matplotlib style. But now if I change it to dark mode, I've got my dark background code working.
We really hope that especially for the more advanced Shiny users, you can also work from these templates and possibly bring in your own data set and really, um, you know, take some of these concepts and really make it your own and apply it to your own domain specific problems.
We really hope that especially for the more advanced Shiny users, you can also work from these templates and possibly bring in your own data set and really, um, you know, take some of these concepts and really make it your own and apply it to your own domain specific problems. So if you have any questions or want to learn more, please check out the Shiny for Python website. Remember the templates are under the components menu and feel free to check out our GitHub repo if you have ideas for other templates or want to contribute. Thanks.

