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.
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;}
My only question is, how do you find the hourglass icon you used on the server side of the program?
ReplyDelete