reactable icon indicating copy to clipboard operation
reactable copied to clipboard

Optionally wrap by colDef rather than globally

Open zac-garland opened this issue 5 years ago • 2 comments

Awesome package!! Have you considered text wrapping by colDef rather than defining it globally? or alternatively allowing both.

In the short example below, it would be nice to force the Judge names on one line, but have the rating col labels wrap. I know this could be accomplished by manually defining the minWidth,maxWidth, etc. but it would be nice to define it as a wrap boolean. Just a thought for consideration.

library(reactable)
library(tidyverse)

dat <- datasets::USJudgeRatings %>% setNames(c(
  "Number of contacts of lawyer with judge", "Judicial integrity",
  "Demeanor", "Diligence", "Case flow managing", "Prompt decisions",
  "Preparation for trial", "Familiarity with law", "Sound oral rulings",
  "Sound written rulings", "Physical ability", "Worthy of retention"
))

ramp <- scales::colour_ramp(c("red", "white", "blue"))

dat %>%
  rownames_to_column("Judge") %>%
  mutate_if(is.numeric, percent_rank) %>%
  reactable(defaultColDef = colDef(
    style = function(value) {
      color <- ramp(value)
      list(background = color)
    },
    format = colFormat(digits = 1),
    minWidth = 50
  ))

zac-garland avatar Aug 10 '20 17:08 zac-garland

Hi, thanks for the suggestion. I considered it originally, but wanted to wait to see if it was going to be common enough to use. Since then, I've seen a few examples where column-level wrapping would be useful, including this example, so it'll likely be added at some point.

For now, you can do it with a custom column style like white-space: nowrap; text-overflow: ellipsis;

# Wrap text in cells and display an ellipsis for clipped text
colDef(
  style = list(whiteSpace = "nowrap", textOverflow = "ellipsis")
)

# Same as above, but also wraps header text
colDef(
  style = list(whiteSpace = "nowrap", textOverflow = "ellipsis"),
  headerStyle = list(whiteSpace = "nowrap", textOverflow = "ellipsis")
)

If this is too tedious to write, you could create your own colDef() wrapper with a wrap boolean:

colDef <- function(..., wrap = FALSE, style = NULL, headerStyle = NULL) {
  if (wrap) {
    style <- c(style, list(whiteSpace = "nowrap", textOverflow = "ellipsis"))
    headerStyle <- c(headerStyle, list(whiteSpace = "nowrap", textOverflow = "ellipsis"))
  }
  reactable::colDef(..., style = style, headerStyle = headerStyle)
}

Then use it like this:

library(reactable)
library(tidyverse)

dat <- datasets::USJudgeRatings %>% setNames(c(
  "Number of contacts of lawyer with judge", "Judicial integrity",
  "Demeanor", "Diligence", "Case flow managing", "Prompt decisions",
  "Preparation for trial", "Familiarity with law", "Sound oral rulings",
  "Sound written rulings", "Physical ability", "Worthy of retention"
))

ramp <- scales::colour_ramp(c("red", "white", "blue"))

dat %>%
  rownames_to_column("Judge") %>%
  mutate_if(is.numeric, percent_rank) %>%
  reactable(
    defaultColDef = colDef(
      style = function(value) {
        color <- ramp(value)
        list(background = color)
      },
      format = colFormat(digits = 1),
      minWidth = 50
    ),
    columns = list(
      Judge = colDef(wrap = TRUE)
    )
  )

glin avatar Aug 16 '20 15:08 glin

That's a great suggestion @glin! I will use this method in the interim! Feel free to close, or leave open if you want a reminder. Thanks again for the awesome package!

zac-garland avatar Aug 16 '20 17:08 zac-garland