Embedding videos in {reactable} tables

tables data visualization

Pushing the limits of expandable row details

June Choe (University of Pennsylvania Linguistics)https://live-sas-www-ling.pantheon.sas.upenn.edu/
09-12-2020

In a {reactable} table, you can have a row expand to reveal more details by supplying the details argument with a function returning an image, raw html, another reactable table, etc. There are many examples of this in the package vignette, and they give you a good sense of just how flexible and powerful this feature is.

My first reaction to this was that it seemed like just about anything that can be displayed on a web page can be embedded in the expandable details. So what about something very unusual like… videos? Can {reactable} handle it? Are there potential usecases of this?

Annotated #tidytuesday screencasts

While entertaining this idea, I remembered coming across a tweet by Alex Cookson with a link to a very detailed spreadsheet containing timestamped notes of David Robinson’s live #tidytuesday screencasts.

Anyone other #rstats people find @drob's #TidyTuesday screencasts useful?

I made a spreadsheet with timestamps for hundreds of specific tasks he does: https://t.co/HvJbLk1chd

Useful if, like me, you keep going back and ask, “Where in the video did he do [this thing] again?”

— Alex Cookson (@alexcookson) January 13, 2020

So I turned the spreadsheet into a {reactable} table with rows that can expand to reveal a Youtube video at the timestamp. I actually think this makes a really cool use case - it’s easier here than in Google Spreadsheet to navigate around the table with pagination and search bar, and you don’t need to constantly open and close Youtube videos in new windows (in fact, you can keep multiple videos open across rows here!).

Try it out for yourself!

Code

library(tidyverse)
library(htmltools)
library(reactable)

# David Robinson's (@drob) #tidytuesday screencast annotations, made by Alex Cookson (@alexcookson)
screencasts <-
  gsheet::gsheet2tbl("docs.google.com/spreadsheets/d/1pjj_G9ncJZPGTYPkR1BYwzA6bhJoeTfY2fJeGKSbOKM") %>% 
  select(Screencast, Date, Timestamp = `Timestamp (sec)`, Link:Functions) %>% 
  mutate(Link = str_extract(Link, "(?<=v=).*(?=&)"))


###############
## The Table ##
###############

reactable(screencasts,
  
  # Function to embed Youtube Video 
  details = function(index){
    
    # Grab video info from hidden columns
    link <- screencasts$Link[index]
    time <- screencasts$Timestamp[index]
    
    # Div container to add grey padding around the video
    tags$div(style = "text-align:center; padding:10px; background:grey",
             
             # The actual video
             tags$iframe(
               height = "640", width = "640", allow = "fullscreen",
               src = glue::glue("https://www.youtube.com/embed/{link}?start={time}&autoplay=1")
             )
             
    )
    
  },
  
  # Column options
  columns = list(
    Link = colDef(show = F),
    Timestamp = colDef(show = F),
    Description = colDef(width = 500)
  ),
  
  # Some theme options
  searchable = TRUE,
  bordered = TRUE,
  fullWidth = TRUE,
  theme = reactableTheme(
    style = list(fontSize = '14px'),
    searchInputStyle = list(width = "100%")
  ),
  
)