I would like to write an introduction tour using the function introjs for my R shiny app where one of the elements which gets highlighted is a pickerInput. But I am having troubles with the correct highlighting.
Here's an example:
library(shiny)
library(rintrojs)
ui <- fluidPage(
introjsUI(),
pickerInput(
inputId = "color",
label = "What is your favorite color?",
choices = c("Red", "Green", "Blue")
),
br(),
actionButton(inputId = "tour", label = "Start Tour")
)
server <- function(input, output, session) {
introjs(session)
observeEvent(input$tour, {
introjs(session, options = list(
steps = list(
list(element = "#color",
intro = "Pick a color."),
list(element = "#tour",
intro = "This is a button.")
)
))
})
}
shinyApp(ui, server)
I would like to have the whole pickerInput highlighted (like it does when it highlights the button). But this is what happenes:
Something is wrong with the highlighting:
If I use the introBox instead of specifiying the elements of the tour within the introjs-call the problem is solved. But since I would like to implement multiple tours, the soluiton in this post suggests to not use the introBox.
Is there a way to highlight the pickerInput correctly?
You need to change the css selector you are highlighting. Use .dropdown
instead of #color
This
list(element = "#color",
intro = "Pick a color."),
should be changed to this:
list(element = ".dropdown",
intro = "Pick a color."),
Explanation: The html id that you defined as #color
in the pickerInput()
function isn't actually the html id for the dropdown menu, it's the html id for the option you selected from the dropdown menu. This is useful if you need to access that selection in the server, but to change the appearance of the dropdown menu (or target it with introjs), you have to use the css selector for #color
's parent container which is .dropdown
.
This is the dropdown menu class not the id for that specific dropdown menu, so if you have multiple dropdown menus they may all get selected. If that's a problem you could work around it by targeting that menu's html id instead or wrapping that dropdown menu in a div and then target that div.
Use the web developer tools to find their html ids and then target them individually. If you want memorable names you'll probably need to wrap them in tags$div()
like this tags$div(id="memorable-name",pickerInput(...) )
, but then you'll probably also need to adjust the css for #memorable-name
to get the div to be the same size as the child dropdown menu.
Here's an example of just using the html ids found using the developer tools for two dropdown menus
library(shiny)
library(rintrojs)
ui <- fluidPage(
introjsUI(),
pickerInput(
inputId = "color",
label = "What is your favorite color?",
choices = c("Red", "Green", "Blue")
),
br(),
pickerInput(
inputId = "fruit",
label = "What is your favorite fruit?",
choices = c("Apples", "Oranges", "Bananas")
),
br(),
actionButton(inputId = "tour", label = "Start Tour")
)
server <- function(input, output, session) {
introjs(session)
observeEvent(input$tour, {
introjs(session, options = list(
steps = list(
list(element = "div.form-group:nth-child(1) > div:nth-child(2)",
intro = "Pick a color."),
list(element = "div.form-group:nth-child(3) > div:nth-child(2)",
intro = "Pick a fruit."),
list(element = "#tour",
intro = "This is a button.")
)
))
})
}
shinyApp(ui, server)