Yan Holtz
Yan Holtz

Reputation: 115

Applying 2 different CSS styles on Shiny Button

I am developing a R Shiny Application that use the shinyWidgets library. I use 2 times the radioGroupButtons widget. I would like to make it green the first time, and red the second time, using CSS. (In reality I want to make more customisation).

Here is a basic code, applying CSS to every buttons. How can I apply 2 CSS classes?

Thank you very very much for your help !

library("shinyWidgets")
library(shiny)

# Useless server
server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$button1), col = 'skyblue', border = 'white')
  })
}

# Ui
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(

        # A CSS for every .btn button
        tags$style(HTML("
            .btn {
              color: #2ecc71;
              border: 2px #2ecc71 solid;
            }
            .btn:hover {
                color: #fff;
                background-color: #2ecc71;
            }
            .btn-default.active, .btn-default:active, .open > .dropdown-toggle.btn-default {
                color: #fff;
                background-color: #2ecc71;
                border-color: #2ecc71;
            }
        ")),

        # first radio button, it is green!
        radioGroupButtons("button1", label = "It's green !!", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),

        # second radio button, I wish it is red!
        radioGroupButtons("button2", label = "I wish I was red :( ...", choices=c("choice1"=1, "Choice2"=2), selected=1)
    ),
    mainPanel(plotOutput("distPlot"))
  )
)

shinyApp(ui = ui, server = server)

Upvotes: 2

Views: 3634

Answers (2)

Victorp
Victorp

Reputation: 13856

You can add a Bootstrap status then overwrite the class, for example if you add status = "danger", buttons will have class btn-danger :

I can remove the limitation to valid Bootstrap status in the function, it could be useful for such styling (fill an issue here so i remenber).

library("shinyWidgets")
library("shiny")

# Useless server
server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$button1), col = 'skyblue', border = 'white')
  })
}

# Ui
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(

      # A CSS for every .btn button
      tags$style(HTML("
                      .btn-success.btn {
                      color: #2ecc71;
                      background-color: #fff;
                      border: 2px #2ecc71 solid;
                      }
                      .btn-success.btn:hover {
                      color: #fff;
                      background-color: #2ecc71;
                      }
                      .btn-success.active {
                      color: #fff;
                      background-color: #2ecc71;
                      border-color: #2ecc71;
                      }

                      .btn-danger.btn {
                      color: #EE102B;
                      background-color: #fff;
                      border: 2px #EE102B solid;
                      }
                      .btn-danger.btn:hover {
                      color: #fff;
                      background-color: #EE102B;
                      }
                      .btn-danger.active {
                      color: #fff;
                      background-color: #EE102B;
                      border-color: #EE102B;
                      }
                      ")),

      # first radio button, it is green!
      radioGroupButtons("button1", label = "It's green !!", status = "success", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),

      # second radio button, I wish it is red!
      radioGroupButtons("button2", label = "I wish I was red :( ...", status = "danger", choices=c("choice1"=1, "Choice2"=2), selected=1)
      ),
    mainPanel(plotOutput("distPlot"))
      )
    )

shinyApp(ui = ui, server = server)

Upvotes: 0

K. Rohde
K. Rohde

Reputation: 9676

So you want to add some specific classes to your radioGroupButtons. Well, ShinyWidgets doesn't let you, so why not create your own radioButtons widget function.

(Well, this function will be almost entirely copied from radioGroupButtons)

Hint: Type radioGroupButton into the R Console to view the source code.

And lets tweak that function, such that it accepts a class argument, which will be applied to the html element. Then, you can easily access the different radioGroupButton-classes with your CSS.

Working code below:

library("shinyWidgets")
library(shiny)

# Defining the new Widget. 
customRadioGroupButtons <- function (inputId, label = NULL, choices, selected = NULL, status = "default", size = "normal", direction = "horizontal", justified = FALSE, individual = FALSE, checkIcon = list(), class=NULL) {
  choices <- shinyWidgets:::choicesWithNames(choices)
  if (!is.null(selected) && length(selected) > 1) 
    stop("selected must be length 1")
  if (is.null(selected)) 
    selected <- choices[1]
  size <- match.arg(arg = size, choices = c("xs", "sm", "normal", 
                                            "lg"))
  direction <- match.arg(arg = direction, choices = c("horizontal", 
                                                      "vertical"))
  status <- match.arg(arg = status, choices = c("default", 
                                                "primary", "success", "info", "warning", "danger"))
  divClass <- if (individual) 
    ""
  else "btn-group"
  if (!individual & direction == "vertical") {
    divClass <- paste0(divClass, "-vertical")
  }
  if (justified) {
    divClass <- paste(divClass, "btn-group-justified")
  }
  if (size != "normal") {
    divClass <- paste0(divClass, " btn-group-", size)
  }

  # Below here, the paste call is the only difference to the original function.
  radioGroupButtonsTag <- tagList(tags$div(id = inputId, class = paste("radioGroupButtons", class), 
    if (!is.null(label)) 
      tags$label(class = "control-label", `for` = inputId, label),
    if (!is.null(label)) 
      br(), style = "margin-top: 3px; margin-bottom: 3px; ", style = if (justified) "width: 100%;", 
      tags$div(class = divClass, role = "group", 
      `aria-label` = "...", `data-toggle` = "buttons", 
      class = "btn-group-container-sw", shinyWidgets:::generateRGB(inputId, choices, selected, status, size, checkIcon))))
  shinyWidgets:::attachShinyWidgetsDep(radioGroupButtonsTag)
}

# Useless server
server <- function(input, output) {
  output$distPlot <- renderPlot({
    hist(rnorm(input$button1), col = 'skyblue', border = 'white')
  })
}

# Ui
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(

      # Note: Consider making a function if you use this more often.
      tags$style(HTML("
                      .radioGroupButtons.green .btn {
                        color: #2ecc71;
                        border: 2px #2ecc71 solid;
                      }
                      .radioGroupButtons.green .btn:hover {
                        color: #fff;
                        background-color: #2ecc71;
                      }
                      .radioGroupButtons.green .btn-default.active, .radioGroupButtons.green .btn-default:active, .radioGroupButtons.green .open > .dropdown-toggle.btn-default {
                        color: #fff;
                        background-color: #2ecc71;
                        border-color: #2ecc71;
                      }

                      .radioGroupButtons.red .btn {
                        color: #EE102B;
                        border: 2px #EE102B solid;
                      }
                      .radioGroupButtons.red .btn:hover {
                        color: #fff;
                        background-color: #EE102B;
                      }
                      .radioGroupButtons.red .btn-default.active, .radioGroupButtons.green .btn-default:active, .radioGroupButtons.green .open > .dropdown-toggle.btn-default {
                        color: #fff;
                        background-color: #EE102B;
                        border-color: #EE102B;
                      }
                      ")),

      # first radio button, it is green!
      customRadioGroupButtons("button1", class="green", label = "It's green !!", choices=c("choice1"=50, "Choice2"=100, "Choice3"=150), selected=100),

      # second radio button, I wish it is red!
      customRadioGroupButtons("button2", class="red", label = "I wish I was red :( ...", choices=c("choice1"=1, "Choice2"=2), selected=1)
      ),
    mainPanel(plotOutput("distPlot"))
      )
    )

shinyApp(ui = ui, server = server)

Upvotes: 2

Related Questions