# Build your first dynamic shiny.semantic app using layout and grid

## Appsilon

### 2024-04-05

## Create UI inside documents

This is how you generate your first UI with `shiny.semantic`:

    uirender(
      shiny::tagList(
        h4("Numeric input", icon("world")),
        shiny.semantic::numeric_input("input", value = 0, label = ""),
        shiny.semantic::list_container(list(
            list(header = "Item 1", description = "My text for item 1", icon = "cat"),
            list(header = "Item 2", description = "My text for item 2", icon = "tree"),
            list(header = "Item 3", description = "My text for item 3", icon = "dog")
          ), is_divided = TRUE
        )
      ),
    width = "200px", height = "280px")

plot of chunk unnamed-chunk-1

## Create a simple Shiny App

Let’s create a Shiny app with `semanticPage()` and just an `h1` title.

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

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

    shinyApp(ui, server)

### Built-in layouts

Now let’s add 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 ⅔ of the horizontal width and typically contains outputs.

    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 Fomantic (Semantic previously) UI segment containing 2 cards.

    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()`.

    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.

    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: `splitLayout`, `flow_layout`, `vertical_layout` and some 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:

    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.