Context
I'm developing a reusable module in Shiny and would like to leave for user the possibility to change the value of id
in this module, thus: I don't know what namespace would elements inside the module have.
I would like to also use some custom CSS to style those elements and would like to have the CSS code in the separate file (in www/
folder).
Problem
I anticipate the problem with the mentioned id
(namespace) - I'm not sure how to refer to the value stored in variable in one language (R) in the other language (CSS) when working in different files.
I know it is possible to refer to the value using internal stylesheet:
library(shiny)
library(glue)
modUI <- function(id) {
ns <- NS(id)
tagList(
tags$head(tags$style(glue("#{id}-color {{background-color: green;}}"))),
actionButton(ns("color"), "I'm green")
)
}
modServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
}
)
}
ui <- fluidPage(
modUI("example")
)
server <- function(input, output, session) {
modServer("example")
}
shinyApp(ui, server)
But is it possible to do the same with the external stylesheet?
I would like to add that I'm a beginner with styling using both non-R tools (CSS, Saas) and R tools (bslib, fresh), so perhaps I'm just missing something very fundamental. I also would like to add that - even that I have mentioned CSS - I can use something different if appriopriate to use in reusable module.
CodePudding user response:
You can use a css class instead of styling the elements by id which means that it does not matter what id the user passes in.
my_module_ui <- function(id) {
ns <- NS(id)
tagList(
tags$head(tags$style(".my_module_button {background-color: green;}")),
actionButton(ns("color"), "I'm green", class = "my_module_button")
)
}
This can be easily ported into a external stylesheet and other users can overwrite the class styles.
.my_module_button {
background-color: green;
}
Generally spaking, it is far more common in the css world to use classes instead of ids to select styling targets, even if the styling is applied to only one single element.
Just make sure your class names are specific enough to avoid classname collisions. I'd suggest you use the module name as a prefix for the css classes that correspond to the module. The stylesheet for your module will then look something like this
.my_module_button {
background-color: green;
}
.my_module_text {
color: teal;
}
.my_module_container {
margin: 0 auto;
}
There are also advanced techniques with compound selectors, but in my experience, having a few namespaced css classes per module usually gets the job done.