Shiny button stays active unless another button from same div is clicked

The following Shiny app has 3 buttons (blue when inactive). When a button is clicked (active) it should turn red until another button is clicked. If the user clicks elsewhere in the app (e.g. background, or any other widget than the buttons), the clicked button should stay red.

library(shiny)
library(shinyjs)

ui <- fluidPage(
    useShinyjs(),
    
    # CSS
    tags$head(
        tags$style(HTML("
            .btn{
                color: white;
            }
            .item{
                background-color: lightblue;
            }
            .active{
                background-color: red;
            }
        "))
    ),
    
    div(id = "buttons",
        actionButton(inputId = "button_1", label = "Button 1", class = "item"),
        actionButton(inputId = "button_2", label = "Button 2", class = "item"),
        actionButton(inputId = "button_3", label = "Button 3", class = "item")
    )
)

server <- function(input, output, session) {
    # JS
    runjs(HTML("
        $('#buttons .item').on('click',function(){
            $('#buttons .item.active').removeClass('active');
            $(this).addClass('active');
        });
    "))
    
    session$onSessionEnded(stopApp)
    
}

shinyApp(ui, server)

This behaviour works in the snippet below but in the app the buttons do not turn red when clicked.

$('#buttons .item').on('click',function(){
    $('#buttons .item.active').removeClass('active');
    $(this).addClass('active');
});
button{
  color: white;
}
.item{
  background-color: lightblue;
}
.active{
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="buttons">
  <button class="item">Button 1</button>
  <button class="item">Button 2</button>
  <button class="item">Button 3</button>
</div>

Answer

That’s because there’s already a class named active in Shiny which sets a background color to the buttons. So you have to use another name and use !important. And you don’t need HTML in runjs().

library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  
  # CSS
  tags$head(
    tags$style(HTML("
            .btn{
                color: white;
            }
            .item{
                background-color: lightblue;
            }
            .myactive{
                background-color: red !important;
            }
        "))
  ),
  
  div(id = "buttons",
      actionButton(inputId = "button_1", label = "Button 1", class = "item"),
      actionButton(inputId = "button_2", label = "Button 2", class = "item"),
      actionButton(inputId = "button_3", label = "Button 3", class = "item")
  )
)

server <- function(input, output, session) {
  # JS
  runjs("
        $('#buttons .item').on('click',function(){
            $('#buttons .item.myactive').removeClass('myactive');
            $(this).addClass('myactive');
        });
    ")
  
  session$onSessionEnded(stopApp)
  
}

shinyApp(ui, server)