Interactive table made in R
with
reactable
that has labels, images and
charts.
This blogpost guides you through the construction of this table made
by szymanskir.
This page showcases the work of
szymanskir that introduces
packages to make
ggplot2
plots more beautiful. You can find the original code and where the
data are from on
this repo.
Letβs start by loading the packages needed to build the table:
Todayβs data can be easily accessed on the github of the gallery by using the following code:
# REMOVE WHEN MERGING
# url = 'https://raw.githubusercontent.com/holtzy/R-graph-gallery/master/DATA/tidyverse-packages.RDS'
# data_table <- readRDS(url)
data_table <- readRDS("DATA/tidyverse-packages.RDS")
The table mainly relies on the
reactable
package and some cool html/css/javascript
features.
First, we need to define a few functions.
create_history_download_chart()
: creates an interactive
line chart using the echarts4r
package,
displaying download history data. It sets up the
chart with customized dimensions, hides the legend and y-axis, and
includes a tooltip feature that shows formatted information about
the downloads when the user hovers over the chart
points.
create_history_download_chart <- function(downloads_data) {
echarts4r::e_chart(downloads_data, x = start, height = "80px", width = "256px") %>%
echarts4r::e_line(downloads, symbol = "none") %>%
echarts4r::e_legend(show = FALSE) %>%
echarts4r::e_axis(axis = "y", show = FALSE) %>%
echarts4r::e_tooltip(
trigger = "axis",
# Creates custom tooltip content
formatter = htmlwidgets::JS("
function(params) {
const downloadsDate = params[0].value[0];
const downloadsDateLabel = new Date(downloadsDate).
toLocaleString('en-Us', { month: 'short', year: 'numeric' });
const downloadsCount = params[0].value[1];
const downloadsCountLabel = echarts.format.addCommas(params[0].value[1]);
return `
${downloadsDateLabel}
<br/>
${downloadsCountLabel}
`;
}
")
) %>%
# Prevents the plot toolitp from being hidden in case
# it goes over the table boundaries
htmlwidgets::onRender(
htmlwidgets::JS("
function(el, x) {
el.parentElement.style.overflow = 'visible';
}
")
)
}
number_value_icon_cell()
: creates a cell for a web page
that contains an icon and a number. It uses HTML
and
CSS
to position the icon (defined by the icon argument)
to the left of the number (defined by the value argument), ensuring
the icon is neatly aligned and sized correctly.
number_value_icon_cell <- function(value, icon) {
htmltools::div(
style = "
display: flex;
justify-content: flex-end
",
htmltools::img(
src = knitr::image_uri(icon),
height = "24px",
width = "24px",
style = "
vertical-align: bottom;
margin-right: 4px;
"
),
value
)
}
create_table()
:
Table Creation: The function takes a dataset (all_data) and creates an interactive table using reactable::reactable. This table will display various information about software packages.
Column Customization:
Styling and Layout: The table uses custom styling for headers and cells, including center alignment, font customization, and layout adjustments. It employs CSS for additional effects like hover transitions on contributor avatars and links. Additional Features:
Custom CSS styles are included to enhance interactivity, like hover effects on contributor avatars and repository URLs.
create_table <- function(all_data) {
table <- reactable::reactable(
all_data,
defaultColDef = reactable::colDef(
headerStyle = "text-align: center"
),
columns = list(
hex_sticker = reactable::colDef(
name = "",
cell = function(value, row_index) {
row_data <- all_data[row_index, ]
# Display Hex along with title and
# repository description
htmltools::div(
style = "
display: flex;
align-items: center;
",
htmltools::div(
htmltools::img(
src = value,
alt = glue::glue("Hex sticker of {row_data$package_name}"),
height = "80px"
)
),
htmltools::div(
style = "
margin-left: 24px
",
htmltools::div(
style = "
font-weight: 700;
",
htmltools::a(
style = "
color: #38577f;
",
class = "package_repo_url",
href = row_data$repo_url,
target = "_blank",
row_data$package_name
),
),
htmltools::div(
style = "
font-size: 14px;
font-style: italic;
color: hsl(201, 23%, 34%);
line-height: 20px
",
row_data$description
)
)
)
},
width = 384
),
# Hide unused columns
repo_url = reactable::colDef(show = FALSE),
package_name = reactable::colDef(show = FALSE),
description = reactable::colDef(show = FALSE),
# Render repo stats in form of <ICON> <NUMBER>
stargazers = reactable::colDef(
name = "Stargazers",
cell = function(value) {
number_value_icon_cell(value, "img/graph/star.svg")
},
width = 112
),
watchers = reactable::colDef(
name = "Watchers",
cell = function(value) {
number_value_icon_cell(value, "img/graph/eye.svg")
},
width = 112
),
tags = reactable::colDef(
name = "Tags",
cell = function(value) {
number_value_icon_cell(value, "img/graph/tag.svg")
},
width = 80
),
download_stats = reactable::colDef(
name = "Monthly Downloads",
cell = function(value) {
create_history_download_chart(value)
},
width = 256,
style = "overflow: visible;"
),
# Display contributor avatars as image bubbles
top_5_contributors = reactable::colDef(
name = "Top Five Contributors",
cell = function(value) {
htmltools::div(
purrr::map(
value,
~htmltools::span(
htmltools::img(
src = .x$avatar_url,
alt = glue::glue("GitHub avatar of {.x$login}"),
class = "contributor",
height = "44px",
style = "
border-radius: 100%;
box-shadow: rgba(27, 31, 36, 0.15) 0px 0px 0px 1px
"
) %>% htmltools::a(href = .x$html_url, target="_blank") %>%
htmltools::tags$abbr(title = .x$login)
)
)
)
},
width = 256
)
),
# Center Vertically the content of each column
# and use custom font
theme = reactable::reactableTheme(
cellStyle = list(
display = "flex",
flexDirection = "column",
justifyContent = "center"
),
style = list(
fontFamily = "Lato, sans-serif"
)
),
fullWidth = FALSE,
sortable = FALSE
) %>%
# Add titleto the table
htmlwidgets::prependContent(
htmltools::div(
style = "
width: 1200px;
",
htmltools::div("Tidyverse in Numbers",
style = "padding: 0px 4px; font-size: 28px; font-weight: 700; font-family: Lato, sans-serif;")
)
)
# Include custom styling as it's impossible to
# use the :hover in inline CSS
htmltools::browsable(htmltools::tagList(
htmltools::tags$head(
htmltools::tags$style("
.contributor {
margin: 0px 2px;
transition: all 0.2s ease-in-out;
}
.contributor:hover {
transform: translateY(-6px);
transition: all 0.2s ease-in-out;
}
.package_repo_url {
text-decoration: none;
}
.package_repo_url:hover {
text-decoration: underline;
}
")
),
return(table)
))
}
Now we just have to create the table thanks to our functions:
This post explains how to reproduce an interactive table built with
reactable
by szymanskir. The table
has very nice features such as images when CSS
features,
interactive charts and statistics.
If you want to learn more about reactable
, check out the
dedicated section. Check also the
table section
π After crafting hundreds of R charts over 12 years, I've distilled my top 10 tips and tricks. Receive them via email! One insight per day for the next 10 days! π₯