Layout Panels

Understanding how to build a user interface

In this section we discuss the layout of a Shiny app.

fluidRow()

One useful function for customizing the layout of your app is fluidRow(). This function creates horizontal rows where objects can be placed.

You can add as many rows as you want, but you want to be careful about expanding your app too much vertically as your users might not be willing to scroll down to interact with your app in full.

library(shiny)

# Define UI with fluid rows
ui <- fluidPage(
  "Side", "by", "side", "text",
  fluidRow("Text on row 1"),
  fluidRow("Text on row 2"),
  fluidRow("Text on row 3")
)

# Define server function that does nothing
server <- function(input, output, session) {}

# Create the app object
shinyApp(ui = ui, server = server)

Side by side text

Text on row 1
Text on row 2
Text on row 3


column()

The column function is also incredibly useful. It adds columns within a row, and it requires that you define a width for each column.

library(shiny)

# Define UI with fluid rows and columns
ui <- fluidPage(
  fluidRow(
    column("R1, C1, width = 3", width = 3),
    column("R1, C2, width = 9", width = 9)
  ),
  fluidRow(
    column("R2, C1, width = 4", width = 4),
    column("R2, C2, width = 4", width = 4),
    column("R2, C3, width = 4", width = 4)
  )
)

# Define server function that does nothing
server <- function(input, output, session) {}

# Create the app object
shinyApp(ui = ui, server = server)

R1, C1, width = 3

R1, C2, width = 9

R2, C1, width = 4

R2, C2, width = 4

R2, C3, width = 4


The width is relative

The total width of columns within any given row should add up to 12. You can use the columns to place output objects like a plots or summary tables in specific places in your app.


3 + 9 = 12

R1, C1

width = 3

R1, C2, width = 9

4 + 4 + 4 = 12

R2, C1, width = 4

R2, C2, width = 4

R2, C3, width = 4


Panels

You can use panels to group multiple elements into a single element that has its own properties.

This is especially important and useful for complex apps with a large number of inputs and outputs such that it might not be clear to the user where to get started.

wellPanel()

The wellpanel() function groups elements into a grey well, or a box with rounded corners. This is a look you should be used to seeing in shiny apps by now.

library(shiny)

# Define UI with wellPanels
ui <- fluidPage(
  wellPanel( fluidRow("Row 1") ),
  wellPanel( fluidRow("Row 2") ),
  wellPanel( fluidRow("Row 3") )
)

# Define server function that does nothing
server <- function(input, output, session) {}

# Create the app object
shinyApp(ui = ui, server = server)

Row 1

Row 2

Row 3


Panels

Shiny offers 12 different panels, but we’ll take a look at a small subset of them in this section, and then you’ll get to work with a few others in the exercises that follow.

sidebarPanel() and mainPanel()

We have made heavy use of sidebarPanel() and mainPanel() in our apps in this course. However we mostly stuck with their default widths.

The default width for a sidebarPanel() is 4 and for a mainPanel() is 8.

library(shiny)

# Define UI with default width sidebar
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      strong("Sidebar"),
      "Usually inputs go here, width = 4 by default"
      ),
    mainPanel(
      strong("Main panel"),
      "Usually outputs go here, width = 8 by default"
      )
  )
)

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

shinyApp(ui = ui, server = server)

Sidebar Usually inputs go here, width = 4 by default

Main panel Usually outputs go here, width = 8 by default


If you wanted to make an app where the sidebar and mainPanel are of equal width, so the app is split down the middle, you can specify a width argument to the sidebarPanel() and mainPanel() functions and set each to 6.

library(shiny)

# Define UI with default width sidebar
fluidPage(
  sidebarLayout(
    sidebarPanel("Sidebar with width = 6", width = 6),
    mainPanel("Main panel with width = 6", width = 6)
  )
)

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

shinyApp(ui = ui, server = server)

Sidebar with width = 6

Main panel with width = 6


titlePanel()

The titlePanel() is used to create a panel containing an application title. Often it makes sense to include this panel outside the sidebarLayout(). But in addition to the title on the page, youmight want to also change the text that shows up on the browser tab for our app, especially if our title is long.

library(shiny)

# Define UI with title panel
ui <- fluidPage(
  titlePanel("My awesome app"),
  sidebarLayout(
    sidebarPanel("Some inputs"),
    mainPanel("Some outputs")
  )
)

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

shinyApp(ui = ui, server = server)

My awesome app

Some inputs

Some outputs


titlePanel() with windowTitle

To customize this text you specify the windowTitle argument in the titlePanel(), which is by default equal to the application title. For example, your application title might be “Movie browser, 1970 to 2014”, but you might just want to make your window title “Movies”.

library(shiny)

# Define UI with title panel and window title
ui <- fluidPage(
  titlePanel("Movie browser, 1970 to 2014",
             windowTitle = "Movies"),
  sidebarLayout(
    sidebarPanel("Some inputs"),
    mainPanel("Some outputs")
  )
)
server <- function(input, output, session) {}

shinyApp(ui = ui, server = server)

Movie browser, 1970 to 2014

Some inputs

Some outputs


conditionalPanel()

The last panel we’ll consider is conditionalPanel(), which creates a panel that is visible conditional upon the value of an input or an output.

First, let’s see it in action in the app below. Switch between any and selected number of digits to see how the sidebar panel changes.



And here is the code that creates the app with the conditional panel.

Under the hood this function evaluates a JavaScript expression once at startup and then whenever Shiny detects a relevant change or input/output.

Being able to display panels conditional on previous user selections is a powerful feature of Shiny.

library(shiny)

# Define UI with conditionalPanel
ui <- fluidPage(
  titlePanel("Random number generator"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        "digit_type", "Number of digits:",
        c("any", "selected")
      ),
      conditionalPanel(
        condition = "input.digit_type == 'selected'",
        sliderInput("digit_count", "How many digits?",
          min = 1, max = 10, value = 4
        )
      ),
      actionButton("go", "Generate new random number"),
      width = 5
    ),
    mainPanel(
      br(),
      "Your random number is",
      h4(textOutput("random_number")),
      width = 7
    )
  )
)

# Define server logic that generates a random number based on user input
server <- function(input, output, session) {
  output$random_number <- renderText({
    input$go
    raw <- runif(1)
    digits <- if (input$digit_type == "any") {
      sample(1:10, size = 1)
    } else {
      input$digit_count
    }
    round(raw * 10^digits)
  })
}

shinyApp(ui = ui, server = server)