How to Make Impressive Shiny Dashboards in Under 10 Minutes with semantic.dashboard
<h2>Introducing semantic.dashboard</h2> <span data-preserver-spaces="true">Dashboards allow you to structure reports intuitively and break them down into easy-to-read chunks. As a result, end-users can navigate and explore data much easier than with traditional reports.</span> <span data-preserver-spaces="true">The <code>shinydashboard</code> R package has been out for ages, and it is a good option with a decent amount of features. However, apps built with it tend to look alike – especially if you're using it daily on multiple projects. A lot of simplistic, aesthetically identical dashboards can leave a bad impression on clients and stakeholders. That's where <code>semantic.dashboard</code> comes into play.</span> <span data-preserver-spaces="true">The <code>semantic.dashboard</code> package is an open-source alternative to <code>shinydashboard</code> created by <a href="https://appsilon.com/shiny/" target="_blank" rel="noopener noreferrer">Appsilon</a>. It allows you to include <a href="http://fomantic-ui.com/" target="_blank" rel="noopener noreferrer">Fomantic UI</a></span><span data-preserver-spaces="true"> components to R Shiny apps without breaking a sweat. </span> For example, let's take a look at two identical applications - the first built with <code>shinydashboard</code>, and the second one with <code>semantic.dashboard</code>: <img class="size-full wp-image-6154" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b02187aa4d870bbd4d3d1c_Screenshot-2020-12-03-at-11.28.12.webp" alt="Dashboard built with shinydashboard" width="1545" height="823" /> Image 1 - Dashboard built with shinydashboard <img class="size-full wp-image-6155" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b02188a89a044c4d36b981_Screenshot-2020-12-03-at-11.28.48.webp" alt="Dashboard built with semantic.dashboard" width="1963" height="1149" /> Image 2 - Dashboard built with semantic.dashboard Both look good - that's guaranteed, but the one built with <code>semantic.dashboard</code> doesn't look as generic. You'll create a somewhat simplified version of this dashboard today. <span data-preserver-spaces="true">You can download the source code of this article <a href="https://appsilon.com/wp-content/uploads/2020/12/semantic-dashboard-code.zip" target="_blank" rel="noopener noreferrer">here</a>.</span> <blockquote><strong>Want to learn more about <code>semantic.dashboard</code>? <a class="editor-rtfLink" href="https://github.com/Appsilon/semantic.dashboard" target="_blank" rel="noopener noreferrer">Visit the official Github page.</a> Feel free to leave us a star!</strong></blockquote> <span data-preserver-spaces="true">Navigate to a section:</span> <ul><li><a href="#first-dashboard">semantic.dashboard Installation and Your First Dashboard</a></li><li><a href="#interactive-dashboard">Build a Fully Interactive Dashboard</a></li><li><a href="#conclusion">Conclusion</a></li></ul> <span data-preserver-spaces="true">To learn more about Appsilon's open-source packages, see our new </span><a class="editor-rtfLink" href="http://shiny.tools/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Open-Source Landing Page:</span></a><span data-preserver-spaces="true"> </span> <a href="http://shiny.tools"><img class="size-large wp-image-5332" src="https://wordpress.appsilon.com/wp-content/uploads/2020/09/Screen-Shot-2020-09-23-at-5.02.14-PM-1024x504.png" alt="Appsilon's shiny.tools landing page for our open source packages." width="1024" height="504" /></a> <em>Appsilon's shiny.tools landing page for our open source packages.</em> <h2 id="first-dashboard"><span data-preserver-spaces="true">Installation and Your First Dashboard</span></h2> <span data-preserver-spaces="true">The <code>semantic.dashboard</code> package is available on CRAN (</span><em><span data-preserver-spaces="true">Comprehensive R Archive Network</span></em><span data-preserver-spaces="true">). To install it, execute the following line from the R console:</span> <pre><code class="language-r">install.packages("semantic.dashboard")</code></pre> <span data-preserver-spaces="true">You can now proceed by creating an empty dashboard:</span> <pre><code class="language-r">library(shiny) library(semantic.dashboard) <br>ui <- dashboardPage( dashboardHeader(), dashboardSidebar(sidebarMenu()), dashboardBody() ) <br>server <- function(input, output) { } <br>shinyApp(ui, server)</code></pre> <span data-preserver-spaces="true">Here's the corresponding output:</span> <img class="size-full wp-image-6096" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b270aafcac124f318a568b_1-1.webp" alt="Empty shiny.semantic dashboard" width="2574" height="954" /> <em>Image 3 - Empty shiny.semantic dashboard</em> <span data-preserver-spaces="true">The <code>semantic.dashboard</code>'s app UI is made of a <code>dashboardPage</code>, which is further split into three elements:</span> <ol><li><strong><span data-preserver-spaces="true">Header</span></strong><span data-preserver-spaces="true"> - <code>dashboardHeader</code></span></li><li><strong><span data-preserver-spaces="true">Sidebar</span></strong><span data-preserver-spaces="true"> - <code>dashboardSidebar</code></span></li><li><strong><span data-preserver-spaces="true">Body</span></strong><span data-preserver-spaces="true"> - <code>dashboardBody</code></span></li></ol> <span data-preserver-spaces="true">This structure is identical as with <code>shinydashboard</code> - making things easier to learn. Let's see how to tweak all of them.</span> <span data-preserver-spaces="true">There are a lot of things you can do with <code>dashboardHeader</code>. For example, you can change the color by specifying a value for the <code>color</code> parameter. You could also include a logo by setting <code>logo_path</code> and <code>logo_allign</code> parameters. If you want to remove the header, specify <code>disabled = TRUE</code>.</span> <span data-preserver-spaces="true">Here's how to change the color from white to something less boring:</span> <pre><code class="language-r">dashboardHeader(color = "blue", inverted = TRUE)</code></pre> <span data-preserver-spaces="true">The <code>inverted</code> parameter sets the color to the header background instead of the header text.</span> <span data-preserver-spaces="true">Here's the corresponding output:</span> <img class="size-full wp-image-6097" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d5eb84d9192ab6b0fffc_7223069e_2.webp" alt="Styling header of the semantic dashboard" width="2138" height="328" /> <em>Image 4 - Styling the header of the semantic dashboard</em> <span data-preserver-spaces="true">Next, let's see how to add elements to the <code>dashboardSidebar</code>. You can specify the sidebar size by tweaking the <code>side</code> parameter (</span><em><span data-preserver-spaces="true">left</span></em><span data-preserver-spaces="true"> by default). You can also tweak the size, which you'll see how in a minute. Finally, you can altogether disable the sidebar by setting <code>disable = TRUE</code>.</span> <span data-preserver-spaces="true">Here's how to make the sidebar wider:</span> <pre><code class="language-r">dashboardSidebar( size = "wide", sidebarMenu( menuItem(tabName = "panel1", text = "Panel 1"), menuItem(tabName = "panel2", text = "Panel 2") ) )</code></pre> <span data-preserver-spaces="true">Here are the results:</span> <img class="size-full wp-image-6098" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d5ebbe40ac3284ae1ccd_163a2dc8_3.webp" alt="Styling sidebar of the semantic dashboard" width="2138" height="490" /> <em>Image 5 - Styling the sidebar of the semantic dashboard</em> <span data-preserver-spaces="true">That adds the elements to the sidebar, but how can you display different content when the tab is clicked? That's where tweaks to <code>dashboardBody</code> come into play.</span> <span data-preserver-spaces="true">Let's add <code>tabItems</code> and two tabs, corresponding to two options in the sidebar. The first option is selected by default, as specified with the <code>selected</code> parameter. Only a single text box should be visible on both panels, indicating which panel you're currently on. Here's the code snippet:</span> <pre><code class="language-r">dashboardBody( tabItems( selected = 1, tabItem( tabName = "panel1", textOutput(outputId = "text1") ), tabItem( tabName = "panel2", textOutput(outputId = "text2") ) ) )</code></pre> <span data-preserver-spaces="true">To make this work, you'll need to make some tweaks to the <code>server</code> function. You'll have to render text on the corresponding outputs. Here's how:</span> <pre><code class="language-r">server <- function(input, output) { output$text1 <- renderText("This is Panel 1") output$text2 <- renderText("This is Panel 2") }</code></pre> <span data-preserver-spaces="true">Your dashboard should look like this now:</span> <img class="size-full wp-image-6099" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d5ec98512f0e5204eb23_a417543d_4.gif" alt="Initial dashboard with two panels" width="1060" height="248" /> <em>Image 6 - Initial dashboard with two panels</em> <span data-preserver-spaces="true">Now you know the basics of <code>semantic.dashboard</code>. Let's see how to take it a step further and display an interactive data-driven map.</span> <h2 id="interactive-dashboard"><span data-preserver-spaces="true">Build a Fully Interactive Dashboard</span></h2> <span data-preserver-spaces="true">R comes with a lot of built-in datasets, <code>quakes</code> being one of them. It shows geolocations of 1000 seismic events that occurred near Fiji since 1964. Here's what the first couple of rows look like:</span> <img class="size-full wp-image-6100" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b270aca29bdbc93bbf4cb6_5-1.webp" alt="First couple of rows of the Quakes dataset" width="722" height="364" /> <em>Image 7 - First couple of rows of the Quakes dataset</em> <span data-preserver-spaces="true">You'll now see how to develop a semantic dashboard with the following tabs:</span> <ul><li><strong><span data-preserver-spaces="true">Interactive map</span></strong><span data-preserver-spaces="true"> - display geographical area near Fiji with markers representing the magnitude of the seismic event</span></li><li><strong><span data-preserver-spaces="true">Table</span></strong><span data-preserver-spaces="true"> - shows the source dataset formatted as a table</span></li></ul> <span data-preserver-spaces="true">You'll create the interactive map with the <code>leaflet</code> package, so make sure to have it installed:</span> <pre><code class="language-r">install.packages("leaflet")</code></pre> <span data-preserver-spaces="true">The UI follows the pattern discussed in the previous section - there's a header, sidebar, and a body. The header will be empty this time. Most of the differences are in the <code>dashboardBody</code>. The structure should look familiar, but there are two new functions:</span> <ul><li><span data-preserver-spaces="true"><code>leafletOutput()</code> - used to display the interactive map </span></li><li><span data-preserver-spaces="true"><code>dataTableOutput()</code> - used to display the data table </span></li></ul> <span data-preserver-spaces="true">To make the map as large as possible, you can set some inline CSS styles. In the code below, the height is modified, so the map always takes almost the entire screen height (- 80 pixels as a margin).</span> <span data-preserver-spaces="true">Here's the code for the UI:</span> <pre><code class="language-r">library(shiny) library(shiny.semantic) library(shinydashboard) library(leaflet) <br>ui <- dashboardPage( dashboardHeader(), dashboardSidebar( size = "wide", sidebarMenu( menuItem(tabName = "map", text = "Map", icon = icon("map")), menuItem(tabName = "table", text = "Table", icon = icon("table")) ) ), dashboardBody( tabItems( selected = 1, tabItem( tabName = "map", tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"), leafletOutput("map") ), tabItem( tabName = "table", fluidRow( h1("Quakes Table"), semantic_DTOutput("quakesTable") ) ) ) ) )</code></pre> <span data-preserver-spaces="true">In order to make this dashboard work, you'll have to modify the <code>server</code> function. Inside it lies the code for rendering both the map and the table. The coordinates for the map were chosen arbitrarily, after a quick Google search. </span> <span data-preserver-spaces="true">The magnitude of the seismic activity determines the size of a marker. Every marker is clickable - showing the magnitude, depth in kilometers, and the number of stations that reported the seismic activity.</span> <span data-preserver-spaces="true">Here's the code for the server:</span> <pre><code class="language-r">server <- function(input, output) { output$map <- renderLeaflet({ leaflet() %>% setView(lng = 179.3355929, lat = -20.4428959, zoom = 6.5) %>% addProviderTiles("Esri.WorldStreetMap") %>% addCircles( data = quakes, radius = sqrt(10^quakes$mag) * 30, color = "#000000", fillColor = "#ffffff", fillOpacity = 0.5, popup = paste0( "<strong>Magnitude: </strong>", quakes$mag, " ", "<strong>Depth (km): </strong>", quakes$depth, " ", "<strong>Num. stations reporting: </strong>", quakes$stations ) ) }) output$quakesTable <- DT::renderDataTable( semantic_DT(quakes) ) }</code></pre> <span data-preserver-spaces="true">And here's the final dashboard:</span> <img class="wp-image-6150 size-full" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b0218f6cd8f7584c83592a_6_fixed.gif" alt="Final Quakes dashboard" width="1658" height="818" /> Image 8 - Final Quakes dashboard <h2 id="conclusion"><span data-preserver-spaces="true">Conclusion</span></h2> <span data-preserver-spaces="true">In this short hands-on guide, you've learned how to develop simple and aesthetically-pleasing Shiny dashboards. You've learned what <code>semantic.dashboard</code> is, what it brings to the table, and how to pair it with other libraries to produce stunning and intuitive dashboards. </span><span data-preserver-spaces="true">You can learn more about <code>semantic.dashboard</code> by visiting the links below.</span> <blockquote><span data-preserver-spaces="true">Looking for inspiration? </span><a class="editor-rtfLink" href="https://appsilon.github.io/shiny.semantic/index.html" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Check out component demos and complete dashboards here.</span></a></blockquote> <ul><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/create-outstanding-dashboards-with-the-new-semantic-dashboard-package/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Create outstanding R Shiny dashboards with the semantic.dashboard package</span></a></li><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/video-tutorial-create-and-customize-a-simple-shiny-dashboard/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Video Tutorial: Create and Customize a Simple Shiny Dashboard</span></a></li><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/shiny-dashboard-ui-crash-course/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Why is My Dashboard Ugly? A Crash Course in R Shiny UI</span></a></li><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/r-shiny-faster-updateinput-css-javascript/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Make R Shiny Dashboards Faster with updateInput, CSS, and JavaScript</span></a></li><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/how-to-scale-a-shiny-dashboard/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Video Tutorial: How to Scale Shiny Dashboards</span></a></li></ul> <a href="https://appsilon.com/careers/"><img class="aligncenter wp-image-5940 size-medium" src="https://wordpress.appsilon.com/wp-content/uploads/2020/11/appsilon.hiring0-600x338.jpg" alt="" width="600" height="338" /></a> <p style="text-align: center;"><strong><span data-preserver-spaces="true">Appsilon is hiring globally! We are primarily seeking an Engineering Manager who can lead a team of 6-8 ambitious software engineers. See our </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/careers/" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Careers</span></strong></a><strong><span data-preserver-spaces="true"> page for all new openings, including openings for a </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/careers/#project-manager" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Project Manager</span></strong></a><strong><span data-preserver-spaces="true"> and </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/careers/#community-manager" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Community Manager</span></strong></a><strong><span data-preserver-spaces="true">.</span></strong></p>