Search code examples
rshiny

How to change a tippy tooltip depending on the selected tab?


I have an app with a sidebar from shinydashboard and multiple tabs in a tabBox. In the sidebar I want to have an info button - and when you hover over it, a different text depending on which tab you're currently on should display.

One solution that works, but is in my opinion pretty ugly, is to define identical infobuttons with different tooltips for each tab, like so:

library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(tippy)

ui <- dashboardPage(
  skin = 'blue',
  dashboardHeader(),
  dashboardSidebar(width = 275,
                   sidebarMenu(conditionalPanel(condition = "input.my_tabbox == 'panel_1'",
                                                actionBttn(inputId = "info_button",label = NULL,style = 'material-circle',color = 'primary',
                                                           icon = icon('info')),
                                                tippy_this("info_button",tooltip = "You are on panel 1",trigger = 'mouseenter focus',
                                                           placement = 'right')),
                               conditionalPanel(condition = "input.my_tabbox == 'panel_2'",
                                                actionBttn(inputId = "info_button_2",label = NULL,style = 'material-circle',color = 'primary',
                                                           icon = icon('info')),
                                                tippy_this("info_button_2",tooltip = "You are on panel 2",trigger = 'mouseenter focus',
                                                           placement = 'right')))),

  dashboardBody(
    fluidRow(column(width = 12,
                    tabBox(width = 12,id = "my_tabbox",
                           tabPanel(title = "Panel 1",value = "panel_1"),
                           tabPanel(title = "Panel 2",value = "panel_2"))))
  )
)

server <- function(input,output){}
shinyApp(ui = ui,server = server)

However, if I ever want to change the looks or behaviour of the info button, I'd have to redo this for every single tab. So I looked for a different solution: Is it possible to define the button only once and just change the tooltip text? I tried to outsource the tippy_this with renderUI, but it did not work, this is a failed attempt of mine:

ui <- dashboardPage(
  skin = 'blue',
  dashboardHeader(),
  dashboardSidebar(width = 275,
                   sidebarMenu(actionBttn(inputId = "info_button",label = NULL,style = 'material-circle',color = 'primary',icon = icon('info')),
                               uiOutput("my_tippy"))),
  dashboardBody(
    fluidRow(column(width = 12,
                    tabBox(width = 12,id = "my_tabbox",
                           tabPanel(title = "Panel 1",value = "panel_1"),
                           tabPanel(title = "Panel 2",value = "panel_2"))))
  )
)

get_tippy_sentence <- function(tabbox_input){
  if(tabbox_input == "panel_1"){
    return("You are on panel 1")
  }else if(tabbox_input == "panel_2"){
    return("You are on panel 2")
  }
}

server <- function(input,output){
  
  output$my_tippy <- renderUI({
    tippy_this("info_button",tooltip = get_tippy_sentence(input$my_tabbox),trigger = 'mouseenter focus',placement = 'right')
  })
}

I also tried to make the tooltip a reactive and change it with an observeEvent(input$my_tabbox,{...}), but none of those iterations ever managed to display anything different for the second tab.


Solution

  • This is possible if you use a little bit of custom JS. In what follows, similar to your example the text of the tippy is generated dynamically depending on which tab is active. Initially, tab 1 is displayed.

    $(document).ready(function() {
    
        tippy('#info_button', {
            content: 'You are on panel 1',
            placement: 'right'
        });
    
        $('#my_tabbox').on('shown.bs.tab', function() {
            var panelText = $('#my_tabbox').children('.active').prop('innerText');
            var hoverText = 'You are on ' + panelText;
    
            document.querySelector('#info_button')._tippy.setContent(hoverText);
        });
    })
    

    enter image description here

    library(shiny)
    library(shinydashboard)
    library(shinyWidgets)
    library(tippy)
    
    js <- "
    $(document).ready(function() {
    
        tippy('#info_button', {
            content: 'You are on panel 1',
            placement: 'right'
        });
    
        $('#my_tabbox').on('shown.bs.tab', function() {
            var panelText = $('#my_tabbox').children('.active').prop('innerText');
            var hoverText = 'You are on ' + panelText;
    
            document.querySelector('#info_button')._tippy.setContent(hoverText)
        });
    })
    "
    
    ui <- dashboardPage(skin = 'blue',
                        dashboardHeader(),
                        dashboardSidebar(width = 275,
                                         sidebarMenu(
                                             actionBttn(
                                                 inputId = "info_button",
                                                 label = NULL,
                                                 style = 'material-circle',
                                                 color = 'primary',
                                                 icon = icon('info')
                                             ),
                                             tippy_this(
                                                 "info_button",
                                                 tooltip = "",
                                                 trigger = 'mouseenter focus',
                                                 placement = 'right'
                                             )
                                         )),
    
    dashboardBody(tags$head(tags$script(JS(js))),
                  fluidRow(column(
                      width = 12,
                      tabBox(
                          width = 12,
                          id = "my_tabbox",
                          tabPanel(title = "Panel 1", value = "panel_1"),
                          tabPanel(title = "Panel 2", value = "panel_2")
                      )
                  )))
    )
    
    server <- function(input, output) {
        
    }
    shinyApp(ui = ui, server = server)