knitr::opts_chunk$set(
  echo = TRUE,
  collapse = TRUE,
  comment = "#>"
)
library(shiny)
library(shiny.semantic)
library(shiny.layouts)

Two main things shiny.layouts provides is pre-defined app layouts (like app with a sidebar and a main panel) and easy interface to put elements in a custom grid (based on CSS grid). In this article we will see how to use these two features. To make examples look better and shorten their code, we will use shiny.semantic, but shiny.layouts works with any UI framework.

Built-in layouts

Let's start by defining a page wtih a sidebar layout (sidebar_layout()) with a sidebar panel (sidebar_panel()) and main panel (main_panel()). The sidebar is displayed with a distinct background color and typically contains input controls. The main area occupies 2/3 of the horizontal width and typically contains outputs.

screen2

ui <- semanticPage(
  title = "My first page",
  h1("My page"),
  sidebar_layout(
    sidebar_panel(),
    main_panel()
    )
)

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

shinyApp(ui, server)

Next let's fill in the main panel main_panel() with a Semantic UI segment containing 2 cards.

screen3

ui <- semanticPage(
  title = "My first page",
  h1("My page"),
  sidebar_layout(
    sidebar_panel(),
    main_panel(
      segment(
         cards(
           class = "two",
           card(class = "red",
             div(class = "content",
                 div(class = "header", "Main title card 1"),
                 div(class = "meta", "Sub title card 1"),
                 div(class = "description", "More detail description card 1")
             )
           ),
           card(class = "blue",
             div(class = "content",
                 div(class = "header", "Main title card 2"),
                 div(class = "meta", "Sub title card 2"),
                 div(class = "description", "More detail description card 2")
                 )
             )
           )
         )
      )
    )
  )

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

shinyApp(ui, server)

Time to fill in sidebar sidebar_panel(), so let's add a dropdown. We create it input using dropdown_input().

screen4

ui <- semanticPage(
  title = "My first page",
  h1("My page"),
  sidebar_layout(
    sidebar_panel(
      dropdown_input("mtcars_dropdown", c("mpg", "cyl", "disp", "hp"), value = "mpg"),
      textOutput("dropdown")
    ),
    main_panel(
      segment(
         cards(
           class = "two",
           card(class = "red",
             div(class = "content",
                 div(class = "header", "Main title card 1"),
                 div(class = "meta", "Sub title card 1"),
                 div(class = "description", "More detail description card 1")
             )
           ),
           card(class = "blue",
             div(class = "content",
                 div(class = "header", "Main title card 2"),
                 div(class = "meta", "Sub title card 2"),
                 div(class = "description", "More detail description card 2")
             )
           )
         )
      )
      )
    )
)

server <- function(input, output, session) {
  output$dropdown <- renderText(input$mtcars_dropdown)
}

shinyApp(ui, server)

Let's make dropdown do something and generate a histogram and a simple plot from a selected mtcars column using dropdown.

screen5

ui <- semanticPage(
  title = "My first page",
  h1("My page"),
  sidebar_layout(
    sidebar_panel(
      p("Select variable for plots:"),
      dropdown_input("mtcars_dropdown", c("mpg", "cyl", "disp", "hp"), value = "mpg")
    ),
    main_panel(
      segment(
         cards(
           class = "two",
           card(class = "red",
             div(class = "content",
                 div(class = "header", "Main title card 1"),
                 div(class = "meta", "Sub title card 1"),
                 div(class = "description", "More detail description card 1")
             )
           ),
           card(class = "blue",
             div(class = "content",
                 div(class = "header", "Main title card 2"),
                 div(class = "meta", "Sub title card 2"),
                 div(class = "description", "More detail description card 2")
             )
           )
         )
      ),
      plotOutput("histogram"),
      plotOutput("plot")
      )
    )
)

server <- function(input, output, session) {
  output$dropdown <- renderText(input$mtcars_dropdown)
  output$histogram <- renderPlot(hist(mtcars[[input$mtcars_dropdown]]))
  output$plot <- renderPlot(plot(mtcars[[input$mtcars_dropdown]]))
}

shinyApp(ui, server)

There is more layouts that you can use. Just check the documentation of: split_layout, flow_layout, vertical_layout and more.

Grid templates

Finally let's change the layout of the plots on the page and make them appear next to each other. We will use grid() for it and define a grid template using grid_template() with 1 row and 2 columns of the same size. Our grid template will contain 2 areas chart1 and chart2

grid_charts <- grid_template(
  default = list(areas = rbind(c("chart1", "chart2")),
                 rows_height = c("100%"),
                 cols_width = c("50%", "50%"))
)

We assign plots' outputs plotOutput() to both areas inside the grid function.

This is the final effect of our work:

screen6

ui <- semanticPage(
  title = "My first page",
  h1("My page"),
  sidebar_layout(
    sidebar_panel(
      p("Select variable for plots:"),
      dropdown_input("mtcars_dropdown", c("mpg", "cyl", "disp", "hp"), value = "mpg")
    ),
    main_panel(
      segment(
         cards(
           class = "two",
           card(class = "red",
             div(class = "content",
                 div(class = "header", "Main title card 1"),
                 div(class = "meta", "Sub title card 1"),
                 div(class = "description", "More detail description card 1")
             )
           ),
           card(class = "blue",
             div(class = "content",
                 div(class = "header", "Main title card 2"),
                 div(class = "meta", "Sub title card 2"),
                 div(class = "description", "More detail description card 2")
             )
           )
         )
      ),
      grid(grid_charts,
           chart1 = plotOutput("histogram"),
           chart2 = plotOutput("plot")
         )
      )
    )
)

server <- function(input, output, session) {
  output$dropdown <- renderText(input$mtcars_dropdown)
  output$histogram <- renderPlot(hist(mtcars[[input$mtcars_dropdown]]))
  output$plot <- renderPlot(plot(mtcars[[input$mtcars_dropdown]]))
}

shinyApp(ui, server)

You can define grids for different screen sizes. Here is an example on how to define it for mobile.



Appsilon/shiny.layouts documentation built on Feb. 17, 2021, 12:01 a.m.