rshinyshinywidgetsbslib

How to get virtualSelectInput() options to extend past the bslib sidebar?


Once I open the dropdown, I would like the full item name to be visible, i.e. overflowing the dashboard's body. The names are cut at the sidebar border by default.

I'd love to develop my front-end skills to where I can solve this on my own. But currently I cannot solve it despite seeing similar examples like this one.

A solution with an explanation of how to tackle such problems would be much appreciated.

library(shiny)
library(bslib)
library(shinyWidgets)

vec_long_items <- sapply(1:10, function(i) {
  paste(sample(letters, 100, replace = TRUE), collapse = "")
})

shinyApp(
  ui = page_sidebar(
    title = "Long items to select",
    sidebar = sidebar(
      virtualSelectInput(
        inputId = "in1", 
        label = "Input 1", 
        choices = vec_long_items, 
      ),
    ),
  ),
  server = function(input, output, session) {
    output$out_text <- renderTable(data.frame(items = vec_long_items))
  }
)

Solution

  • The elements of the virtual select are displayed in a dropbox-container and depending on your current view this can be above or below the dropdown. You can override the css properties width and max-width of these two selectors:

    .vscomp-dropbox-container.pop-comp-wrapper.position-top,
    .vscomp-dropbox-container.pop-comp-wrapper.position-bottom 
      {
        width: fit-content !important; /* make boxes fit their content */
        max-width: unset !important;   /* overwrite default max-width for larger boxes */
      }
    

    And then we need one additional adjustment: A virtual-select has a dropBoxWrapper property which defines the parent element to render the dropbox. This is set to self by default and we set this to body, i.e., we set

    dropboxWrapper = "body"
    

    in the virtualSelectInput. This makes the dropbox not getting limited by the sidebar.

    enter image description here

    library(shiny)
    library(bslib)
    library(shinyWidgets)
    
    vec_long_items <- sapply(1:10, function(i) {
      paste(sample(letters, 100, replace = TRUE), collapse = "")
    })
    
    css <- "
    .vscomp-dropbox-container.pop-comp-wrapper.position-top,
    .vscomp-dropbox-container.pop-comp-wrapper.position-bottom 
      {
        width: fit-content !important; 
        max-width: unset !important;
      }"
    
    shinyApp(
      ui = page_sidebar(
        title = "Long items to select",
        tags$head(
          tags$style(HTML(css))
        ),
        sidebar = sidebar(
          virtualSelectInput(
            inputId = "in1", 
            label = "Input 1", 
            choices = vec_long_items,
            dropboxWrapper = "body"
          ),
        )
      ),
      server = function(input, output, session) {
        output$out_text <- renderTable(data.frame(items = vec_long_items))
      }
    )