5

Using R's Reactable package and RMarkdown I want to create a table where a column has a green square for Status <= 2 and a red square otherwise.

If I try to format the Status column based on it's value, it creates a non-colored square. See image.

enter image description here

In the .Rmd file below, I can get the css to make a colored square in a column only if the column has no values.

To summarize, under the Status column, I'd like colored squares (green square for Status <= 2 and a red square otherwise) with no visible numbers, left aligned with the Status name of the column.

The Flag column is there just to show that the css is working.

RMarkdown File

title: Conditional Colored Square in Reactable Table
author: IX
date: 'September 5, 2020'
slug: test
categories: []
tags: []
output: 
  html_document
---

```{css, echo=FALSE}
 .row {
    display : flex;
    align-items : center;
    margin-bottom: 15px;
  }
.box {
  height: 20px;
  width: 20px;
  border: 1px solid black;
  margin-right : 5px;
}

.red {
  background-color: red;
}

.green {
  background-color: green;
}

.blue {
  background-color: blue;
}
```



```{r, echo=FALSE, message=FALSE, warning=FALSE}
library("reactable")

orders <- data.frame(
  Order = 2300:2304,
  Created = seq(as.Date("2019-04-01"), by = "day", length.out = 5),
  Customer = sample(rownames(MASS::painters), 5),
  Status = c(1, 2, 3, 4, 5),
  Flag = c("", "", "", "", "")
)

reactable(orders, columns = list(
  Status = colDef(cell = function(value) {
    if (value <= 2) {
      class <- paste0("tag box green", tolower(value))
      htmltools::div(class = class, value)
    }
  }),
  Flag = colDef(cell = function(value) {
    class <- paste0("tag box green", tolower(value))
    htmltools::div(class = class, value)
  })  
))
ixodid
  • 2,180
  • 1
  • 19
  • 46

1 Answers1

2

Using css is the right way to go.

The color doesn't appear in the example you provided because of the paste:

class <- paste0("tag box green", tolower(value))

which results in green1, green2, ... that are undefined selector classes.

Try:

---
title: Conditional Colored Square in Reactable Table
author: IX
date: 'September 5, 2020'
slug: test
categories: []
tags: []
output: 
  html_document
---

```{css, echo=FALSE}
.row {
    display : flex;
    align-items : center;
    margin-bottom: 15px;
  }
.box {
  height: 20px;
  width: 20px;
  border: 1px solid black;
  margin-right : 5px;
}


.green {
  background: green;
  color: green;
}

.red {
  background-color: red;
  color: red;
}
```



```{r, echo=FALSE, message=FALSE, warning=FALSE}
library("reactable")

orders <- data.frame(
  Order = 2300:2304,
  Created = seq(as.Date("2019-04-01"), by = "day", length.out = 5),
  Customer = sample(rownames(MASS::painters), 5),
  Status = c(1, 2, 3, 4, 5),
  Flag =  c("", "", "","","")
)

reactable(orders, columns = list(
  Status = colDef(cell = function(value) {
    if (value <= 2) {
      class <- "box green"
    } else {
      class <- "box red"
    }
    htmltools::div(class = class, "")  
  }),
  Flag = colDef(cell = function(value) {
      class <- paste0("tag box")
      htmltools::div(class = class, value)
  })  
))

enter image description here

Waldi
  • 39,242
  • 6
  • 30
  • 78
  • Does this: htmltools::div(class = class, "#") replace the number in the Status column with a colored "#" character which is not readily visible because the background is the same color? Is it possible to do this without a hidden character as I demonstrated in the Flag column? Also, the colored squares should be squares, not rounded rectangles. – ixodid Sep 09 '20 at 17:55
  • I found the rounded squares neat, but you can remove them by setting `border-radius` of `.tag`to 1px or even 0. '#' is the placeholder and could be any character (but not space), it disappears in the background color. A character has the advantage of easily centering under Status. – Waldi Sep 09 '20 at 18:14
  • see my edit with both solutions : hidden character or box – Waldi Sep 09 '20 at 18:29