Join the R Community at ShinyConf 2023

shiny.semantic 0.4.0 Update Brings CSS Grid UI Functionality to Shiny Apps


Updated: January 24, 2023.

shiny.semantic is an R package created by Appsilon that brings the Fomantic UI library to Shiny apps. With shiny.semantic, you can rapidly create great-looking Shiny apps with non-standard UI components.

Do your dashboards look dull? Here are 7 UX tips for designing dashboards people will love.

We have just released version 0.4.0, which includes standardized syntax, a useful grid functionality for easily positioning UI elements, and multiple quality-of-life improvements. With a grid, you can create a single layout that works on mobile, tablet, and computer. shiny.semantic is available on CRAN. To learn more about Appsilon’s open-source packages, visit our new shiny.tools landing page:

Image 1 – Shiny Tools homepage

shiny.semantic: Version 0.4.0 Update

If you don’t have the package already installed, just run the following command through the R console.

install.package("shiny.semantic")

The shiny.semantic package was released in 2016 and was quickly adopted by the R community as an alternative to Bootstrap UI. At the beginning of 2020, Appsilon decided to migrate the engine of shiny.semantic (all CSS and JS libraries) to the more actively supported FomanticUI project, but we left the name of the package unchanged for legacy purposes.

Today, we are happy to share with you that shiny.semantic has reached version 0.4.0. In the latest edition, we have introduced a couple of breaking changes. First of all, we have standardized the syntax. You can find more information about the new syntax in our style guide. Briefly, now we use camelCase for all the functions that have equivalence in the regular Shiny syntax, but we stick to snake_case for custom shiny.semantic functions.

For example, you can still call the stock Shiny actionButton in a similar way as in standard Shiny, but as an alternative, you may also use action_button, which has even more customization options specific to FomanticUI.

Grid Functionality

Another big change is the introduction of powerful functionality that we are calling “grid.” With a grid, you can easily position the elements of your UI on the page. You start by defining the template of your grid. Let’s call it here my_layout. (You may also style particular grid container elements using parameter areas_style straight from R.)

library(shiny)
library(shiny.semantic)

my_layout <- grid_template(default = list(
  areas = rbind(
    c("top_left", "top_right"),
    c("bottom", "bottom")
  )
))

display_grid(my_layout)

Image 2 – CSS grid layout

And in the Shiny UI pass the template together with the definition of elements of UI in a specific place. For example:

library(shiny)
library(shiny.semantic)

my_layout <- grid_template(default = list(
  areas = rbind(
    c("top_left", "top_right"),
    c("bottom", "bottom")
  )
))

ui <- semanticPage(
  grid(
    grid_template = my_layout,
    top_left = segment(h1("Top left")),
    top_right = segment(h1("Top right")),
    bottom = segment(h1("Bottom"))
  )
)

server <- function(input, output) {
  
}

shinyApp(ui = ui, server = server)

 

Image 3 – CSS Grid in shiny.semantic

Semantic Grid for Mobile Devices (Responsive)

The semantic grid is also responsive, since you can easily tweak the stylings for screens narrower than 768 pixels. Here’s an example:

library(shiny)
library(shiny.semantic)

# Here we define the grid_template that we will pass to our grid
myGrid <- grid_template(
  default = list(
    # Here we define the data.frame describing our layout
    # The easiest way is to use rbind so that the layout can be 'visualized' in code
    areas = rbind(
      c("header", "header", "header"),
      c("menu", "main", "right1"),
      c("menu", "main", "right2")
    ),
    # Then we define the dimensions of the different elements of the layout
    # We can use any valid css units to make the layout behave exactly as desired
    rows_height = c("50px", "auto", "100px"),
    cols_width = c("100px", "2fr", "1fr")
  ),
  # This is optional, but we can define a specific layout for mobile (screen width below 768px)
  mobile = list(
    areas = rbind(
      c("header", "header", "header"),
      c("menu", "main", "right1"),
      c("menu", "main", "right2")
    ),
    rows_height = c("50px", "2fr", "1fr"), # Notice how we changed the rows heights here
    cols_width = c("100px", "2fr", "1fr")
  )
)

# We can use nested grids to precisely control the layout of all the elements
# Here we define another grid_template to use in one of the elements of the parent grid
subGrid <- grid_template(
  default = list(
    areas = rbind(
      c("top_left", "top_right"),
      c("bottom_left", "bottom_right")
    ),
    rows_height = c("50%", "50%"),
    cols_width = c("50%", "50%")
  ),
  # This is optional, but we can define a specific layout for mobile (screen width below 768px)
  mobile = list(
    areas = rbind(
      c("top_left"),
      c("top_right"),
      c("bottom_left"),
      c("bottom_right")
    ),
    rows_height = c("25%", "25%", "25%", "25%"),
    cols_width = c("100%")
  )
)

ui <- semanticPage(
  grid(myGrid,
    # We can define the css style of the grid using container_style
    container_style = "border: 5px solid #3d7ea6",
    # We can define the css style of each of the grid elements using area_styles
    area_styles = list(
      header = "border: 3px solid #5c969e",
      menu = "border: 3px solid #5c969e",
      main = "border: 3px solid #5c969e",
      right1 = "border: 3px solid #5c969e",
      right2 = "border: 3px solid #5c969e"
    ),
    # Finally, we define the ui content we would like to have inside each element
    header = div(shiny::tags$h1("Hello CSS Grid!")),
    menu = div("menu"),
    main = grid(subGrid,
      area_styles = list(
        top_left = "border: 3px solid #ffa5a5;",
        top_right = "border: 3px solid #ffa5a5;",
        bottom_left = "border: 3px solid #ffa5a5;",
        bottom_right = "border: 3px solid #ffa5a5;"
      ),
      top_left = div("main top left"),
      top_right = div("main top right"),
      bottom_left = div("main bottom left"),
      bottom_right = div("main bottom right")
    ),
    right1 = div("right 1"),
    right2 = div("right 2")
  )
)

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

shinyApp(ui = ui, server = server)

Image 4 – Shiny semantic responsive grid

More on Shiny Semantic Grid

You don’t need to build your own layouts from scratch! We’ve implemented (with grid) some of the most popular layouts that you may know from Shiny: horizontal layout, vertical layout, and sidebar layout that you can see below:

Image 5 – Popular Shiny app layouts

The shiny.semantic documentation is now rendered with an extremely useful pkgdown package: http://appsilon.github.io/shiny.semantic. With very little work, the documentation got a nice fresh look with a number of examples for almost every function. I could tell you about all of the new components that we introduced: counter button, toasts, progress bar, etc. – but it’s better that you visit our new documentation website to explore them all on your own. Furthermore, we’ve added a few short tutorials that will help you to dive into the details of shiny.semantic development. If you are interested in all the details of the latest changes, please refer to our changelog.

You can see the effects of shiny.semantic transforming the look of a Shiny dashboard from our work on the Utah Division of Water Quality app: before and after

Image 6 – Utah division of water app before and after Semantic Grid

You may get or update the new shiny.semantic from CRAN. If you encounter any problems, please report bugs on our GitHub or contact us directly: dev@wordpress.appsilon.com. Remember that shiny.semantic is fully open-source, so we always welcome new contributors. Feel free to reach out and learn how you can contribute to the development of shiny.semantic.

If you like the new version of the package, please leave us a star on GitHub: https://github.com/Appsilon/shiny.semantic. We always love receiving feedback on our work. Happy coding!

Looking for a shiny.semantic cheatsheet? Look no more – here’s the only one you’ll need.


Learn More