New shiny::bindCache() function
reactive() or render*() functionImproved theming support
{bslib} & {thematic} packagesAccessibility improvements and many bug fixes
Try v1.6 out today with:
remotes::install_github("rstudio/shiny")
New shiny::bindCache() function
reactive() or render*() functionImproved theming support
{bslib} & {thematic} packagesAccessibility improvements and many bug fixes
Try v1.6 out today with:
remotes::install_github("rstudio/shiny")
library(shiny)ui <- fluidPage( sliderInput("x", "x", 0, 10, 5), sliderInput("y", "y", 0, 10, 5), verbatimTextOutput("val"))server <- function(input, output) { r <- reactive({ Sys.sleep(2) input$x + input$y }) output$val <- renderPrint(r())}shinyApp(ui, server)

x or y changes, r() re-executes.library(shiny)ui <- fluidPage( sliderInput("x", "x", 0, 10, 5), sliderInput("y", "y", 0, 10, 5), verbatimTextOutput("val"))server <- function(input, output) { r <- reactive({ Sys.sleep(2) input$x + input$y }) output$val <- renderPrint(r())}shinyApp(ui, server)

x or y changes, r() re-executes.r() can recall its most recent value (transient), but not its entire history (persistent)library(shiny)ui <- fluidPage( sliderInput("x", "x", 0, 10, 5), sliderInput("y", "y", 0, 10, 5), verbatimTextOutput("val"))server <- function(input, output) { r <- reactive({ Sys.sleep(2) input$x + input$y }) %>% bindCache(input$x, input$y) output$val <- renderPrint(r())}shinyApp(ui, server)

bindCache() a reactive and its input value(s).library(shiny)ui <- fluidPage( sliderInput("x", "x", 0, 10, 5), sliderInput("y", "y", 0, 10, 5), verbatimTextOutput("val"))server <- function(input, output) { r <- reactive({ Sys.sleep(2) input$x + input$y }) %>% bindCache(input$x, input$y) output$val <- renderPrint(r())}shinyApp(ui, server)

bindCache() a reactive and its input value(s).r() can now retrieve x+y from cache! 🎉library(shiny)ui <- fluidPage( sliderInput("x", "x", 0, 10, 5), sliderInput("y", "y", 0, 10, 5), verbatimTextOutput("val"))server <- function(input, output) { r <- reactive({ Sys.sleep(2) input$x + input$y }) %>% bindCache(input$x, input$y) output$val <- renderPrint(r())}shinyApp(ui, server)

bindCache() a reactive and its input value(s).r() can now retrieve x+y from cache! 🎉?bindCache)# requires dev version of plotly# remotes::install_github("ropensci/plotly")library(plotly)ui <- fluidPage( selectizeInput( "cities", "Select a city", choices = unique(txhousing$city) ), plotlyOutput("p"))server <- function(input, output, ...) { output$p <- renderPlotly({ Sys.sleep(2) plot_ly(txhousing, x = ~date, y = ~median) %>% filter(city %in% input$cities) %>% group_by(city) %>% add_lines() }) %>% bindCache(input$cities)}shinyApp(ui, server)

Some custom output bindings may need updating to cache correctly (see ?bindCache). Let us know if you run into issues!
New shiny::bindCache() function
reactive() or render*() functionImproved theming support
{bslib} & {thematic} packagesAccessibility improvements and many bug fixes
Try v1.6 out today with:
remotes::install_github("rstudio/shiny")
{bslib}: tools for customizing Bootstrap CSS from R
{thematic}: simplified theming of R plots ({ggplot2}, {lattice}, & {base})
Also not yet on CRAN
remotes::install_github(c("rstudio/bslib", "rstudio/thematic")){bslib} with Shinylibrary(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!library(shiny)library(bslib)ui <- fluidPage( theme = bs_theme(version = 4), ...)
Special compatibility layer helps most Shiny apps & R Markdown docs upgrade to Bootstrap 4.
Upgrading may break some apps (try version = 3 in that case).
library(shiny)library(bslib)# In the past, this was shinythemes::shinythemes("darkly")ui <- fluidPage( theme = bs_theme(bootswatch = "darkly"), ...)
version).
bs_theme_preview( bs_theme(bootswatch = "darkly"))

bs_theme( bg = "black", fg = "white", primary = "red", base_font = font_google("Grandstander"))

font_google() makes it easy to import Google Font filesbs_theme( bg = "black", fg = "white", primary = "red", base_font = font_google("Grandstander"))

bs_theme( bg = "black", fg = "white", primary = "red", base_font = font_google("Grandstander"))

bs_theme( bg = "#202123", fg = "#B8BCC2", primary = "#EA80FC", base_font = font_google("Grandstander"))

