0

Long story short, I've been trying to get .active pseudo classes to work for some shinyWidgets::checkboxGroupButtons(). I discovered that when in the ui() I set theme = bslib::bs_theme(version = 5), the HTML that is generated for the buttons is drastically different than when using version 4. As a result, the button state does not change to active with BS5 when checked.


Summary of html differences:

With BS4 set, each button is within its own DIV, and uses the html button<> element.

With BS5 set, the buttons do not have individual DIVs, and use label<>.


Question 1: Is this happening as intended? Why?

If so, Bonus Question 2 (and the impetus for the question): How do I get a .active state to work with BS5 version? Based on using the a CSS selector widget, the CSS to change the style for buttons when using BS4 looks like:

.btn-group-toggle:nth-child(1) .btn-custom-class.active {
    background: #1B9E77 !important;
    color: black !important;
    border: #1B9E77 !important;
  }

Whereas with BS5 a selector is required, css like this is required:

#cluster_groups1+ .btn-custom-class.active {
    background: red !important;
    color: black !important;
    border: red !important;
  }

HOWEVER, while the BS5 css formatting above works for pseudo classes like :hover and :active, it does not work for .active.

It appears that when one of the buttons is checked with BS5, the HTML code does not change to show it as active (whereas with BS4 the HTML does change) - so in essence it's not necessarily the .active that doesn't work for a #selector, but that the state doesn't change in the HTML when clicked.

Below are the shiny code for each version and the resulting HTML

BS4 version:

library(shiny)
library(shinyWidgets)


ui <- fillPage(
  theme = bslib::bs_theme(version = 4), 
  

              checkboxGroupButtons(
                inputId = "cluster_groups",
                label = "Clusters Displayed",
                choiceNames = c("1", "2", "3", "4", "5", "6"),
                choiceValues = 1:6,
                #selected = c("1", "2", "3", "4", "5", "6"),
                status = "custom-class"
              )



)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

Resulting HTML:


<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <script type="application/shiny-singletons"></script>
  <script type="application/html-dependencies">jquery[3.6.0];shiny-sass[1.7.2];shiny-javascript[1.7.2];bootstrap[4.6.0];bs3compat[0.4.0];shinyWidgets[0.7.3.9210]</script>
<script src="jquery-3.6.0/jquery.min.js"></script>
<link href="shiny-sass-1.7.2/shiny-sass.css" rel="stylesheet" />
<script src="shiny-javascript-1.7.2/shiny.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link href="bootstrap-4.6.0/bootstrap.min.css" rel="stylesheet" />
<script src="bootstrap-4.6.0/bootstrap.bundle.min.js"></script>
<script src="bs3compat-0.4.0/transition.js"></script>
<script src="bs3compat-0.4.0/tabs.js"></script>
<script src="bs3compat-0.4.0/bs3compat.js"></script>
<link href="shinyWidgets/shinyWidgets.min.css" rel="stylesheet" />
<script src="shinyWidgets/shinyWidgets-bindings.min.js"></script>  <style type="text/css">
    html, body { width: 100%; height: 100%; overflow: hidden; }
    body { padding: 0px; margin: 0; }
  </style>
</head>
<body>
  <div class="form-group shiny-input-container shiny-input-checkboxgroup shiny-input-container-inline">
    <label id="cluster_groups-label" class="control-label" for="cluster_groups">Clusters Displayed</label>
    <br/>
    <div id="cluster_groups" class="checkbox-group-buttons">
      <div aria-labelledby="cluster_groups-label" class="btn-group btn-group-container-sw" data-toggle="buttons" role="group">
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="1"/>
            1
          </button>
        </div>
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="2"/>
            2
          </button>
        </div>
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="3"/>
            3
          </button>
        </div>
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="4"/>
            4
          </button>
        </div>
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="5"/>
            5
          </button>
        </div>
        <div class="btn-group btn-group-toggle" role="group">
          <button class="btn checkbtn btn-custom-class">
            <input type="checkbox" autocomplete="off" name="cluster_groups" value="6"/>
            6
          </button>
        </div>
      </div>
    </div>
  </div>
</body>
</html>


BS5 Version:

library(shiny)
library(shinyWidgets)


ui <- fillPage(
  theme = bslib::bs_theme(version = 5), 
  

              checkboxGroupButtons(
                inputId = "cluster_groups",
                label = "Clusters Displayed",
                choiceNames = c("1", "2", "3", "4", "5", "6"),
                choiceValues = 1:6,
                #selected = c("1", "2", "3", "4", "5", "6"),
                status = "custom-class"
              )



)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <script type="application/shiny-singletons"></script>
  <script type="application/html-dependencies">jquery[3.6.0];shiny-sass[1.7.2];shiny-javascript[1.7.2];bootstrap[5.1.3];bs3compat[0.4.0];shinyWidgets[0.7.3.9210]</script>
<script src="jquery-3.6.0/jquery.min.js"></script>
<link href="shiny-sass-1.7.2/shiny-sass.css" rel="stylesheet" />
<script src="shiny-javascript-1.7.2/shiny.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link href="bootstrap-5.1.3/bootstrap.min.css" rel="stylesheet" />
<script src="bootstrap-5.1.3/bootstrap.bundle.min.js"></script>
<script src="bs3compat-0.4.0/transition.js"></script>
<script src="bs3compat-0.4.0/tabs.js"></script>
<script src="bs3compat-0.4.0/bs3compat.js"></script>
<link href="shinyWidgets/shinyWidgets.min.css" rel="stylesheet" />
<script src="shinyWidgets/shinyWidgets-bindings.min.js"></script>  <style type="text/css">
    html, body { width: 100%; height: 100%; overflow: hidden; }
    body { padding: 0px; margin: 0; }
  </style>
</head>
<body>
  <div class="form-group shiny-input-container shiny-input-checkboxgroup shiny-input-container-inline">
    <label id="cluster_groups-label" class="control-label" for="cluster_groups">Clusters Displayed</label>
    <br/>
    <div id="cluster_groups" class="checkbox-group-buttons">
      <div aria-labelledby="cluster_groups-label" class="btn-group btn-group-container-sw" data-toggle="buttons" role="group">
        <input type="checkbox" autocomplete="off" id="cluster_groups1" name="cluster_groups" value="1" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups1">1</label>
        <input type="checkbox" autocomplete="off" id="cluster_groups2" name="cluster_groups" value="2" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups2">2</label>
        <input type="checkbox" autocomplete="off" id="cluster_groups3" name="cluster_groups" value="3" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups3">3</label>
        <input type="checkbox" autocomplete="off" id="cluster_groups4" name="cluster_groups" value="4" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups4">4</label>
        <input type="checkbox" autocomplete="off" id="cluster_groups5" name="cluster_groups" value="5" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups5">5</label>
        <input type="checkbox" autocomplete="off" id="cluster_groups6" name="cluster_groups" value="6" class="btn-check"/>
        <label class="btn checkbtn btn-custom-class" for="cluster_groups6">6</label>
      </div>
    </div>
  </div>
</body>
</html>

jzadra
  • 4,012
  • 2
  • 26
  • 46

0 Answers0