Search code examples
cssrshinysortablejs

How to adjust the width and margin of Sortable's rank lists?


Is there a way to define the ratio between the width of ranked list (drag from here narrow, to here wider) that are horizontally aligned? Can we adjust/reduce the space between the two lists?

Example from the sortable package (https://rstudio.github.io/sortable/)

## Example shiny app with bucket list

library(shiny)
library(sortable)

ui <- fluidPage(
  tags$head(
    tags$style(HTML(".bucket-list-container {min-height: 350px;}"))
  ),
  fluidRow(
    column(
      tags$b("Exercise"),
      width = 12,
      bucket_list(
        header = "Drag the items in any desired bucket",
        group_name = "bucket_list_group",
        orientation = "horizontal",
        add_rank_list(
          text = "Drag from here",
          labels = list(
            "one",
            "two",
            "three",
            htmltools::tags$div(
              htmltools::em("Complex"), " html tag without a name"
            ),
            "five" = htmltools::tags$div(
              htmltools::em("Complex"), " html tag with name: 'five'"
            )
          ),
          input_id = "rank_list_1"
        ),
        add_rank_list(
          text = "to here",
          labels = NULL,
          input_id = "rank_list_2"
        )
      )
    )
  ),
  fluidRow(
    column(
      width = 12,
      tags$b("Result"),
      column(
        width = 12,
        
        tags$p("input$rank_list_1"),
        verbatimTextOutput("results_1"),
        
        tags$p("input$rank_list_2"),
        verbatimTextOutput("results_2"),
        
        tags$p("input$bucket_list_group"),
        verbatimTextOutput("results_3")
      )
    )
  )
)

server <- function(input, output, session) {
  output$results_1 <-
    renderPrint(
      input$rank_list_1 # This matches the input_id of the first rank list
    )
  output$results_2 <-
    renderPrint(
      input$rank_list_2 # This matches the input_id of the second rank list
    )
  output$results_3 <-
    renderPrint(
      input$bucket_list_group # Matches the group_name of the bucket list
    )
  
}


shinyApp(ui, server)

Solution

  • The bucket list uses flex and acts as a container for the two rank lists. If you would like to have a narrow left list and a more wide right list, you can adjust the ratios of the flex items (see also Controlling ratios of flex items along the main axis within the MDN docs). As an example, if the left list should take 1/3 of the available space and the right list should take 2/3, you could add

    #rank-list-rank_list_1 {
      flex: 1 1 0;
    }
    
    #rank-list-rank_list_2 {
      flex: 2 1 0;
    }
    

    If you additionally want to have a minimal space between the two lists, you can change margin-right of the left list to 0 and margin-left of the right list to 0 (see the article on margin within the docs).

    enter image description here

    library(shiny)
    library(sortable)
    
    ui <- fluidPage(
      tags$head(
        tags$style(HTML(".bucket-list-container {min-height: 350px;}
                         #rank-list-rank_list_1 {
                           flex: 1 0 0;
                           margin-right: 0;
                         }
                         #rank-list-rank_list_2 {
                           flex: 2 0 0;
                           margin-left: 0;
                         }"))
      ),
      fluidRow(
        column(
          tags$b("Exercise"),
          width = 12,
          bucket_list(
            header = "Drag the items in any desired bucket",
            group_name = "bucket_list_group",
            orientation = "horizontal",
            add_rank_list(
              text = "Drag from here",
              labels = list(
                "one",
                "two",
                "three",
                htmltools::tags$div(
                  htmltools::em("Complex"), " html tag without a name"
                ),
                "five" = htmltools::tags$div(
                  htmltools::em("Complex"), " html tag with name: 'five'"
                )
              ),
              input_id = "rank_list_1"
            ),
            add_rank_list(
              text = "to here",
              labels = NULL,
              input_id = "rank_list_2"
            )
          )
        )
      ),
      fluidRow(
        column(
          width = 12,
          tags$b("Result"),
          column(
            width = 12,
            
            tags$p("input$rank_list_1"),
            verbatimTextOutput("results_1"),
            
            tags$p("input$rank_list_2"),
            verbatimTextOutput("results_2"),
            
            tags$p("input$bucket_list_group"),
            verbatimTextOutput("results_3")
          )
        )
      )
    )
    
    server <- function(input, output, session) {
      output$results_1 <-
        renderPrint(
          input$rank_list_1 # This matches the input_id of the first rank list
        )
      output$results_2 <-
        renderPrint(
          input$rank_list_2 # This matches the input_id of the second rank list
        )
      output$results_3 <-
        renderPrint(
          input$bucket_list_group # Matches the group_name of the bucket list
        )
      
    }
    
    
    shinyApp(ui, server)