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>