admin管理员组

文章数量:1316414

I am experimenting with bslib's dark/light mode feature. I would like to replot a base R graphic depending on the dark/light mode. In particular, I want to set the fg and bg options to par().

A quick search brought up the functions bs_current_theme and bs_get_variables:

current_theme <- bslib::bs_current_theme()
bg <- bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]

However, the value of bg seems not to change after toggle_dark_mode() is called. Here is an example app that prints bg every time the dark/light mode button is pressed:

ui <- bslib::page_navbar(
  title = "Dark Mode Demo",
  theme = bslib::bs_theme(version=5),
  bslib::nav_panel(
    title = "Base Graphics",
    bslib::card(
      bslib::card_header("Mosaic"),
      shiny::plotOutput("base_mosaic")
    )
  ),
  bslib::nav_spacer(),
  bslib::nav_item(
    bslib::input_dark_mode(id = "theme_toggle", mode = "light")
  )
)

server <- function(input, output, session) {
  # dark / light mode
  shiny::observeEvent(input$theme_toggle, {
    bslib::toggle_dark_mode(mode=input$theme_toggle)
    current_theme <- bslib::bs_current_theme()
    message("bg=", bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]])
    par(bg = bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]) 
  })
  output$base_mosaic <- shiny::renderPlot({ 
    plot(1:10)
  })
}

shiny::shinyApp(ui, server)

What is the best way to determine the current background and foreground (=text) color in bslib?

I am experimenting with bslib's dark/light mode feature. I would like to replot a base R graphic depending on the dark/light mode. In particular, I want to set the fg and bg options to par().

A quick search brought up the functions bs_current_theme and bs_get_variables:

current_theme <- bslib::bs_current_theme()
bg <- bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]

However, the value of bg seems not to change after toggle_dark_mode() is called. Here is an example app that prints bg every time the dark/light mode button is pressed:

ui <- bslib::page_navbar(
  title = "Dark Mode Demo",
  theme = bslib::bs_theme(version=5),
  bslib::nav_panel(
    title = "Base Graphics",
    bslib::card(
      bslib::card_header("Mosaic"),
      shiny::plotOutput("base_mosaic")
    )
  ),
  bslib::nav_spacer(),
  bslib::nav_item(
    bslib::input_dark_mode(id = "theme_toggle", mode = "light")
  )
)

server <- function(input, output, session) {
  # dark / light mode
  shiny::observeEvent(input$theme_toggle, {
    bslib::toggle_dark_mode(mode=input$theme_toggle)
    current_theme <- bslib::bs_current_theme()
    message("bg=", bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]])
    par(bg = bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]) 
  })
  output$base_mosaic <- shiny::renderPlot({ 
    plot(1:10)
  })
}

shiny::shinyApp(ui, server)

What is the best way to determine the current background and foreground (=text) color in bslib?

Share Improve this question edited Jan 30 at 5:24 Jan 9,4786 gold badges20 silver badges33 bronze badges asked Jan 29 at 20:43 Karsten W.Karsten W. 18.5k12 gold badges73 silver badges111 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

Here is a possibility using a small custom message handler: It gets the current value of the Bootstrap variable --bs-body-bg and sends it to Shiny:

library(shiny)
library(bslib)

ui <- page_navbar(
  tags$head(
    tags$script("
      Shiny.addCustomMessageHandler('get_bg', function(value) {
        var bg = getComputedStyle(document.body).getPropertyValue('--bs-body-bg');
        Shiny.setInputValue('current_bg', {bg});
      });
    ")
  ),
  title = "Dark Mode Demo",
  theme = bs_theme(version=5),
  nav_panel(
    title = "Base Graphics",
    card(
      card_header("Mosaic"),
      plotOutput("base_mosaic")
    )
  ),
  nav_spacer(),
  nav_item(
    input_dark_mode(id = "theme_toggle", mode = "light")
  )
)

server <- function(input, output, session) {
  # dark / light mode
  observeEvent(input$theme_toggle, {
    toggle_dark_mode(mode=input$theme_toggle)
    
    session$sendCustomMessage("get_bg", "")
    req(input$current_bg)
    message("bg=", input$current_bg)
  })
  output$base_mosaic <- renderPlot({ 
    par(bg = input$current_bg)
    plot(1:10)
  })
}

shinyApp(ui, server)

In addition to @Jan's answer, I found out here that there different variables used by Bootstrap depending on the color-mode. For instance, there are variables body-bg-dark and body-color-dark. So another approach to my question would be:

if(input$theme_toggle=="dark") {
    bg <- bslib::bs_get_variables(current_theme, "body-bg-dark")[["body-bg-dark"]]
    fg <- bslib::bs_get_variables(current_theme, "body-color-dark")[["body-color-dark"]]
    clr <- khroma::color("dark")(2)
} else {
    bg <- bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]
    fg <- bslib::bs_get_variables(current_theme, "body-color")[["body-color"]]
    clr <- khroma::color("light")(2)
}

It was not easy to adapt a base graphic to the color-mode, but I got it working. See here.

本文标签: rDetermine foregroundbackground colour in bslib app with darklight modeStack Overflow