class: middle, center, inverse # Styling Shiny & R Markdown with `{bslib}` & `{thematic}` ### Carson Sievert, Software Engineer @ RStudio ### Slides: https://bit.ly/r-pharma2020
[@cpsievert](https://twitter.com/cpsievert)
[@cpsievert](https://github.com/cpsievert)
[cpsievert.me](https://cpsievert.me)
<cpsievert1@gmail.com> <style type="text/css"> @import url(https://fonts.googleapis.com/css?family=IBM+Plex+Sans);@import url(https://fonts.googleapis.com/css?family=Roboto+Slab);@import url(https://fonts.googleapis.com/css?family=Open+Sans);body{font-family:Open Sans, sans-serif}h1,h2,h3{font-family:Roboto Slab, serif}.remark-slide-content.large{font-size:1.5rem}.remark-slide-content.dark-mode{font-family:Roboto Slab;background-color:#444;color:#e4e4e4}.remark-slide-content.dark-mode a{color:#e39777} </style> --- class: large, middle ### New R 📦s for styling Shiny & R Markdown __`{bslib}`__: tools for styling HTML from R (e.g., Shiny apps, `rmarkdown::html_document()`, etc) * [rstudio.github.io/bslib](https://rstudio.github.io/bslib) __`{thematic}`__: simplified theming of R plots (`{ggplot2}`, `{lattice}`, & `{base}`) * [rstudio.github.io/thematic](https://rstudio.github.io/thematic) Not yet on CRAN (give it about a month or so) ```r remotes::install_github(c("rstudio/bslib", "rstudio/thematic")) ``` --- class: large ### Start using `{bslib}` with Shiny ```r library(shiny) library(bslib) ui <- fluidPage( * theme = bs_theme(), ... ) ``` * `fluidPage()`, `navbarPage()`, `bootstrapPage()`, etc. all have this `theme` argument. * You may already be using `theme` with `{shinythemes}` or your own custom Bootstrap CSS. * `bs_theme()` is way more powerful! --- class: large ### By default, upgrades app to Bootstrap 4 ```r library(shiny) library(bslib) ui <- fluidPage( * theme = bs_theme(version = "4+3"), ... ) ``` * `bs_theme()` defaults to `version = "4+3"`, which means BS4 plus added compatibility for BS3. * Helps most Shiny apps & R Markdown docs upgrade to BS4. * Upgrading may break some custom widgets. * In that case, set `version = 3`. --- class: large ### Continue using Bootswatch themes ```r library(shiny) library(bslib) # In the past, this was shinythemes::shinythemes("darkly") ui <- fluidPage( * theme = bs_theme(bootswatch = "darkly"), ... ) ``` * Now you can use [Bootswatch](https://bootswatch.com/3/darkly) with BS4 or BS3 (just change `version`). * Bootswatch 4 has some new themes (e.g., [solar](https://bootswatch.com/solar) and [minty](https://bootswatch.com/minty)) --- class: large ### Preview a theme ```r bs_theme_preview( bs_theme(bootswatch = "darkly") ) ``` <img src="darkly-preview.png" width="100%" style="display: block; margin: auto;" /> --- class: large ### Customize main colors and fonts! ```r bs_theme_preview(bs_theme( bg = "black", fg = "white", primary = "red", base_font = "Grandstander" )) ``` <img src="bs-theme-custom.gif" width="100%" style="display: block; margin: auto;" /> --- class: large ### Use a better palette (e.g., [material dark](https://material.io/design/color/dark-theme.html)) ```r bs_theme_preview(bs_theme( bg = "#202123", fg = "#B8BCC2", primary = "#EA80FC", base_font = "Grandstander" )) ``` <img src="custom-preview.png" width="100%" style="display: block; margin: auto;" /> --- class: inverse, middle, large ### Tempering `bs_theme()` expectations * "Just works" with: * HTML that doesn't clash with Bootstrap CSS styling * "Just works" soon with: * _All_ of Shiny (e.g., `navbarPage()`, `sliderInput()`, etc) * `rmarkdown::html_document()`, `DT::datatable()`, other popular `{htmlwidgets}` * Your [custom component](https://rstudio.github.io/bslib/articles/theming.html#themable-components-1)? * Can't work with things not rendered by web browser (e.g., `plotOutput()`). * Use `{thematic}` to "translate" CSS to R plots! --- #### Plots don't reflect `bs_theme()` 😠```r fluidPage( theme = bs_theme(bg = "#002B36", fg = "#EEE8D5", primary = "#2AA198", base_fonts = "Pacifico"), tabsetPanel(type = "pills", tabPanel("ggplot", plotOutput("ggplot")), tabPanel("lattice", plotOutput("lattice")), tabPanel("base", plotOutput("base"))) ) ``` <img src="thematic-before.png" width="70%" style="display: block; margin: auto;" /> --- #### `{thematic}` to the rescue! 🎉 ```r *thematic::thematic_shiny() fluidPage( theme = bs_theme(bg = "#002B36", fg = "#EEE8D5", primary = "#2AA198", base_fonts = "Pacifico"), tabsetPanel(type = "pills", tabPanel("ggplot", plotOutput("ggplot")), tabPanel("lattice", plotOutput("lattice")), tabPanel("base", plotOutput("base"))) ) ``` <img src="thematic-after.png" width="70%" style="display: block; margin: auto;" /> --- ### The `{thematic}` package, in general * `{thematic}` alters R plotting defaults using a few simple settings. Use `thematic_on()` to enable globally (until `thematic_off()` is called). .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "black", fg = "white", accent = "red", font = "Indie Flower" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-7-1.png" width="100%" style="display: block; margin: auto;" /> ] --- ### The `{thematic}` package, in general * `{thematic}` alters R plotting defaults using a few simple settings. Use `thematic_on()` to enable globally (until `thematic_off()` is called). .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "black", fg = "white", accent = "red", * font = "Indie Flower" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` .bg-light-red.b--red.ba.bw2.br3.shadow-5.ph4.mt5[ Since Indie Flower is a Google Font, `{thematic}` installs it if needed! ] ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-8-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: dark-mode ### [Auto-theming](https://rstudio.github.io/thematic/articles/auto.html) with `{thematic}` * Main colors and fonts can be `"auto"`-detected! .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-9-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: dark-mode ### [Auto-theming](https://rstudio.github.io/thematic/articles/auto.html) with `{thematic}` * Main colors and fonts can be `"auto"`-detected! .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` .bg-light-yellow.black-70.b--yellow.ba.bw2.br3.shadow-5.ph4.mt5[ `"auto"` works best via `shiny::renderPlot()` (works with any CSS, not just `bs_theme()`)! ] ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-10-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: dark-mode ### [Auto-theming](https://rstudio.github.io/thematic/articles/auto.html) with `{thematic}` * Main colors and fonts can be `"auto"`-detected! .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` .bg-light-yellow.black-70.b--yellow.ba.bw2.br3.shadow-5.ph4.mt5[ `"auto"` can work with `bs_theme()` in `rmarkdown::html_document()` ] ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-11-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: dark-mode ### [Auto-theming](https://rstudio.github.io/thematic/articles/auto.html) with `{thematic}` * Main colors and fonts can be `"auto"`-detected! .pull-left[ ```r library(thematic) library(ggplot2) thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto" ) ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth() ``` .bg-light-yellow.black-70.b--yellow.ba.bw2.br3.shadow-5.ph4.mt5[ `"auto"` detects your RStudio Theme inside RStudio ] ] .pull-right[ <img src="index_files/figure-html/unnamed-chunk-12-1.png" width="100%" style="display: block; margin: auto;" /> ] --- class: inverse, middle, center ## That's enough about `{thematic}`, back to `{bslib}` BTW, `{thematic}` also makes it easy to control `qualitative` and `sequential` colorscales. --- ### Real-time theming ```r # Includes `bs_themer()`, an interactive widget for real-time theming! bs_theme_preview(bs_theme(bg = "#202123", fg = "#B8BCC2", primary = "#EA80FC", base_font = "Grandstander")) ```
--- ### More targetted theming * The main colors and fonts "cascade" to 100s of other theming defaults * Can also set more specific styles via [Bootstrap Sass variables](https://getbootstrap.com/docs/4.4/getting-started/theming/#variable-defaults) (e.g., [`$progress-bar-bg`]((https://github.com/rstudio/bslib/blob/0e936d/inst/lib/bootstrap/scss/_variables.scss#L1003)) ```r bs_theme( bg = "#002B36", fg = "#EEE8D5", "progress-bar-bg" = "orange" ) ``` <img src="progress-orange.png" width="50%" style="display: block; margin: auto;" /> .footnote[ Beware, Sass variables can be quite different across `versions`! ] --- ### What's Sass? What's a Sass variable? * Sass is a more powerful way to write CSS (i.e., style HTML) * Sass variables provide "high-level controls" over CSS <div align="center"> <img src="sass.png" width="80%" /> </div> * `bs_theme()` sets Bootstrap Sass variables (CSS compilation happens magically at run-time) Learn more about [Sass](https://sass-lang.com) and the `{sass}` 📦 at <https://rstudio.github.io/sass> --- ### Leverage the power of BS4 Utility Classes Customize [spacing](https://getbootstrap.com/docs/4.4/utilities/spacing/), [borders](https://getbootstrap.com/docs/4.4/utilities/borders/), modify [colors](https://getbootstrap.com/docs/4.4/utilities/colors/), and more! .pull-left[ ```r tabsetPanel( tabPanel("One", "No padding"), tabPanel("Two", "No padding") ) ``` <img src="tab-before.png" width="100%" style="display: block; margin: auto;" /> ] .pull-right[ ```r tabsetPanel( tabPanel( "One", "With padding", * class = "p-3 border border-top-0 rounded-bottom" ), tabPanel("Two", "No padding") ) ``` <img src="tab-after.png" width="100%" style="display: block; margin: auto;" /> ] .footnote[ See more examples at <https://rstudio.github.io/bslib/articles/recipes.html> ] --- ### More generally, leverage the power of Sass Add [Sass rules](https://sass-lang.com/documentation/style-rules) to do things like `@extend` all [navs to be centered](https://getbootstrap.com/docs/4.4/components/navs/#horizontal-alignment) ```r fluidPage( theme = bs_theme() %>% * bs_add_rules(".nav { @extend .justify-content-center; }"), tabsetPanel( tabPanel("One", "Centered w/ padding", class = "p-3 border border-top-0 rounded-bottom"), tabPanel("Two", "No padding") ) ) ``` <img src="tab-centered.png" width="100%" style="display: block; margin: auto;" /> .footnote[ See more examples at <https://rstudio.github.io/bslib/articles/recipes.html> ] --- ### Create custom, themable, components .panelset[ .panel[.panel-name[R Code] ```r person <- function(name, title, company) { div( class = "person", h3(class = "name", name), div(class = "title", title), div(class = "company", company) ) } fluidPage( person("Andrew Carnegie", "Owner", "Carnegie Steel Company"), person("John D. Rockefeller", "Chairman", "Standard Oil"), theme = bs_theme(bg = "#002B36", fg = "#EEE8D5") %>% * bs_add_rules(sass::sass_file("person.scss")) ) ``` ] .panel[.panel-name[Sass Code] ```scss .person { display: inline-block; padding: $spacer; border: $border-width solid $border-color; @include border-radius; @include box-shadow; outline: 0; width: 300px; @include media-breakpoint-down(sm) { display: block; width: auto; margin-right: $grid-gutter-width; } margin: $grid-gutter-width; margin-right: 0; .title { font-weight: bold; } .title, .company { color: $gray-600; } } .person:last-of-type { margin-right: $grid-gutter-width; } ``` ] .panel[.panel-name[Result] <div align="center"> <img src="person.png" width="60%" /> </div> ] ] --- ### Dynamic theming in Shiny w/ `setCurrentTheme()`! ```r dark <- bs_theme(bg = "black", fg = "white") light <- bs_theme() ui <- fluidPage( theme = light, checkboxInput("dark_mode", "Dark mode", FALSE) ) server <- function(input, output, session) { observe(session$setCurrentTheme( if (input$dark_mode) dark else light )) } shinyApp(ui, server) ``` <img src="dark-mode.gif" width="50%" style="display: block; margin: auto;" /> Very new and experimental ([learn more](https://rstudio.github.io/bslib/articles/theming.html#dynamic-shiny))! --- ### Use your theme inside R Markdown Pass `bs_theme()` parameters to `html_document()` and `html_document_base()`<sup>1</sup> (we hope to extend this to other output formats as well). ```yaml --- output: html_document: theme: bg: "#202123" fg: "#B8BCC2" primary: "#EA80FC" base_font: "Grandstander" --- ``` .footnote[ 1. Currently requires an experimental version of R Markdown `remotes::install_github("rstudio/rmarkdown#1706")` ] --- ### Use your theme inside R Markdown Customize the `bs_theme()` further with `bs_global_*()` ````yaml --- output: html_document: theme: bg: "#202123" fg: "#B8BCC2" primary: "#EA80FC" base_font: "Grandstander" --- ```{r, echo = FALSE} library(bslib) *bs_global_add_rules(".nav { @extend .justify-content-center; }") ``` ```` .footnote[ 1. Currently requires an experimental version of R Markdown `remotes::install_github("rstudio/rmarkdown#1706")` ] --- class: large ### Summary * Use `{bslib}` to style HTML in Shiny & R Markdown. * Upgrades to Bootstrap 4 by default (can also `version = 3`). * Customize main colors and fonts with `bs_theme()`. * Also new defaults for more specific Sass variables * Leverage BS4 Utility Classes to customize spacing, borders, and more. * Include additional Sass rules with `bs_add_rules()` * Great for `@extend`ing Utility Classes or creating your own Bootstrap Sass styles! * Use `{thematic}` for easier theming of R plots * Works with `{ggplot2}`, `plotly::ggplotly()`, `{lattice}`, and `{base}` R graphics. * Auto-theming (i.e., translating CSS to R defaults) works great on Shiny, but can also specify colors and fonts directly in `{thematic}`. --- class: center, middle ## Thank you! Any questions? ### Slides: <https://bit.ly/r-pharma2020> ### <https://rstudio.github.io/bslib> ### <https://rstudio.github.io/thematic>
<a href='https://twitter.com/cpsievert'>@cpsievert</a> <br />
<a href='https://github.com/cpsievert'>@cpsievert</a> <br />
<cpsievert1@gmail.com> <br />
<https://cpsievert.me/> .footnote[ <br> Slides made possible thanks to [`{xaringan}`](https://github.com/yihui/xaringan) and [`{xaringanExtra}`](https://github.com/gadenbuie/xaringanExtra) ]