
If your goal is to build elegant, professional dashboards, you should be using shiny.fluent. In this Shiny tutorial, we’ll cover how you can make the most of your UI and give your application a chance for success.
Shiny UI tutorial using shiny.fluent
With Appsilon’s public launch of two R packages – shiny.fluent and shiny.react, the accessibility of React libraries to the Shiny dev community is now easier than ever. shiny.react opens up the rich React ecosystem (e.g., frameworks, blueprints, and components for charts and maps) to R developers, creating the opportunity to improve development speed, app functionality, and design. The ability to port entire React UI libraries is now possible through shiny.react.
For professional, elegant designs consistent with enterprise-grade applications shiny.fluent joins the efficiency of Microsoft’s Fluent UI and R’s advanced data handling capabilities. With a significant set of components allowing for unique functions like the ‘People Picker‘, ‘Teaching Bubble‘, and ‘Hover Card‘, and support for powerful functions like Stack(), users can be flexible with component placements in the dashboard. Through shiny.react, shiny.fluent makes it possible for the R community to access the power of React JavaScript library and Microsoft’s Fluent UI.
- Welcome to shiny.fluent
- Getting started
- Creating shiny.fluent dashboards
- Single Page Layout
- Dashboard Layout
- Filling All the Areas
- Additional Pages
- Conclusion
Read More: Why You Should Use Shiny for Enterprise Application Development
Welcome to shiny.fluent
Shiny.fluent ports Fluent UI to R using shiny.react machinery, giving powerful, professional, and user-friendly interfaces to the Shiny community. In this tutorial, we will walk you through how to create a dashboard for a Fluent UI app to improve upon a simple sales analysis application. If you haven’t already, we recommend you start your shiny.fluent adventure here to familiarize yourself with using Fluent components – the tutorial below will build on what you learn there.
Getting started with the Shiny tutorial
Shiny.react was created with ease of use in mind for R developers. Inputs are as close as possible to the Shiny API and the react package(s) documentation is provided inside the R documentation system. To begin use of shiny.fluent we will install the shiny.react and shiny.fluent packages.
Installation
To install the packages, run:
remotes::install_github("Appsilon/shiny.react") remotes::install_github("Appsilon/shiny.fluent")
Prerequisites
With shiny.react and shiny.fluent packages installed, let’s load the libraries needed for this example.
library(dplyr) library(ggplot2) library(glue) library(leaflet) library(plotly) library(sass) library(shiny) library(shiny.fluent) library(shiny.router)
Creating a shiny.fluent dashboard
In this tutorial, we will walk through how to build a dashboard UI.
Single Page Layout
As a next step, let’s add a title and subtitle to our current app. We’ll create a helper function and call it makePage, so that it is easy to add more pages in the same fashion.
makePage <- function (title, subtitle, contents) { tagList(div( class = "page-title", span(title, class = "ms-fontSize-32 ms-fontWeight-semibold", style = "color: #323130"), span(subtitle, class = "ms-fontSize-14 ms-fontWeight-regular", style = "color: #605E5C; margin: 14px;") ), contents) }
We can now take our entire UI built so far and put it in a “page” layout, giving it a helpful title and subtitle.
analysis_page <- makePage( "Sales representatives", "Best performing reps", div( Stack( horizontal = TRUE, tokens = list(childrenGap = 10), makeCard("Filters", filters, size = 4, style = "max-height: 320px"), makeCard("Deals count", plotlyOutput("plot"), size = 8, style = "max-height: 320px") ), uiOutput("analysis") ) ) ui <- fluentPage( tags$style(".card { padding: 28px; margin-bottom: 28px; }"), analysis_page )
Dashboard Layout
It’s time to create a place for our header, navigation sidebar, and footer. We’ll use CSS grid for that. It’s a modern, flexible and straightforward way to achieve such a layout.
We start by creating divs for each of the areas, with placeholder texts that we will later replace.
header <- "header" navigation <- "navigation" footer <- "footer" layout <- function(mainUI){ div(class = "grid-container", div(class = "header", header), div(class = "sidenav", navigation), div(class = "main", mainUI), div(class = "footer", footer) ) }
Now it’s time to tell the browser using CSS how to arrange these areas. To define how our areas should be laid out on the page, let’s put the following rules in www/style.css:
.grid-container { display: grid; grid-template-columns: 320px 1fr; grid-template-rows: 54px 1fr 45px; grid-template-areas: "header header" "sidenav main" "footer footer"; height: 100vh; } .header { grid-area: header; background-color: #fff; padding: 6px 0px 6px 10px; display: flex; } .main { grid-area: main; background-color: #faf9f8; padding-left: 40px; padding-right: 32px; max-width: calc(100vw - 400px); max-height: calc(100vh - 100px); overflow: auto; } .footer { grid-area: footer; background-color: #f3f2f1; padding: 12px 20px; } .sidenav { grid-area: sidenav; background-color: #fff; padding: 25px; }
We can also use this opportunity to add some additional styling for the entire page, and add the following rules to the same file:
body { background-color: rgba(225, 223, 221, 0.2); min-height: 611px; margin: 0; } .page-title { padding: 52px 0px; } .card { background: #fff; padding: 28px; margin-bottom: 28px; border-radius: 2px; background-clip: padding-box; }
Now we only need to update our UI definition to load styles from www/style.css and use the new layout.
ui <- fluentPage( layout(analysis_page), tags$head( tags$link(href = "style.css", rel = "stylesheet", type = "text/css") ))
Filling All the Areas
Moving forward, we may now begin adding a Header, Footer, and Sidebar to the empty areas of our dashboard.
Header
Let’s replace the previous header definition with:
header <- tagList( img(src = "appsilon-logo.png", class = "logo"), div(Text(variant = "xLarge", "Sales Reps Analysis"), class = "title"), CommandBar( items = list( CommandBarItem("New", "Add", subitems = list( CommandBarItem("Email message", "Mail", key = "emailMessage", href = "mailto:me@example.com"), CommandBarItem("Calendar event", "Calendar", key = "calendarEvent") )), CommandBarItem("Upload sales plan", "Upload"), CommandBarItem("Share analysis", "Share"), CommandBarItem("Download report", "Download") ), farItems = list( CommandBarItem("Grid view", "Tiles", iconOnly = TRUE), CommandBarItem("Info", "Info", iconOnly = TRUE) ), style = list(width = "100%")))
As you can see, we’re using CommandBar and CommandBarItem from shiny.fluent. We also need to add a bit of styling to our CSS file:
.title { padding: 0px 14px 0px 14px; color: #737373; margin: 6px 0px 6px 10px; border-left: 1px solid darkgray; width: 220px; } .logo { height: 44px; }
Navigation in the Sidebar
Nav is a very powerful component from Fluent UI. It has very rich configuration options, but we will use it to show just a couple of links:
navigation <- Nav( groups = list( list(links = list( list(name = 'Home', url = '#!/', key = 'home', icon = 'Home'), list(name = 'Analysis', url = '#!/other', key = 'analysis', icon = 'AnalyticsReport'), list(name = 'shiny.fluent', url = 'http://github.com/Appsilon/shiny.fluent', key = 'repo', icon = 'GitGraph'), list(name = 'shiny.react', url = 'http://github.com/Appsilon/shiny.react', key = 'shinyreact', icon = 'GitGraph'), list(name = 'Appsilon', url = 'http://appsilon.com', key = 'appsilon', icon = 'WebAppBuilderFragment') )) ), initialSelectedKey = 'home', styles = list( root = list( height = '100%', boxSizing = 'border-box', overflowY = 'auto' ) ) )
Footer
Footer is relatively straightforward – we can put anything we want there. Here we use Text for typography (setting uniform font styling). We also use Stack to arrange elements horizontally and with bigger gaps.
footer <- Stack( horizontal = TRUE, horizontalAlign = 'space-between', tokens = list(childrenGap = 20), Text(variant = "medium", "Built with ❤ by Appsilon", block=TRUE), Text(variant = "medium", nowrap = FALSE, "If you'd like to learn more, reach out to us at hello@appsilon.com"), Text(variant = "medium", nowrap = FALSE, "All rights reserved.") ) layout <- function(mainUI){ div(class = "grid-container", div(class = "header", header), div(class = "sidenav", navigation), div(class = "main", mainUI), div(class = "footer", footer) ) } # --- ui <- fluentPage( layout(analysis_page), tags$head( tags$link(href = "style.css", rel = "stylesheet", type = "text/css") ))
Let’s see how this looks together.
Additional Pages
The final step is to add pages and enable navigation between them.
Home Page
Let’s make a home page, consisting of two cards with some welcome text.
card1 <- makeCard( "Welcome to shiny.fluent demo!", div( Text("shiny.fluent is a package that allows you to build Shiny apps using Microsoft's Fluent UI."), Text("Use the menu on the left to explore live demos of all available components.") )) card2 <- makeCard( "shiny.react makes it easy to use React libraries in Shiny apps.", div( Text("To make a React library convenient to use from Shiny, we need to write an R package that wraps it - for example, a shiny.fluent package for Microsoft's Fluent UI, or shiny.blueprint for Palantir's Blueprint.js."), Text("Communication and other issues in integrating Shiny and React are solved and standardized in shiny.react package."), Text("shiny.react strives to do as much as possible automatically, but there's no free lunch here, so in all cases except trivial ones you'll need to do some amount of manual work. The more work you put into a wrapper package, the less work your users will have to do while using it.") )) home_page <- makePage( "This is a Fluent UI app built in Shiny", "shiny.react + Fluent UI = shiny.fluent", div(card1, card2) )
If we replace analysis_page with home_page in our UI, we can see this page. However, there’s one problem: we don’t have a way to switch between pages! This is where so-called page routing comes into play.
Adding shiny.router
To enable switching between pages we will use the shiny.router package. This way we will also have shareable URLs to individual pages.
The first step is to define the available routes:
router <- make_router( route("/", home_page), route("other", analysis_page))
Now, we need to put router$ui in the place where we want the selected page to appear. (Currently, we also need to manually include router’s JavaScript dependencies, because shiny.fluent is not compatible with the way shiny.router loads this dependency. We expect this to be resolved in future versions of shiny.router).
# Add shiny.router dependencies manually: they are not picked up because they're added in a non-standard way. shiny::addResourcePath("shiny.router", system.file("www", package = "shiny.router")) shiny_router_js_src <- file.path("shiny.router", "shiny.router.js") shiny_router_script_tag <- shiny::tags$script(type = "text/javascript", src = shiny_router_js_src) ui <- fluentPage( layout(router$ui), tags$head( tags$link(href = "style.css", rel = "stylesheet", type = "text/css"), shiny_router_script_tag ))
One final step is to add this single line to our server function, which otherwise remains untouched from the Part 1 of the Shiny tutorial.
router$server(input, output, session)
That’s it!
And there you go! We now have styled a shiny.fluent app into a solid dashboard layout. Here’s the final result:
Summing up our Shiny tutorial with shiny.fluent
The speed at which you can now add user-friendly and ubiquitous Microsoft product elements to your project is quite impressive. In a matter of minutes, we were able to create a functional, professional-looking Shiny dashboard with shiny.fluent. And if your users are already familiar with Microsoft products, adoption can be seamless.
There is more complexity over something like shiny.semantic. However, an intermediate level of knowledge of Shiny is sufficient to begin. Component examples are provided and more comprehensive documentation can be found in the official Fluent UI docs or by typing shiny.fluent:: (e.g., ‘?shiny.fluent::MyComponentName’).
Please feel free to post any comments regarding shiny.fluent on our feedback thread. We love to hear feedback from our users and are happy to help should you have questions. If you like the package and want to show your support, please consider dropping a star on the shiny.fluent package at our Github and browse our other shiny packages.
Appsilon is hiring for remote roles! See our Careers page for all open positions, including a React Developer and R Shiny Developers. Join Appsilon and work on groundbreaking projects with the world’s most influential Fortune 500 companies.