rmarkdown::html_document--- output: html_document: theme: bg: "#202123" fg: "#B8BCC2" primary: "#EA80FC" base_font: !expr bslib::font_google("Grandstander")---
Currently requires an experimental version of R Markdown remotes::install_github("rstudio/rmarkdown#1706")
Currently themable (in next CRAN release):
The {shiny} package
rmarkdown::html_document() and DT::datatable()
Any "Bootstrap compatible" HTML/CSS
Currently themable (in next CRAN release):
The {shiny} package
rmarkdown::html_document() and DT::datatable()
Any "Bootstrap compatible" HTML/CSS
Soon to be themable (we'd love your help!):
Other HTML-based R Markdown output formats
Other {htmlwidgets} packages (e.g., {plotly}, {reactable}, etc)
Other extension packages (e.g., {shinyWidgets}, etc)
Currently themable (in next CRAN release):
The {shiny} package
rmarkdown::html_document() and DT::datatable()
Any "Bootstrap compatible" HTML/CSS
Soon to be themable (we'd love your help!):
Other HTML-based R Markdown output formats
Other {htmlwidgets} packages (e.g., {plotly}, {reactable}, etc)
Other extension packages (e.g., {shinyWidgets}, etc)
Fundamentally un-themable via CSS:
plotOutput(): use {thematic} to "translate" CSS to R plots!bs_theme() 😭fluidPage( theme = bs_theme(bg = "#002B36", fg = "#EEE8D5", primary = "#2AA198", base_fonts = font_google(("Pacifico")), tabsetPanel(type = "pills", tabPanel("ggplot", plotOutput("ggplot")), tabPanel("lattice", plotOutput("lattice")), tabPanel("base", plotOutput("base"))))

{thematic} to the rescue! 🎉thematic::thematic_shiny()fluidPage( theme = bs_theme(bg = "#002B36", fg = "#EEE8D5", primary = "#2AA198", base_fonts = font_google("Pacifico")), tabsetPanel(type = "pills", tabPanel("ggplot", plotOutput("ggplot")), tabPanel("lattice", plotOutput("lattice")), tabPanel("base", plotOutput("base"))))

{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).library(thematic)library(ggplot2)thematic_on( bg = "black", fg = "white", accent = "red", font = "Indie Flower")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()

{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).library(thematic)library(ggplot2)thematic_on( bg = "black", fg = "white", accent = "red", font = "Indie Flower")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()
Since Indie Flower is a Google Font, {thematic} installs it if needed!

{thematic}"auto"-detected!library(thematic)library(ggplot2)thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()

{thematic}"auto"-detected!library(thematic)library(ggplot2)thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()
"auto" works best via shiny::renderPlot() (works with any CSS, not just bs_theme())!

{thematic}"auto"-detected!library(thematic)library(ggplot2)thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()
"auto" can work with {bslib} in rmarkdown::html_document()

{thematic}"auto"-detected!library(thematic)library(ggplot2)thematic_on( bg = "auto", fg = "auto", accent = "auto", font = "auto")ggplot(mtcars, aes(wt, mpg)) + geom_point() + geom_smooth()
"auto" detects your RStudio Theme inside RStudio

bs_theme_preview() overlays a real-time theming widget, let's see it action!
Call bs_themer() in the server code (also works with a runtime: shiny R Markdown doc)
setCurrentTheme()ui <- fluidPage( theme = bs_theme(), checkboxInput("dark_mode", "Dark mode", FALSE))server <- function(input, output, session) { observe(session$setCurrentTheme({ if (input$dark_mode) { bs_theme(bg = "black", fg = "white", primary = "purple") } else { bs_theme() } }))}shinyApp(ui, server)

Main colors (e.g., bg, fg, etc) "cascade" to 100s of other settings, all of which can be set via Bootstrap Sass variables (e.g., $progress-bar-bg)
bs_theme( bg = "#002B36", fg = "#EEE8D5", "progress-bar-bg" = "orange")

bs_theme() works by overriding Bootstrap Sass variable defaults. Learn more about Sass and the {sass} 📦 at https://rstudio.github.io/sass
Customize spacing, borders, modify colors, and more!
tabsetPanel( tabPanel("One", "No padding"), tabPanel("Two", "No padding"))

tabsetPanel( tabPanel( "One", "With padding", class = "p-3 border border-top-0 rounded-bottom" ), tabPanel("Two", "No padding"))

See more examples at https://rstudio.github.io/bslib/articles/recipes.html
Add Sass rules to do things like @extend all navs to be centered
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") ))

See more examples at https://rstudio.github.io/bslib/articles/recipes.html
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"))).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;}
Use shiny::bindCache() to persistently cache reactive expressions
?bindCache for more detailsUse bslib::bs_theme() to theme Shiny & R Markdown.
Upgrades to Bootstrap 4 by default (can also version = 3).
Use Bootswatch and/or design your own custom themes.
Use bs_theme_preview()/bs_themer() to quickly preview and update themes.
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}.
@cpsievert
@cpsievert
cpsievert1@gmail.com
https://cpsievert.me/
Slides made possible thanks to {xaringan} and {xaringanExtra}
New shiny::bindCache() function
reactive() or render*() functionImproved theming support
{bslib} & {thematic} packagesAccessibility improvements and many bug fixes
Try v1.6 out today with:
remotes::install_github("rstudio/shiny")
Keyboard shortcuts
| ↑, ←, Pg Up, k | Go to previous slide |
| ↓, →, Pg Dn, Space, j | Go to next slide |
| Home | Go to first slide |
| End | Go to last slide |
| Number + Return | Go to specific slide |
| b / m / f | Toggle blackout / mirrored / fullscreen mode |
| c | Clone slideshow |
| p | Toggle presenter mode |
| t | Restart the presentation timer |
| ?, h | Toggle this help |
| Esc | Back to slideshow |