Twitter Followers in an interactive HTML table

Author: Greg Lin - GitHub - LinkedIn
Table: Twitter Followers.
Repo: See the Twitter Followers vignette on the reactable package site.
Data: Source: FiveThirtyEight. Raw data: twitter_followers.csv .

The Twitter Followers demo is a re-creation of the table from the FiveThirtyEight article, Which 2020 Candidates Have The Most In Common … On Twitter?

It’s an interactive HTML table with sorting, data formatting, embedded bar charts, and custom styling. In this article, we’ll walk through how we made this table using reactable, and show a typical workflow for building tables.

This article on the reactable package website walks through in detail how the table is created. Including loading data and creating the basic table, adding horizontal bar charts, dynamic formatting, finishing touches for styling.


Code

library(reactable)
library(htmltools)
tbl <- reactable(
  data,
  pagination = FALSE,
  defaultSorted = "exclusive_followers_pct",
  defaultColDef = colDef(headerClass = "header", align = "left"),
  columns = list(
    account = colDef(
      cell = function(value) {
        url <- paste0("https://twitter.com/", value)
        tags$a(href = url, target = "_blank", paste0("@", value))
      },
      width = 150
    ),
    followers = colDef(
      defaultSortOrder = "desc",
      cell = function(value) {
        width <- paste0(value * 100 / max(data$followers), "%")
        value <- format(value, big.mark = ",")
        value <- format(value, width = 9, justify = "right")
        bar <- div(
          class = "bar-chart",
          style = list(marginRight = "6px"),
          div(class = "bar", style = list(width = width, backgroundColor = "#3fc1c9"))
        )
        div(class = "bar-cell", span(class = "number", value), bar)
      }
    ),
    exclusive_followers_pct = colDef(
      name = "Exclusive Followers",
      defaultSortOrder = "desc",
      cell = JS("function(cellInfo) {
        // Format as percentage
        const pct = (cellInfo.value * 100).toFixed(1) + '%'
        // Pad single-digit numbers
        let value = pct.padStart(5)
        // Show % on first row only
        if (cellInfo.viewIndex > 0) {
          value = value.replace('%', ' ')
        }
        // Render bar chart
        return (
          '<div class=\"bar-cell\">' +
            '<span class=\"number\">' + value + '</span>' +
            '<div class=\"bar-chart\" style=\"background-color: #e1e1e1\">' +
              '<div class=\"bar\" style=\"width: ' + pct + '; background-color: #fc5185\"></div>' +
            '</div>' +
          '</div>'
        )
      }"),
      html = TRUE
    )
  ),
  compact = TRUE,
  class = "followers-tbl"
)
# Add the title and subtitle
div(class = "twitter-followers",
    div(class = "followers-header",
        div(class = "followers-title", "Candidates whose followers are loyal only to them"),
        "Share of each 2020 candidate's followers who don't follow any other candidates"
    ),
    tbl
)
# Add Google Fonts to the page
tags$link(href = "https://fonts.googleapis.com/css?family=Karla:400,700|Fira+Mono&display=fallback",
          rel = "stylesheet")
/* CSS for the R Markdown document, inserted through a ```{css} code chunk */

/* Styles for the table container, title, and subtitle */
.twitter-followers {
  /* Center the table */
  margin: 0 auto;
  /* Reduce the table width */
  width: 575px;
  font-family: Karla, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

.followers-header {
  margin: 8px 0;
  font-size: 16px;
}

.followers-title {
  font-size: 20px;
  font-weight: 600;
}

/* Styles for the table */
.followers-tbl {
  font-size: 14px;
  line-height: 18px;
}

.followers-tbl a {
  color: inherit;
}

/* Styles for the column headers */
.header {
  border-bottom: 2px solid #555;
  font-size: 13px;
  font-weight: 400;
  text-transform: uppercase;
}

.header:hover {
  background-color: #eee;
}

/* Styles for the bar charts */
.bar-cell {
  display: flex;
  align-items: center;
}

.number {
  font-family: "Fira Mono", Consolas, Monaco, monospace;
  font-size: 13.5px;
  white-space: pre;
}

.bar-chart {
  flex-grow: 1;
  margin-left: 6px;
  height: 14px;
}

.bar {
  height: 100%;
}

reactable, single-table-example, interactive-html

1 Like