Create BEAUTIFUL value boxes using R
How to fully customize value boxes using bslib and bs4Dash in Shiny and Quarto
Coders,
I just published a new YouTube tutorial showing how to create and fully customize beautiful values boxes using the bslib and bs4Dash R packages. I also show how to include customized interactive graphics in the value boxes using the plotly R package.
In the video you will learn how to:
Explore value boxes parameters using the “Build a Box” demo app.
Customize bslib value boxes with the bslib R package.
Integrate customize interactive graphics in your value boxes.
Use values boxes in your shiny apps.
Create and customize value boxes using the bs4Dash R package.
Watch the video now:
Getting Started with the bslib demo app
Let’s get started directly with this bslib “Build a box” demo application which you can access at: https://bslib.shinyapps.io/build-a-box/
As you can see in the value box settings, you can change the inputs and whatever you write for example numbers and the value box will automatically update. When it’s done, you can click on show code and you can simply download the code.
Key Features You Can Customize:
Title and Value: You can change the title, the value, you can easily add extra text in the markdown also if you want. And as you can see it will be showed in the value box.
Theme Colors: You can change the theme. This is bootstrap color. So primary color is blue. But if you go on success for example, it will be green because this is a default color for success in bootstrap. If you want to use your own custom colors, you can do it also by clicking on this changing the URL of the colors and you will get the colors that you want.
Full Screen Mode: You can also allow full screen. This is quite a nice features of the cards of bslib which is using the background of the value box function. You can click on this button to click on expand and you get extra information about the x-axis which you don’t see in a smaller value box. So this is pretty nice.
Showcase Options: Also, the third section is related to the showcase. You can have a very simple value box like this. But if you want to add an interactive plot or an icon, you can do it very easily. So you can first choose where to put this showcase:
At the bottom
As the left center (which is default)
At the top right
Let’s put it back in the left center for example. You decided to have a plot. We can have a line, a bar, or possibly a box. We will see how you can also fully customize this interactive graphics a bit later on. You can also change the colors. You can fully customize them if you want.
You can also instead of a plot use an icon and you have the list of different icons you can use and you can choose the one you want.
Required R Packages
First, let’s load the necessary libraries/R packages we will use:
library(bslib)
library(plotly)
library(htmltools)
library(bsicons)
library(shiny)
library(bs4Dash)
library(htmlwidgets)Creating Value Boxes with bslib
Let’s copy paste the example code that we just created using the demo app. If we run this line of code, you will see in the viewer the cards appearing:
layout_columns(
value_box(
title = "Package Numbers", value = "409,446", shiny::markdown("asdfsd"),
theme = "primary", showcase = "Your Plot", showcase_layout = "left center",
full_screen = TRUE, fill = TRUE, height = NULL
),
value_box(
title = "AWS Cloud Spending", value = "$3,463", , theme = "success",
showcase = "Your Plot", showcase_layout = "left center",
full_screen = TRUE, fill = TRUE, height = NULL
),
value_box(
title = "Project Stars", value = "5,100", , theme = NULL,
showcase = bsicons::bs_icon("star"), showcase_layout = "left center",
full_screen = FALSE, fill = TRUE, height = NULL
)
)Key Function:
layout_columnsis a bslib function to create the layout by column as the function says.
Understanding the Parameters:
You can simply call the value box function with:
Title — the main heading • Value — the key metric or number
Extra content — markdown or HTML code to fully customize the content
Theme — color scheme (primary, success, etc.)
Showcase — where we put the code for plots or icons
Full screen — set to
TRUEto enable expansion,FALSEto disableFill and height — layout customization options
We can change the theme from primary (blue) to success (green). The showcase is where we will have to put the code for the plot, and if you want the full screen, you put it true. If you want to remove it false. We want to fill and you can also customize the height of your card.
Creating Interactive Graphics (Spark Lines)
As mentioned previously, we want to create the interactive graphics now. The documentation is at: https://rstudio.github.io/bslib/articles/value-boxes/
As you can see on the official bslib package documentation regarding value boxes, you have all the information to create the value boxes including using shiny and this layout column to wrap it differently using bslib.
If you go to expandable spark lines, which are actually the name for this mini interactive plots, you have the code to create this spark line object which is called in the showcase to create this.
Actually, what I did is simply copy paste the code, and this is the code. Let’s go quickly through it so you know also how you can customize your interactive spark line:
sparkline <- plot_ly(economics) %>%
add_lines(
x = ~date, y = ~psavert,
color = I("white"), span = I(1),
fill = 'tozeroy', alpha = 0.2
) %>%
layout(
xaxis = list(visible = F, showgrid = F, title = ""),
yaxis = list(visible = F, showgrid = F, title = ""),
hovermode = "x",
margin = list(t = 0, r = 0, l = 0, b = 0),
font = list(color = "white"),
paper_bgcolor = "transparent",
plot_bgcolor = "transparent"
) %>%
config(displayModeBar = FALSE) %>%
htmlwidgets::onRender(
"function(el) {
el.closest('.bslib-value-box')
.addEventListener('bslib.card', function(ev) {
Plotly.relayout(el, {'xaxis.visible': ev.detail.fullScreen});
})
}"
)Understanding the Spark Line Code:
Data Source: This is using plotly with the economics data set which is automatically loaded when you load the plotly package.
Color Customization: If you run this first chunk of code, you will see in the viewer your plotly code, but you don’t see the line because we specify we wanted it white. But if you want to have it in a different color and you run again this chunk of code, as you can see now it’s in blue.
Layout Cleanup: We also want to remove the grid and some information about the axis. So we use a layout argument. Now you don’t see anything because everything is either transparent or white. But this is what we want. We want also to remove this mode bar so you can call it the display mode bar inside the config function as false and this mode bar will disappear.
Quarto Integration: Finally, and this is only specifically if you want to use spark line in your Quarto document reports, you can use this on render function with this javascript code. As explained in the documentation page, this JavaScript is actually equivalent to say show the x-axis on the chart when it’s taller than 200 pixels, otherwise hide it. There was a little bug when you display it with this x-axis and this is the code to fix this. We will see also how to do the equivalent with shiny.
Creating a Complete Value Box with Spark Line:
We will run this chunk of code to have our spark line object and we will again use value box with a different example with customized code to put extra lines if it’s useful for you:
value_box(
title = "Personal Savings Rate",
value = "7.6%",
p("Started at 12.6%"),
p("Averaged 8.6% over that period"),
p("Peaked 17.3% in May 1975"),
showcase = sparkline,
showcase_layout = "bottom",
full_screen = TRUE,
theme = "success"
)As you can see in the showcase we have our spark line object we just created and we have it at the bottom.
Creating Value Boxes with Shiny
Let’s see how to do it also with shiny. I’ll take again an example from the official documentation of bslib:
ui <- page_fluid(
theme = bslib::bs_theme(
base_font = font_google("Atkinson Hyperlegible")
),
br(),
layout_column_wrap(
width = "200px",
class = "mt-3",
value_box(
title = "Unemployment Rate",
value = "2.7%",
p("Started at 1.5%"),
p("Averaging 3%"),
p("Peaked at 5.2% in Dec 1982"),
showcase = plotlyOutput("unemploy"),
full_screen = TRUE
),
value_box(
title = "Personal Savings Rate",
value = "7.6%",
p("Started at 12.6%"),
p("Averaging 8.6%"),
p("Peaked at 17.3% in May 1975"),
showcase = plotlyOutput("psavert"),
showcase_layout = showcase_top_right(),
full_screen = TRUE,
theme = "success"
),
value_box(
title = "Personal Consumption",
value = "$3.8B",
p("Started at $0.25B"),
p("Averaging $1.7B"),
showcase = bsicons::bs_icon("piggy-bank", size = "100%"),
full_screen = TRUE,
theme = "danger"
)
)
)UI Structure
We will create a page fluid which is a function from bslib. You can customize it and as again this layout column wrap with some classes and the width and we will add the three value boxes as examples.
Important: As you can see in the showcase line, instead of calling our spark line object, we will call plotlyOutput with an id which is actually calling the spark line object in the server side.
Server Logic
This is the server code from the documentation:
server <- function(input, output) {
output$unemploy <- renderPlotly({
plotly_time_series(
economics,
x = ~date,
y = ~ 100 * unemploy / pop
)
})
output$psavert <- renderPlotly({
plotly_time_series(
economics,
x = ~date,
y = ~psavert
)
})
output$pce <- renderPlotly({
plotly_time_series(
economics,
x = ~date,
y = ~ 100 * pce / pop
)
})
plotly_time_series <- function(d, x, y) {
info <- getCurrentOutputInfo()
large <- isTRUE(info$height() > 200)
plot_ly(d, x = x, y = y) %>%
add_lines(
color = I(info$fg()),
span = I(1),
#hoverinfo = if (!large) "none",
fill = 'tozeroy',
alpha = 0.2
) %>%
layout(
hovermode = "x",
margin = list(t = 0, r = 0, l = 0, b = 0),
font = list(color = info$fg()),
paper_bgcolor = "transparent",
plot_bgcolor = "transparent",
xaxis = list(
title = "",
visible = large,
showgrid = FALSE
),
yaxis = list(
title = "",
visible = large,
showgrid = FALSE
)
) %>%
config(displayModeBar = FALSE)
}
}
shinyApp(ui, server)Again for each spark line we have a different render plotly calling the plotly time series function which is actually a function created which creates a plotly object.
Let’s run this chunk of code so you have an idea about what it does. This is the shiny application running. And as expected we have our interactive spark lines with the different information we wanted. And the beauty of shiny is like every time the data updates in the server, new value boxes would be updated accordingly.
Creating Value Boxes with bs4Dash
Right now I want to show you also how to create value boxes. This time with the bs4Dash R package.
bs4Dash has different functions to build your packages. It starts with a dashboard page function and then you can call the functions for the different argument to build the header, the sidebar, control bar, footer, the title and the body:
ui <- dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(),
controlbar = dashboardControlbar(),
footer = dashboardFooter(),
title = "test",
body = dashboardBody(
fluidRow(
valueBoxOutput("vbox")
)
)
)
server = function(input, output) {
output$vbox <- renderValueBox({
valueBox(
value = 150,
subtitle = "New orders",
color = "primary",
icon = icon("shopping-cart"),
href = "#"
)
})
}
shinyApp(ui, server)This is an example taken once again from the official documentation from BS4Dash package. And as you can see we will create this time the value box in the server side. This is pretty similar to bslib. You can choose:
Value — the main metric
Subtitle — descriptive text
Color — theme color
Icon — visual element
Href — optional link
And this value box is simply rendered in the UI.
Let’s run this chunk of code and we will see how it looks like with BS4Dash. This is the value box with BS4Dash with the different parameters as we customized them.
Adding Spark Lines to bs4Dash Value Boxes
Now we want to add a spark line also which we customize just as we did with bslib. Let’s see how to do that now.
Once again I will reuse the code from the official documentation:
Enhanced bs4Dash UI with Spark Lines
ui <- dashboardPage(
header = dashboardHeader(),
sidebar = dashboardSidebar(),
controlbar = dashboardControlbar(),
footer = dashboardFooter(),
title = "bs4Dash value boxes",
body = bs4DashBody(
fluidRow(
valueBox(
value = 150,
subtitle = "New orders",
color = "primary",
icon = icon("cart-shopping")
),
valueBox(
value = "53%",
subtitle = "New orders",
color = "indigo",
icon = icon("gears"),
footer = plotlyOutput("salesSparkline", height = "50px"),
width = 4,
elevation = 4
),
valueBox(
value = "44",
subtitle = "User Registrations",
color = "teal",
icon = icon("sliders")
)
)
)
)As you can see it’s pretty similar, but this time we use the value box function directly in the UI. And for the second value box we will use this time the footer argument to create your interactive spark line once again using plotly output.
Customized Server Logic
If we go on the server side, this time I customized a bit the economics data set with some data wrangling to make it look better:
server <- function(input, output) {
output$salesSparkline <- renderPlotly({
econ_data <- economics %>%
tail(24) %>% # Using last 24 months for visualization
mutate(
month_name = format(date, "%b %Y"),
unemployment_millions = unemploy / 1000 # Convert to millions for cleaner display
)
plot_ly(
data = econ_data,
x = ~date,
y = ~unemployment_millions,
type = "scatter", mode = "lines",
line = list(color = "#ffffff", width = 2),
text = ~paste("Date:", month_name,
"<br>Unemployment:", round(unemployment_millions, 2), "M",
sep = ""),
hoverinfo = "text") %>%
layout(
paper_bgcolor = "rgba(0,0,0,0)",
plot_bgcolor = "rgba(0,0,0,0)",
margin = list(l = 0, r = 0, b = 0, t = 0, pad = 0),
xaxis = list(
showgrid = FALSE,
zeroline = FALSE,
showticklabels = FALSE,
title = "" # Removed x-axis title
),
yaxis = list(
showgrid = FALSE,
zeroline = FALSE,
showticklabels = FALSE,
title = "" # Removed y-axis title
),
showlegend = FALSE,
hovermode = "closest"
) %>%
config(displayModeBar = FALSE)
})
}
shinyApp(ui, server)And you can again fully customize your plot object. And you have the two arguments to customize the tool tip. And you can change this code as you want.
And once it’s done, you can simply run the UI, the server and once again shiny apps. And as we wanted, we have our value box with this interactive spark lines with a nice tooltip.
Conclusion
Value boxes are a powerful way to display key metrics and information in your R applications. Whether you’re using bslib for modern, customizable cards or bs4Dash for dashboard-style layouts, both packages offer extensive customization options.
Key Takeaways from This Tutorial:
Use the BSLib demo app to quickly prototype your value boxes
Integrate interactive spark lines using plotly for enhanced data visualization
Leverage the full-screen capability for detailed views
Choose between bslib and bs4Dash based on your application’s design requirements
Happy coding with R! 🚀


