Search code examples
htmlcssrshinysortablejs

In Shiny, how to set CSS grid so that the panels embedded in columns extend independently of each other?


I am completely new to CSS/HTML and am stumbling through. A web programmer told me I'm effectively looking for a "flex box".

I am setting up a 2-column grid in CSS, where the left-column will have a series of input panels where the values are dragged/dropped into a single panel in the right column. The left-column panels will be of fixed height, always. The single right-column panel expands vertically as the user drags/drops into it, as it does presently per the below reproducible code. I'd like the expansion of the right-column panel to not change the heights of the panels in the left-column.

How can this be done?

The images at the bottom better explain.

Reproducible code:

library(shiny)
library(sortable)   
library(htmlwidgets)

icon_list <- function(x){lapply(x,function(x) {tags$div(tags$strong(x))})}

ui <- fluidPage(

# parent (I think!):        
  div(style = "margin-top: 2rem; width: 60%; display: grid; grid-template-columns: 1fr 1fr; gap: 2rem;",
  
  # the below 3 div(...) are children of the above parent div(...)
  
    div(class = "panel panel-default",
        div(class = "panel-heading", "Drag from here"),
        div(class = "panel-body", 
            id= "sort1",
            icon_list(c("A","B","C","D","E"))
            )
    ),
    div(class = "panel panel-default",
        div(class = "panel-heading", "Drag to here"),
        div(class = "panel-body", 
            id = "sort2"
            )
    ),
        
    div(class = "panel panel-default",
        div(class = "panel-heading", "Trash bin"),
        div(class = "panel-body", 
            id = "sortable_bin"
            )
    )
  
  ),
  sortable_js(
    "sort1",
    options = sortable_options(
      group = list(
        pull = "clone",
        name = "sortGroup1",
        put = FALSE)
    )
  ),
  sortable_js(
    "sort2",
    options = sortable_options(
      group = list(
        group = "sortGroup1",
        put = TRUE,
        pull = TRUE)
    )
  ),
  sortable_js(
    "sortable_bin",
    options = sortable_options(
      group = list(
        group = "sortGroup1",
        put = TRUE,
        pull = TRUE),
      onAdd = htmlwidgets::JS("function (evt) { this.el.removeChild(evt.item); }")
    )
  )
)

server <- function(input, output) {}

shinyApp(ui, server)

Explanatory images:

enter image description here

enter image description here

enter image description here


Solution

  • The css-grid messes up some things, if you add align-items: start than you have the elments "running" down the page, so I wrapped the 2x2 grid that you have into a 1x1, where the left column has both divs for "Drag from here" and "Trash bin":

    library(shiny)
    library(sortable)
    library(htmlwidgets)
    
    icon_list <- function(x) {
      lapply(x, function(x) {
        tags$div(tags$strong(x))
      })
    }
    
    ui <- fluidPage(
    
      # parent (I think!):
      div(
        style = "margin-top: 2rem; width: 60%; display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; align-items: start;",
    
        # the below 3 div(...) are children of the above parent div(...)
        div(
          div(
            class = "panel panel-default",
            div(class = "panel-heading", "Drag from here"),
            div(
              class = "panel-body",
              id = "sort1",
              icon_list(c("A", "B", "C", "D", "E"))
            )
          ),
          div(
            class = "panel panel-default",
            div(class = "panel-heading", "Trash bin"),
            div(
              class = "panel-body",
              id = "sortable_bin"
            )
          )
        ),
        div(div(
          class = "panel panel-default",
          div(class = "panel-heading", "Drag to here"),
          div(
            class = "panel-body",
            id = "sort2"
          )
        ))
      ),
      sortable_js(
        "sort1",
        options = sortable_options(
          group = list(
            pull = "clone",
            name = "sortGroup1",
            put = FALSE
          )
        )
      ),
      sortable_js(
        "sort2",
        options = sortable_options(
          group = list(
            group = "sortGroup1",
            put = TRUE,
            pull = TRUE
          )
        )
      ),
      sortable_js(
        "sortable_bin",
        options = sortable_options(
          group = list(
            group = "sortGroup1",
            put = TRUE,
            pull = TRUE
          ),
          onAdd = htmlwidgets::JS("function (evt) { this.el.removeChild(evt.item); }")
        )
      )
    )
    
    server <- function(input, output) {}
    
    shinyApp(ui, server)
    

    enter image description here