bslib icon indicating copy to clipboard operation
bslib copied to clipboard

`selectInput()`'s dropdown clipped inside a `card()`

Open DavideMagno opened this issue 2 years ago • 9 comments

Hi, thanks a lot for release 0.5, it looks very neat!

One question: I have a selectInput in a card, but since it's very long it requires scrolling as it doesn't overlap with other cards. This is a fundamentally different behaviour as the "box" ui in shinydashboard, which I very much liked.

How can I make it work the same in bslib?

Screenshot 2023-06-08 alle 19 59 06

Cheers, Davide

DavideMagno avatar Jun 08 '23 18:06 DavideMagno

This was also reported in #502 where the proposed workaround is to add style = "overflow: visible" to the card() and card_body() with the long select input menu. If you have htmltools loaded, you can use style = css(overflow = "visible").

That's not the most user-friendly approach, but it's a reasonable path to take given that setting overflow: visible for all cards wouldn't be a good default setting.

Here are two demo apps based on the example in #502. With shinydashboard:

library(shiny)
library(htmltools)
library(shinydashboard)
server <- function(input, output) { }

ui_sd <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    box(
      selectInput("test", label = NULL, choices = colnames(mtcars))
    ),
    box(
      selectInput("test1", label = NULL, choices = colnames(mtcars))
    )
  )
)

shinyApp(ui_sd, server)

And here's a similar app with bslib:

# With {bslib} ---------------------------------------------------
library(shiny)
library(htmltools)
library(bslib)
server <- function(input, output) { }

ui_bslib <- fluidPage(
  theme = bslib::bs_theme(version = 5),
  card(
    style = css(overflow = "visible"),
    card_body(
      style = css(overflow = "visible"),
      selectInput("test", label = NULL, choices = colnames(mtcars))
    )
  ),
  selectInput("test1", label = NULL, choices = colnames(mtcars))
)

shinyApp(ui_bslib, server)

gadenbuie avatar Jun 09 '23 14:06 gadenbuie

Also reported on Posit Community: https://community.rstudio.com/t/selectinput-within-navs-tab-card-options-cut-off/163460

gadenbuie avatar Jul 13 '23 21:07 gadenbuie

The overflow:visible trick will work for a single card(), but similar issues will occur if you put the card() in another parent container with overflow:auto. As a more general workaround, I'd recommend using selectizeInput()'s dropdownParent option:

ui <- page_fluid(
  card(
    selectizeInput(
      "test", label = NULL, choices = colnames(mtcars), 
      options = list(dropdownParent = "body")
    )
  ),
  selectInput("test1", label = NULL, choices = colnames(mtcars))
)

shinyApp(ui, function(...) { })

cpsievert avatar Jul 14 '23 14:07 cpsievert

That's neat (TIL)! Should we consider setting this option by default in shiny? (Is that technically possible?) Are there non-obvious downsides to setting this globally?

gadenbuie avatar Jul 14 '23 15:07 gadenbuie

I feel like there might be some old issues that discuss it...I can't think of any reason not to off the top of my head, but I'm sure it has the potential to break legacy apps.

As a middle-ground solution, we could maybe consider defaulting to that option in the binding if we detect window.bootstap.VERSION >= 5?

cpsievert avatar Jul 14 '23 15:07 cpsievert

We actually added it and then removed it:

  • Added: https://github.com/rstudio/shiny/pull/3413
  • Removed: https://github.com/rstudio/shiny/pull/3450
  • Because: https://github.com/rstudio/shiny/issues/3448

Maybe we could explore another approach to handle this in the select input binding

gadenbuie avatar Jul 14 '23 17:07 gadenbuie

Ahh yea, this also made me realize that dropdownParent = "body" won't work with full_screen = TRUE (at least currently)

cpsievert avatar Jul 14 '23 18:07 cpsievert

With the latest (dev) version of bslib, you can now do this (and count on it working reliably).

page_fluid(
  theme = bs_theme() |>
    bs_add_rules(c(
      ".card {overflow: visible !important;}",
      ".card-body {overflow: visible !important;}"
    )),
  card(
    selectizeInput("test", label = NULL, choices = colnames(mtcars))
  )
) |>
  shinyApp(function(...) { })

That said, it feels like we should make this easier, possibly through a card(scrolling = FALSE) argument?

cpsievert avatar Oct 24 '23 20:10 cpsievert

Another option is to use the overflow-visible helper class:

page_fluid(
  card(
    class = "overflow-visible",
    card_body(
      class = "overflow-visible",
      selectizeInput("test", label = NULL, choices = colnames(mtcars))
    )
  )
)

gadenbuie avatar Oct 24 '23 20:10 gadenbuie