rshinybslib

Is there a way to use fill items in a bslib sidebar?


I can't find a way to use fill items in a bslib sidebar.

In this case I am trying to put an element in the bottom of the sidebar.

layout_sidebar is fillable, but only the main area is fillable.

This puts properly the top and bottom elements in the main area:

library(bslib)

ui <- page_fillable(
  layout_sidebar(
    # sidebar = sidebar(
      card(
        fill = TRUE,
        fillable = TRUE,
        card_body(
          fill = FALSE,
          h1("top")
        ),
        card_body(
          fill = TRUE
        ),
        card_body(
          fill = FALSE,
          h1("bottom")
        )
      )
    # )
  )
)

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

shinyApp(ui, server)

Fillable main area:

enter image description here

I would like to have the same behavior in the sidebar.

library(bslib)

ui <- page_fillable(
  layout_sidebar(
    sidebar = sidebar(
      fillable = TRUE,
      card(
        fill = TRUE,
        fillable = TRUE,
        card_body(
          fill = FALSE,
          h1("top")
        ),
        card_body(
          fill = TRUE
        ),
        card_body(
          fill = FALSE,
          h1("bottom")
        )
      )
    )
  )
)

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

shinyApp(ui, server)

Non fillable sidebar:

enter image description here

I tried using as_fill_carrier() on the sidebar but it returns this warning:

Warning: `bindFillRole()` only works on htmltools::tag() objects 
(e.g., div(), p(), etc.), not objects of type 'bslib_sidebar'.

Solution

  • The relevant part of the DOM here looks like this (aside > .sidebar-content > bslib::card()):

    <aside id="bslib-sidebar-5784" class="sidebar" hidden>
      <div class="sidebar-content bslib-gap-spacing">
        <div class="card bslib-card bslib-mb-spacing html-fill-item html-fill-container" 
             data-bslib-card-init data-require-bs-caller="card()" data-require-bs-version="5">
          ...
    

    From the card on the setup is suitable. What you need to add is (see also the article on Filling layouts in the bslib docs):

    Below this is implemented via htmltools::tagQuery().

    enter image description here

    library(shiny)
    library(bslib)
    
    ui <- page_fillable(
      layout_sidebar(
        sidebar = sidebar(
          card(
            card_body(
              fill = FALSE,
              h1("top")
            ),
            card_body(),
            card_body(
              fill = FALSE,
              h1("bottom")
            )
          )
        ) 
      ) 
    )
    
    ui <- htmltools::tagQuery(ui)$
      find("aside")$
      addClass("html-fill-container")$
      find(".sidebar-content")$
      addClass("html-fill-container html-fill-item")$
      allTags()
    
    shinyApp(ui, \(...){})