Search code examples
rshinybslib

Conditional bslib tooltip


I'm developing an Rshiny app where I would like a bslib::tooltip to conditionally appear on certain tabs. I've gotten as far as only showing text under desired conditions:

input showing desired tooltip

but I still get a black pointer and container space appearing in the other conditions:

input showing undesired pointer and empty container

appR:

library(bslib) # bootstrap theme
library(shiny) # runs the show

# real app uses modules
sidebarSel_ui <- function(id){
  ns <- NS(id)
  
  # conditional choices based on tab
  choiceTxt <- if (id=="pg1") {
    c("Choice 1","Choice 2","Choice 3","Choice 4")
  } else if (id=="pg2") {
    c("Choice 1","Choice 2")
  }
  
  # conditional tooltip based on tab
  tipTxt <- if (id=="pg1") {
    "Some info about choices 3 and 4"
  } else {
    NULL # leaves black pointer and container space
  }
  
  # send to UI
  tagList(
    selectInput(
      inputId=ns("select1"),
      label="Some choices",
      choices=choiceTxt,
      selectize=FALSE,
      selected="Choice 1"
    ) |>
      tooltip(tipTxt, placement="right") # looks weird on tab 2 
  )
}

ui <- page_fluid(
  # call CSS theme
  theme=bs_theme(bootswatch="cosmo"),
  sidebarLayout(
    sidebarPanel(
      width=2,
      conditionalPanel(
        condition="input.condPanel==1",
        sidebarSel_ui("pg1")
      ),
      conditionalPanel(
        condition="input.condPanel==2",
        sidebarSel_ui("pg2")
      )
    ),
    mainPanel(
      width=10,
      tabsetPanel(
        id="condPanel",
        tabPanel(
          title="Tab 1",
          value=1
        ),
        tabPanel(
          title="Tab 2",
          value=2
        )
      )
    )
  )
)

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

shinyApp(ui = ui, server = server)

I tried putting the tooltip inside a conditionalPanel, but it wouldn't work because the tooltip is piped after selectInput - the input is actually the first argument for the tooltip (and is therefore wrapped in a tooltip div when rendered), so I can't figure out how to make just the tooltip conditional while leaving the rest of the input alone. Is there anything I can do to get rid of the black pointer and empty container when I don't want the tooltip to appear?


Solution

  • Only add the tooltip if id == "pg1". SidebarSel_ui() now becomes:

    sidebarSel_ui <- function(id) {
      ns <- NS(id)
    
      # conditional choices based on tab
      choiceTxt <- if (id == "pg1") {
        c("Choice 1", "Choice 2", "Choice 3", "Choice 4")
      } else if (id == "pg2") {
        c("Choice 1", "Choice 2")
      }
    
      input <- selectInput(
        inputId = ns("select1"),
        label = "Some choices",
        choices = choiceTxt,
        selectize = FALSE,
        selected = "Choice 1"
      )
    
      if (id == "pg1") {
        tipTxt <- "Some info about choices 3 and 4"
        input <- input |> tooltip(tipTxt, placement = "right")
      }
    
      input
    }