shinyDarkmode : Add darkmode to shiny apps

Deepanshu Bhalla 1 Comment , ,
Introduction
In this post we will cover how to add darkmode to Shiny Apps. It uses darkmode.js javascript which allows you to toggle between dark and light mode. It's very easy to implement and does not affect your existing code and styling of your app. It comes with inbuilt button for toggling so you don't need to add any widgets for implementation. Obviously if you don't like the default button styling you can customise it as well.
Dark Mode to Shiny App
Installation
I am glad to release R package named shinyDarkmode for this. You can install it from github. It is not available in CRAN yet.
remotes::install_github("deepanshu88/shinyDarkmode")
Basic Example
The program below is a demo app for K Means Clustering. You will see the button in bottom right for toggling.

First step is to add use_darkmode() in UI. Next step is to add darkmode(label = "⏳") in server.

library(shiny)
library(shinyDarkmode)

# UI
vars <- setdiff(names(iris), "Species")
ui <- fluidPage(
  
  titlePanel("Sample App"),
  
  # Setup
  use_darkmode(),
  
  sidebarPanel(
    selectInput('xcol', 'X Variable', vars),
    selectInput('ycol', 'Y Variable', vars, selected = vars[[2]]),
    numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
  ),
  mainPanel(
    plotOutput('plot1')
  ),
  
  column(width = 12,
         DT::dataTableOutput("mydt")
  )
)

# Server
server <- function(input, output, session) {
  
  darkmode(label = "⏳")
  
  # Combine the selected variables into a new data frame
  selectedData <- reactive({
    iris[, c(input$xcol, input$ycol)]
  })
  
  clusters <- reactive({
    kmeans(selectedData(), input$clusters)
  })
  
  output$plot1 <- renderPlot({
    palette(c("#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
              "#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"))
    
    par(mar = c(5.1, 4.1, 0, 1))
    plot(selectedData(),
         col = clusters()$cluster,
         pch = 20, cex = 3)
    points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
  })
  
  output$mydt <- DT::renderDataTable(iris,
                                     options = list(pageLength = 10, autoWidth = TRUE),
                                     rownames= FALSE)
}

# Run App
shinyApp(ui = ui, server = server)
darkmode( ) function allows you to customise the default button. See the default settings below -
bottom = "32px",
  right = "32px",
  left = "unset",
  time = "0.5s",
  mixColor = "#fff",
  backgroundColor = "#fff",
  buttonColorDark = "#100f2c",
  buttonColorLight = "#fff",
  saveInCookies = FALSE,
  label = "⏳",
  autoMatchOsTheme = TRUE
Toggle Darkmode based on Checkbox
You can use darkmode_toggle( ) function which interacts with checkbox widget.
library(shiny)
library(shinyDarkmode)

ui <- fluidPage(
  
  titlePanel("Sample App"),
  
  # Setup
  use_darkmode(),
  
  # Inputs
  fluidRow(
    tags$div(style = "margin-top: -25px; float: right; margin-right: -150px;",
             checkboxInput("togglemode", "Dark Mode", value = FALSE)
    )
  ), DT::dataTableOutput("mydt")
  
)


# Server
server <- function(input, output, session) {
  
  darkmode_toggle(inputid = 'togglemode')
  
  output$mydt <- DT::renderDataTable(mtcars,
                                     options = list(pageLength = 10, autoWidth = TRUE),
                                     rownames= FALSE)
  
}

# Run App
shinyApp(ui = ui, server = server)
shinyWidgets library has a lot of beautiful checkbox widgets which makes dashboard more lively and visually appealing. Here we are using prettySwitch( ) function from the library. It works similar to shiny checkboxInput widget but also have arguments to style the switch.
library(shiny)
library(shinyWidgets)
library(shinyDarkmode)

ui <- fluidPage(
  
  titlePanel("Sample App"),
  
  # Setup
  use_darkmode(),
  
  # Inputs
  fluidRow(
    tags$div(style = "margin-top: -25px; float: right; margin-right: -150px;",
             prettySwitch("togglemode", "Dark Mode", value = FALSE, fill = TRUE, status = "info")
    )
  ), DT::dataTableOutput("mydt")
  
)


# Server
server <- function(input, output, session) {
  
  darkmode_toggle(inputid = 'togglemode')
  
  output$mydt <- DT::renderDataTable(mtcars,
                                     options = list(pageLength = 10, autoWidth = TRUE),
                                     rownames= FALSE)
  
}

# Run App
shinyApp(ui = ui, server = server)

When darkmode is active, javascript adds CSS class darkmode--activated You can use it to customize the styling of dark mode.

.darkmode--activated button:not(.darkmode-toggle) {background: #bd9e68; border-color: #bd9e68; color: #000; font-weight : 700;}
.darkmode--activated .pretty.p-switch.p-fill input:checked~.state.p-info:before {background-color: #bd9e68 !important; border-color: #bd9e68;}
.darkmode--activated .pretty.p-switch.p-fill input:checked~.state label:after {background-color: #333 !important;}
Related Posts
Spread the Word!
Share
About Author:
Deepanshu Bhalla

Deepanshu founded ListenData with a simple objective - Make analytics easy to understand and follow. He has over 10 years of experience in data science. During his tenure, he worked with global clients in various domains like Banking, Insurance, Private Equity, Telecom and HR.

1 Response to "shinyDarkmode : Add darkmode to shiny apps"
  1. My only question is, how do you find the hourglass icon you used on the server side of the program?

    ReplyDelete
Next → ← Prev